ooxml-excel-editor 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/CHANGELOG.md +95 -0
  2. package/LICENSE +21 -0
  3. package/README.md +516 -0
  4. package/dist/chunks/plugin-overlay-Cfnn9EOi.js +7144 -0
  5. package/dist/chunks/worker-client.stub-BQVZfaLd.js +7 -0
  6. package/dist/components/ActionToolbar.vue.d.ts +9 -0
  7. package/dist/components/ExcelViewer.vue.d.ts +283 -0
  8. package/dist/components/ExportDialog.vue.d.ts +14 -0
  9. package/dist/components/FilterPopup.vue.d.ts +21 -0
  10. package/dist/components/FindBar.vue.d.ts +27 -0
  11. package/dist/components/SheetTabs.vue.d.ts +11 -0
  12. package/dist/components/ToolbarMenu.vue.d.ts +10 -0
  13. package/dist/components/ViewerToolbar.vue.d.ts +21 -0
  14. package/dist/components/export-types.d.ts +14 -0
  15. package/dist/components/toolbar-icons.d.ts +7 -0
  16. package/dist/components/toolbar-types.d.ts +18 -0
  17. package/dist/composables/useExcelDocument.d.ts +17 -0
  18. package/dist/composables/worker-client.d.ts +3 -0
  19. package/dist/composables/worker-client.stub.d.ts +3 -0
  20. package/dist/core/edit/commands.d.ts +94 -0
  21. package/dist/core/edit/default-editor.d.ts +2 -0
  22. package/dist/core/edit/edit-controller.d.ts +137 -0
  23. package/dist/core/edit/editor-context.d.ts +40 -0
  24. package/dist/core/edit/editor-host.d.ts +22 -0
  25. package/dist/core/edit/permissions.d.ts +3 -0
  26. package/dist/core/edit/types.d.ts +23 -0
  27. package/dist/core/export/composite.d.ts +18 -0
  28. package/dist/core/export/data-export.d.ts +9 -0
  29. package/dist/core/export/exporter.d.ts +64 -0
  30. package/dist/core/export/index.d.ts +9 -0
  31. package/dist/core/export/paginate.d.ts +36 -0
  32. package/dist/core/export/pdf.d.ts +28 -0
  33. package/dist/core/export/print.d.ts +3 -0
  34. package/dist/core/export/raster.d.ts +13 -0
  35. package/dist/core/export/types.d.ts +92 -0
  36. package/dist/core/export/vector-pdf.d.ts +42 -0
  37. package/dist/core/export/xlsx-writer.d.ts +15 -0
  38. package/dist/core/finalize.d.ts +10 -0
  39. package/dist/core/format/builtin-formats.d.ts +7 -0
  40. package/dist/core/format/color.d.ts +11 -0
  41. package/dist/core/format/date-serial.d.ts +16 -0
  42. package/dist/core/format/number-format.d.ts +5 -0
  43. package/dist/core/formula/engine.d.ts +27 -0
  44. package/dist/core/formula/hyperformula-adapter.d.ts +3 -0
  45. package/dist/core/formula/recalc.d.ts +9 -0
  46. package/dist/core/formula/refs.d.ts +21 -0
  47. package/dist/core/index.d.ts +52 -0
  48. package/dist/core/layout/autofit.d.ts +2 -0
  49. package/dist/core/layout/freeze.d.ts +11 -0
  50. package/dist/core/layout/grid-metrics.d.ts +37 -0
  51. package/dist/core/layout/merges.d.ts +14 -0
  52. package/dist/core/layout/units.d.ts +20 -0
  53. package/dist/core/layout/viewport.d.ts +29 -0
  54. package/dist/core/loader.d.ts +5 -0
  55. package/dist/core/model/clone.d.ts +9 -0
  56. package/dist/core/model/data-access.d.ts +30 -0
  57. package/dist/core/model/mutations.d.ts +46 -0
  58. package/dist/core/model/snapshot.d.ts +14 -0
  59. package/dist/core/model/structure.d.ts +26 -0
  60. package/dist/core/model/types.d.ts +289 -0
  61. package/dist/core/overlay/anchor.d.ts +9 -0
  62. package/dist/core/overlay/chart-mapper.d.ts +3 -0
  63. package/dist/core/overlay/echarts-loader.d.ts +3 -0
  64. package/dist/core/parse.worker.d.ts +14 -0
  65. package/dist/core/parser/chart-parser.d.ts +3 -0
  66. package/dist/core/parser/drawing-parser.d.ts +3 -0
  67. package/dist/core/parser/exceljs-adapter.d.ts +8 -0
  68. package/dist/core/parser/index.d.ts +3 -0
  69. package/dist/core/parser/page-break-parser.d.ts +3 -0
  70. package/dist/core/parser/raw-xml.d.ts +15 -0
  71. package/dist/core/parser/sparkline-parser.d.ts +3 -0
  72. package/dist/core/parser/theme.d.ts +3 -0
  73. package/dist/core/plugin.d.ts +180 -0
  74. package/dist/core/progress.d.ts +7 -0
  75. package/dist/core/render/autofilter.d.ts +14 -0
  76. package/dist/core/render/borders.d.ts +13 -0
  77. package/dist/core/render/canvas-renderer.d.ts +225 -0
  78. package/dist/core/render/conditional.d.ts +25 -0
  79. package/dist/core/render/fills.d.ts +2 -0
  80. package/dist/core/render/text.d.ts +20 -0
  81. package/dist/core/render/theme.d.ts +19 -0
  82. package/dist/core/viewer/controller.d.ts +339 -0
  83. package/dist/core/viewer/overlay-manager.d.ts +27 -0
  84. package/dist/core/viewer/plugin-overlay.d.ts +8 -0
  85. package/dist/core.d.ts +2 -0
  86. package/dist/core.js +74 -0
  87. package/dist/demo-shared/demo-editor.d.ts +2 -0
  88. package/dist/index.d.ts +19 -0
  89. package/dist/index.js +1493 -0
  90. package/dist/react/ExcelViewer.d.ts +153 -0
  91. package/dist/react/index.d.ts +11 -0
  92. package/dist/react/use-excel-document.d.ts +17 -0
  93. package/dist/react.d.ts +2 -0
  94. package/dist/react.js +838 -0
  95. package/dist/style.css +1 -0
  96. package/package.json +117 -0
@@ -0,0 +1,289 @@
1
+ /**
2
+ * 中间数据模型 —— 渲染层只认这套类型,与 ExcelJS / 原始 XML 形状完全解耦。
3
+ * 将来要换解析库或换 DOM 渲染,只要保证产出/消费这套模型即可。
4
+ */
5
+ /** RGB(A) 颜色,统一成 css 可用字符串(如 "#RRGGBB" / "rgba(...)")。 */
6
+ export type CssColor = string;
7
+ /** 水平对齐 */
8
+ export type HAlign = 'left' | 'center' | 'right' | 'fill' | 'justify' | 'general';
9
+ /** 垂直对齐 */
10
+ export type VAlign = 'top' | 'middle' | 'bottom';
11
+ /** 单个边框边的样式 */
12
+ export interface BorderEdge {
13
+ style: BorderStyle;
14
+ color: CssColor;
15
+ }
16
+ export type BorderStyle = 'none' | 'thin' | 'medium' | 'thick' | 'dashed' | 'dotted' | 'double' | 'hair' | 'mediumDashed' | 'dashDot' | 'mediumDashDot' | 'dashDotDot' | 'mediumDashDotDot' | 'slantDashDot';
17
+ export interface Borders {
18
+ top?: BorderEdge;
19
+ bottom?: BorderEdge;
20
+ left?: BorderEdge;
21
+ right?: BorderEdge;
22
+ /** 对角线边框样式(up/down 共用此线型与颜色) */
23
+ diagonal?: BorderEdge;
24
+ /** ↗ 左下→右上 对角线 */
25
+ diagonalUp?: boolean;
26
+ /** ↘ 左上→右下 对角线 */
27
+ diagonalDown?: boolean;
28
+ }
29
+ export interface Font {
30
+ name: string;
31
+ size: number;
32
+ bold: boolean;
33
+ italic: boolean;
34
+ underline: boolean;
35
+ strike: boolean;
36
+ color: CssColor;
37
+ }
38
+ export type FillType = 'none' | 'solid' | 'pattern' | 'gradient';
39
+ export interface Fill {
40
+ type: FillType;
41
+ /** solid / pattern 前景色;gradient 时为第一个 stop */
42
+ fgColor?: CssColor;
43
+ bgColor?: CssColor;
44
+ pattern?: string;
45
+ /** 渐变色标(可选,简化版) */
46
+ gradientStops?: {
47
+ position: number;
48
+ color: CssColor;
49
+ }[];
50
+ gradientAngle?: number;
51
+ }
52
+ export interface CellStyle {
53
+ font: Font;
54
+ fill: Fill;
55
+ borders: Borders;
56
+ hAlign: HAlign;
57
+ vAlign: VAlign;
58
+ wrapText: boolean;
59
+ shrinkToFit: boolean;
60
+ /** 文本旋转角度(度),Excel 范围 -90..90,255 表示竖排 */
61
+ textRotation: number;
62
+ indent: number;
63
+ /** 数字格式代码字符串(已从 numFmtId 解析为 code) */
64
+ numFmt: string;
65
+ }
66
+ /** 单元格的逻辑值类型 */
67
+ export type CellValueType = 'empty' | 'number' | 'string' | 'boolean' | 'date' | 'error' | 'hyperlink' | 'richtext' | 'formula';
68
+ export interface RichTextRun {
69
+ text: string;
70
+ font?: Partial<Font>;
71
+ }
72
+ export interface CellModel {
73
+ row: number;
74
+ col: number;
75
+ type: CellValueType;
76
+ /** 原始值: number / string / boolean / Date / error 字符串 */
77
+ raw: number | string | boolean | Date | null;
78
+ /** 富文本分段(type === 'richtext' 时有) */
79
+ rich?: RichTextRun[];
80
+ /** 公式文本(type === 'formula' 时有;显示用 raw 缓存值) */
81
+ formula?: string;
82
+ /** 超链接目标 */
83
+ hyperlink?: string;
84
+ /** 单元格批注(纯文本) */
85
+ comment?: string;
86
+ /** 样式索引,指向 SheetModel.styles */
87
+ styleId: number;
88
+ }
89
+ /** 合并区域(0-based,闭区间) */
90
+ export interface MergeRange {
91
+ top: number;
92
+ left: number;
93
+ bottom: number;
94
+ right: number;
95
+ }
96
+ export interface ColumnInfo {
97
+ /** 列宽,单位 = px(已从字符数换算) */
98
+ width: number;
99
+ hidden: boolean;
100
+ }
101
+ export interface RowInfo {
102
+ /** 行高,单位 = px(已从 pt 换算) */
103
+ height: number;
104
+ hidden: boolean;
105
+ }
106
+ /** 冻结窗格: 冻结前 frozenRows 行 / frozenCols 列 */
107
+ export interface FreezeInfo {
108
+ frozenRows: number;
109
+ frozenCols: number;
110
+ }
111
+ /** 条件格式规则(简化版,覆盖常见 4 类) */
112
+ export interface ConditionalRule {
113
+ ranges: MergeRange[];
114
+ priority: number;
115
+ type: 'cellIs' | 'colorScale' | 'dataBar' | 'iconSet' | 'expression' | 'top10' | 'unsupported';
116
+ /** cellIs */
117
+ operator?: string;
118
+ formulae?: string[];
119
+ /** 命中时套用的样式(cellIs / expression) */
120
+ style?: Partial<CellStyle>;
121
+ /** colorScale: 2~3 个色标 */
122
+ colorScale?: {
123
+ min: CssColor;
124
+ mid?: CssColor;
125
+ max: CssColor;
126
+ };
127
+ /** dataBar */
128
+ dataBar?: {
129
+ color: CssColor;
130
+ gradient: boolean;
131
+ };
132
+ /** iconSet */
133
+ iconSet?: {
134
+ name: string;
135
+ };
136
+ }
137
+ /** 图片锚定(像素矩形由 layout 阶段最终算出,这里给逻辑锚点) */
138
+ export interface ImageAnchor {
139
+ /** blob url(由主线程从 bytes 生成;解析阶段为空) */
140
+ src: string;
141
+ /** 原始图片字节 + mime(解析层产出,可跨 Worker 传输) */
142
+ bytes?: Uint8Array;
143
+ mime?: string;
144
+ /** twoCellAnchor: from/to 单元格 + 单元格内偏移(EMU) */
145
+ from: AnchorCell;
146
+ to?: AnchorCell;
147
+ /** oneCellAnchor / absolute 的尺寸(EMU) */
148
+ extWidthEmu?: number;
149
+ extHeightEmu?: number;
150
+ editAs?: string;
151
+ }
152
+ export interface AnchorCell {
153
+ col: number;
154
+ colOffEmu: number;
155
+ row: number;
156
+ rowOffEmu: number;
157
+ }
158
+ /** 图表规格(从 chartN.xml 抽出,交给 ECharts 映射) */
159
+ export interface ChartSpec {
160
+ type: 'bar' | 'line' | 'pie' | 'area' | 'scatter' | 'doughnut' | 'radar' | 'unsupported';
161
+ title?: string;
162
+ showLegend: boolean;
163
+ barDirection?: 'col' | 'bar';
164
+ categories: (string | number)[];
165
+ series: ChartSeries[];
166
+ anchor: ImageAnchor;
167
+ }
168
+ export interface ChartSeries {
169
+ name?: string;
170
+ values: (number | null)[];
171
+ color?: CssColor;
172
+ }
173
+ export interface SheetModel {
174
+ name: string;
175
+ index: number;
176
+ state: 'visible' | 'hidden' | 'veryHidden';
177
+ /** 实际数据范围 */
178
+ dimension: {
179
+ rows: number;
180
+ cols: number;
181
+ };
182
+ /** 稀疏存储: key = `${row}:${col}` */
183
+ cells: Map<string, CellModel>;
184
+ /** 样式表,CellModel.styleId 索引 */
185
+ styles: CellStyle[];
186
+ merges: MergeRange[];
187
+ columns: Map<number, ColumnInfo>;
188
+ rows: Map<number, RowInfo>;
189
+ defaultColWidth: number;
190
+ defaultRowHeight: number;
191
+ freeze: FreezeInfo;
192
+ conditional: ConditionalRule[];
193
+ /** 自动筛选区域(画下拉按钮用) */
194
+ autoFilterRange?: MergeRange;
195
+ /** 含"列表"型数据验证的区域(选中时画下拉箭头) */
196
+ dataValidations: MergeRange[];
197
+ images: ImageAnchor[];
198
+ charts: ChartSpec[];
199
+ /** 形状 / 文本框(DrawingML sp) */
200
+ shapes: ShapeSpec[];
201
+ /** 迷你图(单元格内嵌折线/柱/盈亏图) */
202
+ sparklines: Sparkline[];
203
+ /** 手动分页符(0-based 边界索引): 在这些行上方/列左侧画分页虚线 */
204
+ pageBreaks?: {
205
+ rows: number[];
206
+ cols: number[];
207
+ };
208
+ /** 原生页面设置(打印/导出默认值来源);缺省走 export 模块默认 */
209
+ pageSetup?: PageSetupModel;
210
+ showGridLines: boolean;
211
+ }
212
+ /** OOXML 原生页面设置(pageSetup + pageMargins + 打印区域/标题),用作导出默认值 */
213
+ export interface PageSetupModel {
214
+ orientation?: 'portrait' | 'landscape';
215
+ /** 纸张: 由 paperSize 代码映射;无法识别时省略(走默认 a4) */
216
+ paperFormat?: 'a4' | 'a3' | 'letter' | [number, number];
217
+ /** 缩放百分比(如 80 = 80%);fitToPage 时无意义 */
218
+ scale?: number;
219
+ /** 适应页面(fitToPage): 优先于 scale */
220
+ fitToPage?: boolean;
221
+ fitToWidth?: number;
222
+ fitToHeight?: number;
223
+ /** 页边距 mm(从 inch 换算) */
224
+ margins?: {
225
+ top: number;
226
+ right: number;
227
+ bottom: number;
228
+ left: number;
229
+ header: number;
230
+ footer: number;
231
+ };
232
+ /** 打印区域(0-based 闭区间;多区域取第一段) */
233
+ printArea?: MergeRange;
234
+ /** 打印标题行 [r0,r1] 0-based(每页顶部重复) */
235
+ printTitleRows?: [number, number];
236
+ /** 打印标题列 [c0,c1] 0-based(横向分页时左侧重复;当前竖向分页管线不应用) */
237
+ printTitleCols?: [number, number];
238
+ }
239
+ /** 形状 / 文本框: 用锚点定位,带填充/边框/文字 */
240
+ export interface ShapeSpec {
241
+ anchor: ImageAnchor;
242
+ /** 形状类型(prstGeom): rect / roundRect / ellipse / 其它(按 rect 处理) */
243
+ geom: 'rect' | 'roundRect' | 'ellipse' | 'other';
244
+ text?: string;
245
+ fillColor?: CssColor;
246
+ lineColor?: CssColor;
247
+ textColor?: CssColor;
248
+ bold?: boolean;
249
+ /** 文本水平对齐 */
250
+ align?: 'left' | 'center' | 'right';
251
+ }
252
+ /** 迷你图: 锚在某个单元格,数据来自一段区域的数值 */
253
+ export interface Sparkline {
254
+ row: number;
255
+ col: number;
256
+ type: 'line' | 'column' | 'winloss';
257
+ values: (number | null)[];
258
+ /** 主色(可选,缺省用默认蓝) */
259
+ color?: CssColor;
260
+ negativeColor?: CssColor;
261
+ }
262
+ export interface WorkbookModel {
263
+ sheets: SheetModel[];
264
+ activeSheet: number;
265
+ /** 主题色调色板(theme1.xml 解析所得,索引同 ECMA dk1/lt1/dk2/lt2/accent1..6/hlink/folHlink) */
266
+ themeColors: CssColor[];
267
+ date1904: boolean;
268
+ }
269
+ export declare const cellKey: (row: number, col: number) => string;
270
+ /** 数据钩子: 解析后、渲染前改模型(返回新模型或就地改) */
271
+ export type TransformModelFn = (workbook: WorkbookModel) => WorkbookModel | void;
272
+ /** 单元格样式覆盖(各字段可选;font/fill/borders 允许部分,与解析样式浅合并) */
273
+ export interface CellStyleOverride {
274
+ font?: Partial<Font>;
275
+ fill?: Partial<Fill>;
276
+ borders?: Partial<Borders>;
277
+ hAlign?: HAlign;
278
+ vAlign?: VAlign;
279
+ wrapText?: boolean;
280
+ shrinkToFit?: boolean;
281
+ textRotation?: number;
282
+ indent?: number;
283
+ numFmt?: string;
284
+ }
285
+ /** 渲染钩子: 按单元格覆盖样式(返回部分样式,与解析样式合并) */
286
+ export type CellStyleFn = (cell: CellModel, pos: {
287
+ row: number;
288
+ col: number;
289
+ }) => CellStyleOverride | void;
@@ -0,0 +1,9 @@
1
+ import { ImageAnchor } from '../model/types';
2
+ import { GridMetrics } from '../layout/grid-metrics';
3
+ export interface ContentRect {
4
+ left: number;
5
+ top: number;
6
+ width: number;
7
+ height: number;
8
+ }
9
+ export declare function anchorRect(metrics: GridMetrics, anchor: ImageAnchor): ContentRect;
@@ -0,0 +1,3 @@
1
+ import { ChartSpec } from '../model/types';
2
+ import { EChartsOption } from 'echarts';
3
+ export declare function chartToOption(spec: ChartSpec): EChartsOption;
@@ -0,0 +1,3 @@
1
+ /** echarts 按需加载(可选 peer 依赖)。共享给 OverlayManager 与导出图表栅格化。 */
2
+ import type * as EChartsNS from 'echarts';
3
+ export declare function loadECharts(): Promise<typeof EChartsNS>;
@@ -0,0 +1,14 @@
1
+ import { WorkbookModel } from './model/types';
2
+ import { ParseProgress } from './progress';
3
+ export type WorkerMsg = {
4
+ type: 'progress';
5
+ progress: ParseProgress;
6
+ } | {
7
+ type: 'done';
8
+ ok: true;
9
+ model: WorkbookModel;
10
+ } | {
11
+ type: 'done';
12
+ ok: false;
13
+ error: string;
14
+ };
@@ -0,0 +1,3 @@
1
+ import { RawPackage } from './raw-xml';
2
+ import { ChartSpec } from '../model/types';
3
+ export declare function parseChart(pkg: RawPackage, chartPath: string): Omit<ChartSpec, 'anchor'> | undefined;
@@ -0,0 +1,3 @@
1
+ import { RawPackage } from './raw-xml';
2
+ import { SheetModel } from '../model/types';
3
+ export declare function attachDrawings(pkg: RawPackage, sheets: SheetModel[]): void;
@@ -0,0 +1,8 @@
1
+ import { default as ExcelJS } from 'exceljs';
2
+ import { MergeRange, PageSetupModel, SheetModel, CssColor } from '../model/types';
3
+ import { ProgressFn } from '../progress';
4
+ export declare function buildSheets(wb: ExcelJS.Workbook, themeColors: CssColor[], onProgress?: ProgressFn): SheetModel[];
5
+ /** 从 ExcelJS worksheet.pageSetup 抽出原生页面设置;失败返回 undefined。(导出供单测) */
6
+ export declare function parsePageSetup(ws: ExcelJS.Worksheet): PageSetupModel | undefined;
7
+ export declare function colLettersToIndex(letters: string): number;
8
+ export declare function parseA1Range(range: string): MergeRange | null;
@@ -0,0 +1,3 @@
1
+ import { WorkbookModel } from '../model/types';
2
+ import { ProgressFn } from '../progress';
3
+ export declare function parseWorkbook(buffer: ArrayBuffer, onProgress?: ProgressFn): Promise<WorkbookModel>;
@@ -0,0 +1,3 @@
1
+ import { RawPackage } from './raw-xml';
2
+ import { SheetModel } from '../model/types';
3
+ export declare function attachPageBreaks(pkg: RawPackage, sheets: SheetModel[]): void;
@@ -0,0 +1,15 @@
1
+ export interface RawPackage {
2
+ files: Record<string, Uint8Array>;
3
+ parse(path: string): any | undefined;
4
+ text(path: string): string | undefined;
5
+ bytes(path: string): Uint8Array | undefined;
6
+ list(prefix: string): string[];
7
+ }
8
+ export declare function openPackage(buffer: ArrayBuffer): RawPackage;
9
+ /** 解析 part 的 .rels,返回 r:id → target(相对该 part 目录解析后的绝对包内路径) */
10
+ export declare function parseRels(pkg: RawPackage, partPath: string): Record<string, string>;
11
+ export declare function basename(p: string): string;
12
+ /** 相对 baseDir 解析 target(支持 ../) → 包内绝对路径(无前导 /) */
13
+ export declare function resolvePath(baseDir: string, target: string): string;
14
+ /** fast-xml-parser 对单元素/多元素返回 object/array 不一致,统一成数组 */
15
+ export declare function toArray<T = any>(v: T | T[] | undefined | null): T[];
@@ -0,0 +1,3 @@
1
+ import { RawPackage } from './raw-xml';
2
+ import { SheetModel } from '../model/types';
3
+ export declare function attachSparklines(pkg: RawPackage, sheets: SheetModel[]): void;
@@ -0,0 +1,3 @@
1
+ import { RawPackage } from './raw-xml';
2
+ import { CssColor } from '../model/types';
3
+ export declare function parseTheme(pkg: RawPackage): CssColor[];
@@ -0,0 +1,180 @@
1
+ import { CellStyleFn, CellStyleOverride, ImageAnchor, MergeRange, TransformModelFn, WorkbookModel } from './model/types';
2
+ import { CellValue, ReadOptions, SheetToJSONOptions } from './model/data-access';
3
+ import { CellSnapshot } from './model/snapshot';
4
+ import { EditorResolver } from './edit/editor-context';
5
+ import { ViewerTheme } from './render/theme';
6
+ import { ExcelSource } from './loader';
7
+ import { ImageExportOptions, PdfExportOptions, PrintOptions } from './export/types';
8
+ import { XlsxExportOptions } from './export/xlsx-writer';
9
+ export interface Rect {
10
+ x: number;
11
+ y: number;
12
+ w: number;
13
+ h: number;
14
+ }
15
+ export type PluginEvent = 'cell-click' | 'cell-dblclick' | 'selection-change' | 'sheet-change' | 'hyperlink-click' | 'cell-change' | 'edit-start' | 'edit-commit' | 'dim-change' | 'dirty-change' | 'image-change' | 'struct-change';
16
+ /** 命令式 API(组件 ref 与插件 ctx 共用) */
17
+ export interface ViewerApi {
18
+ load(src: ExcelSource): void;
19
+ getWorkbook(): WorkbookModel | null;
20
+ getActiveSheet(): number;
21
+ setActiveSheet(index: number): void;
22
+ getSelection(): MergeRange | null;
23
+ setSelection(range: MergeRange): void;
24
+ rectOf(row: number, col: number): Rect | null;
25
+ rectOfRange(range: MergeRange): Rect | null;
26
+ redraw(): void;
27
+ /** 该格当前是否可编辑(综合 editable + readOnlyRanges + cellReadOnly) */
28
+ isCellEditable(row: number, col: number): boolean;
29
+ /** 导出当前/指定表为图片 Blob(默认 png) */
30
+ exportImage(opts?: ImageExportOptions): Promise<Blob>;
31
+ /** 导出为图片并触发下载 */
32
+ downloadImage(opts?: ImageExportOptions): Promise<void>;
33
+ /** 导出为 PDF Blob(需可选依赖 jspdf);beforeRenderPage 可画页眉/页脚/水印 */
34
+ exportPdf(opts?: PdfExportOptions): Promise<Blob>;
35
+ /** 导出 PDF 并触发下载 */
36
+ downloadPdf(opts?: PdfExportOptions): Promise<void>;
37
+ /** 打开系统打印(可在对话框另存为 PDF) */
38
+ print(opts?: PrintOptions): Promise<void>;
39
+ /** 整簿 → .xlsx Blob(从编辑后模型重建,所见即所得;需可选依赖 exceljs) */
40
+ exportXlsx(opts?: XlsxExportOptions): Promise<Blob>;
41
+ /** 导出 .xlsx 并触发下载 */
42
+ downloadXlsx(opts?: XlsxExportOptions): Promise<void>;
43
+ /** 整簿 → JSON 文本(各表首行作 key) */
44
+ exportJson(opts?: SheetToJSONOptions): string;
45
+ /** 导出 JSON 并触发下载 */
46
+ downloadJson(opts?: SheetToJSONOptions): void;
47
+ /** 一张表 → CSV 文本(默认活动表、格式化显示值) */
48
+ exportCsv(opts?: {
49
+ target?: number;
50
+ format?: boolean;
51
+ }): string;
52
+ /** 导出 CSV 并触发下载(带 UTF-8 BOM) */
53
+ downloadCsv(opts?: {
54
+ target?: number;
55
+ format?: boolean;
56
+ }): void;
57
+ /** 单元格原始值 */
58
+ getCellValue(row: number, col: number, sheetIndex?: number): CellValue;
59
+ /** 单元格格式化显示文本 */
60
+ getCellText(row: number, col: number, sheetIndex?: number): string;
61
+ /** 整表二维数组(format 默认 true=显示文本) */
62
+ getSheetData(opts?: ReadOptions, sheetIndex?: number): CellValue[][];
63
+ /** 整表对象数组(首行作表头) */
64
+ getSheetJSON(opts?: SheetToJSONOptions, sheetIndex?: number): Record<string, CellValue>[];
65
+ /** 区域二维数组 */
66
+ getRangeData(range: MergeRange, opts?: ReadOptions, sheetIndex?: number): CellValue[][];
67
+ /** 编辑单格;返回是否生效 */
68
+ editCell(row: number, col: number, value: CellValue): boolean;
69
+ /** 区域批量设值(2D,左上对齐 range.top/left);跳过只读格 */
70
+ editRange(range: MergeRange, values: CellValue[][]): boolean;
71
+ /** 清空区域(跳过只读) */
72
+ clearRange(range: MergeRange): boolean;
73
+ undo(): void;
74
+ redo(): void;
75
+ canUndo(): boolean;
76
+ canRedo(): boolean;
77
+ /** 当前正在编辑的格(无则 null) */
78
+ getEditingCell(): {
79
+ row: number;
80
+ col: number;
81
+ } | null;
82
+ /** 查询任意格的完整快照(底层结构 + raw/computed/text/style) */
83
+ getCellSnapshot(row: number, col: number): CellSnapshot | null;
84
+ /** 进入编辑(需有 editor 工厂 + 可编辑);返回是否进入 */
85
+ beginEdit(row: number, col: number): boolean;
86
+ /** 取消当前编辑(不改模型) */
87
+ cancelEdit(): void;
88
+ /** 当前是否有活动编辑器 */
89
+ isEditing(): boolean;
90
+ /** 给区域套样式覆盖(E5;粗体/对齐/填充等);editable 时入命令栈(可撤销 + 发 cell-change + 记脏) */
91
+ setStyle(range: MergeRange, patch: CellStyleOverride): boolean;
92
+ /** 读当前表全部图片锚点(克隆;E6) */
93
+ getImages(): ImageAnchor[];
94
+ /** 加一张图(无 src 但有 bytes+mime 时自动生成 blob url);返回插入索引 */
95
+ addImage(anchor: ImageAnchor): number;
96
+ /** 删一张图 */
97
+ removeImage(index: number): boolean;
98
+ /** 移动图片(屏幕像素增量);editable 时入命令栈 + 发 image-change */
99
+ moveImage(index: number, dxPx: number, dyPx: number): boolean;
100
+ /** 缩放图片(目标屏幕像素宽高);editable 时入命令栈 + 发 image-change */
101
+ resizeImage(index: number, widthPx: number, heightPx: number): boolean;
102
+ /** 在 at 处插入 count 行(E7);editable 时入命令栈 + 发 struct-change */
103
+ insertRows(at: number, count?: number): boolean;
104
+ /** 删除 [at, at+count) 行(与合并相交则相交合并被移除) */
105
+ deleteRows(at: number, count?: number): boolean;
106
+ /** 在 at 处插入 count 列 */
107
+ insertCols(at: number, count?: number): boolean;
108
+ /** 删除 [at, at+count) 列 */
109
+ deleteCols(at: number, count?: number): boolean;
110
+ /** 程序化设列宽(px,模型单位);editable 时入命令栈(可撤销 + 发 dim-change + 记脏) */
111
+ setColumnWidth(col: number, width: number): boolean;
112
+ /** 程序化设行高(px,模型单位);editable 时入命令栈 */
113
+ setRowHeight(row: number, height: number): boolean;
114
+ /** 公式引擎是否已就绪(recalc 开启 + 异步 warm 完成);未开重算恒 false */
115
+ isRecalcReady(): boolean;
116
+ /** 当前是否有未保存修改(自加载/还原以来发生过编辑或 resize) */
117
+ isDirty(): boolean;
118
+ /** 放弃全部修改,还原到刚加载的原件;返回是否还原 */
119
+ resetToOriginal(): boolean;
120
+ }
121
+ /** overlay 渲染上下文(随滚动/缩放,tick 变即重渲) */
122
+ export interface OverlayContext {
123
+ rectOf(row: number, col: number): Rect | null;
124
+ rectOfRange(range: MergeRange): Rect | null;
125
+ tick: number;
126
+ workbook: WorkbookModel | null;
127
+ }
128
+ /** overlay 钩子返回值:框架无关的 DOM 节点(单个 / 多个 / 无)。Vue 与 React 壳都直接挂载。 */
129
+ export type OverlayNode = HTMLElement | HTMLElement[] | null;
130
+ export interface ExcelPluginContext {
131
+ viewer: ViewerApi;
132
+ /** 订阅交互事件 */
133
+ on(event: PluginEvent, handler: (payload: any) => void): void;
134
+ /** 主动重绘 */
135
+ redraw(): void;
136
+ }
137
+ /** 操作工具栏的一个按钮(插件贡献 / 组件 :toolbar 配置 / 命令式自定义共用) */
138
+ export interface ToolbarItem {
139
+ /** 唯一 id(内置: 'find'|'filter'|'sort'|'export'|'zoom'|'copy'|'freeze'|'clear-filter';自定义任意) */
140
+ id: string;
141
+ /** 类型: 'button'(默认) | 'separator'(分隔线,其余字段忽略) */
142
+ type?: 'button' | 'separator';
143
+ /** 图标(emoji / 字形);跨平台一致建议用 iconSvg */
144
+ icon?: string;
145
+ /** 内联 SVG(优先于 icon);建议 24×24 viewBox、stroke=currentColor */
146
+ iconSvg?: string;
147
+ /** 文字 */
148
+ label?: string;
149
+ /** 悬停提示 */
150
+ title?: string;
151
+ /** 点击回调(拿到命令式 API);有 items 时点击改为展开下拉 */
152
+ onClick?: (viewer: ViewerApi) => void;
153
+ /** 是否高亮(激活态),如开关类按钮 */
154
+ active?: (viewer: ViewerApi) => boolean;
155
+ /** 是否禁用(置灰不可点) */
156
+ disabled?: (viewer: ViewerApi) => boolean;
157
+ /** 下拉子菜单项;有则本项为下拉按钮(点击展开) */
158
+ items?: ToolbarItem[];
159
+ }
160
+ export interface ExcelPlugin {
161
+ name: string;
162
+ /** 外观主题覆盖(多插件按数组顺序合并,组件 :theme 最后覆盖) */
163
+ theme?: Partial<ViewerTheme>;
164
+ /** 贡献操作工具栏按钮(opt-in: 插件加载即出现) */
165
+ toolbar?: ToolbarItem[];
166
+ /** 数据钩子: 解析后改模型(多插件 + 组件 prop 链式应用) */
167
+ transformModel?: TransformModelFn;
168
+ /** 渲染钩子: 按单元格覆盖样式(多插件 + 组件 prop 合并) */
169
+ cellStyle?: CellStyleFn;
170
+ /** 交互事件处理(简单写法;复杂用 setup 的 on) */
171
+ events?: Partial<Record<PluginEvent, (payload: any) => void>>;
172
+ /** 在网格上叠加 UI(返回 DOM 节点,框架无关);随 tick 重渲。用 ctx.rectOf 定位单元格。 */
173
+ overlay?: (ctx: OverlayContext) => OverlayNode;
174
+ /** 按格自定义编辑控件(返回工厂;多插件数组序首个非空胜,组件 editor prop 覆盖);需 editable 开启。 */
175
+ editor?: EditorResolver;
176
+ /** 高级: 拿命令式 API、订阅事件;返回可选清理函数 */
177
+ setup?: (ctx: ExcelPluginContext) => void | (() => void);
178
+ }
179
+ /** 定义插件(仅作类型推断,原样返回) */
180
+ export declare function definePlugin(plugin: ExcelPlugin): ExcelPlugin;
@@ -0,0 +1,7 @@
1
+ /** 解析进度(分阶段)。read/build 有真实 ratio;parse 是 exceljs 黑盒,ratio 缺省=不确定态。 */
2
+ export interface ParseProgress {
3
+ stage: 'read' | 'parse' | 'build';
4
+ /** 0..1;parse 阶段为 undefined(不确定态,UI 走脉冲) */
5
+ ratio?: number;
6
+ }
7
+ export type ProgressFn = (p: ParseProgress) => void;
@@ -0,0 +1,14 @@
1
+ import { MergeRange } from '../model/types';
2
+ /** 判断某 cell 是否是自动筛选表头(范围首行) */
3
+ export declare function isFilterHeader(range: MergeRange | undefined, row: number, col: number): boolean;
4
+ /** 单元格右侧筛选下拉按钮的方形区域(像素);供命中检测与绘制共用 */
5
+ export declare function filterButtonBox(cellX: number, cellY: number, cellW: number, cellH: number): {
6
+ x: number;
7
+ y: number;
8
+ size: number;
9
+ } | null;
10
+ /**
11
+ * 在单元格右侧画一个筛选下拉按钮。active=true 时画蓝色漏斗(已筛选)。
12
+ * 返回按钮占用的宽度(供文本避让)。
13
+ */
14
+ export declare function drawFilterButton(ctx: CanvasRenderingContext2D, cellX: number, cellY: number, cellW: number, cellH: number, active?: boolean): number;
@@ -0,0 +1,13 @@
1
+ import { BorderEdge } from '../model/types';
2
+ /** 共享边取较重的一条(同重则取 a / 本单元格的)。任一为空按 none 计。 */
3
+ export declare function heavierEdge(a: BorderEdge | undefined, b: BorderEdge | undefined): BorderEdge | undefined;
4
+ /**
5
+ * 画一条边。(x1,y1)-(x2,y2) 为边的两端点(已是屏幕坐标)。
6
+ * 横边传 y1===y2,竖边传 x1===x2。
7
+ */
8
+ export declare function drawEdge(ctx: CanvasRenderingContext2D, edge: BorderEdge | undefined, x1: number, y1: number, x2: number, y2: number): void;
9
+ /**
10
+ * 画一条任意方向的对角线(单元格对角线边框 ↘ / ↗)。
11
+ * 用线型的宽度/虚线/颜色;double 退化为单线(对角双线极罕见,不值得歪斜偏移)。
12
+ */
13
+ export declare function drawDiagonalEdge(ctx: CanvasRenderingContext2D, edge: BorderEdge | undefined, x1: number, y1: number, x2: number, y2: number): void;