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,137 @@
1
+ import { CellStyleOverride, ColumnInfo, ImageAnchor, MergeRange, RowInfo, SheetModel, WorkbookModel } from '../model/types';
2
+ import { CellValue } from '../model/data-access';
3
+ import { CellSnapshot } from '../model/snapshot';
4
+ import { CellPos, DimAxis } from './commands';
5
+ import { StructOp } from '../model/structure';
6
+ import { FormulaEngineFactory } from '../formula/engine';
7
+ export type EditEventName = 'cell-change' | 'edit-start' | 'edit-commit' | 'dim-change' | 'dirty-change' | 'image-change' | 'struct-change';
8
+ export type EditSource = 'api' | 'ui' | 'undo' | 'redo';
9
+ /** 结构变更事件载荷(增删行列;restore = 撤销/重做的整体还原) */
10
+ export interface StructChangePayload {
11
+ op: StructOp | 'restore';
12
+ at?: number;
13
+ count?: number;
14
+ source: EditSource;
15
+ }
16
+ /** 图片变更事件载荷(before/after = ImageAnchor 克隆;add → before=null;remove → after=null) */
17
+ export interface ImageChangePayload {
18
+ index: number;
19
+ before: ImageAnchor | null;
20
+ after: ImageAnchor | null;
21
+ source: EditSource;
22
+ }
23
+ export interface CellChangePayload {
24
+ before: CellSnapshot;
25
+ after: CellSnapshot;
26
+ source: EditSource;
27
+ }
28
+ /** 列宽/行高变更事件载荷(before/after = px 尺寸,含默认值回落) */
29
+ export interface DimChangePayload {
30
+ axis: DimAxis;
31
+ index: number;
32
+ before: number;
33
+ after: number;
34
+ source: EditSource;
35
+ }
36
+ /** 脏状态变更事件载荷 */
37
+ export interface DirtyChangePayload {
38
+ dirty: boolean;
39
+ }
40
+ /** EditController 与 ViewerController 的桥(host-callback,框架无关) */
41
+ export interface EditControllerHost {
42
+ getSheet(): SheetModel | null;
43
+ getWorkbook(): WorkbookModel | null;
44
+ getDate1904(): boolean;
45
+ /** 该格是否可编辑(综合 editable + readOnlyRanges + cellReadOnly) */
46
+ isEditable(row: number, col: number): boolean;
47
+ /** 编辑模式是否开启(决定是否懒捕获 baseline / 记账脏状态) */
48
+ isEditingEnabled(): boolean;
49
+ /** 当前活动表索引(0-based;重算把级联事件/写回锚到它) */
50
+ getActiveSheetIndex(): number;
51
+ /** 是否开启公式重算(EditConfig.recalc) */
52
+ isRecalcEnabled(): boolean;
53
+ /** 公式引擎工厂(EditConfig.formulaEngine,或默认 HyperFormula;未开重算 → null) */
54
+ getEngineFactory(): FormulaEngineFactory | null;
55
+ /** 模型变更后回调:重建几何 + 重绘 */
56
+ onModelChange(): void;
57
+ /** 图片结构变化(增删)→ 重建叠加层(重绘不够,要新建/移除 DOM)。移动只需 onModelChange 重定位。 */
58
+ rebuildOverlays(): void;
59
+ /** 发编辑事件(壳转 emit + 插件派发) */
60
+ emit(event: EditEventName, payload: unknown): void;
61
+ }
62
+ export declare class EditController {
63
+ private host;
64
+ private undoStack;
65
+ private redoStack;
66
+ private editing;
67
+ private readonly limit;
68
+ private dirty;
69
+ private baseline;
70
+ private baselineFor;
71
+ private engine;
72
+ private engineFor;
73
+ private warming;
74
+ constructor(host: EditControllerHost);
75
+ /** 异步懒初始化引擎(开重算 + 有工厂 + 尚未为当前簿建好)。返回的 Promise 供测试 await;生产 fire-and-forget。 */
76
+ warmEngine(): Promise<void>;
77
+ /** 释放引擎(切簿/关重算/dispose)。 */
78
+ disposeEngine(): void;
79
+ /** 配置变化(recalc/factory)或换新簿:重置引擎并按需重新点火。 */
80
+ refreshEngine(): void;
81
+ private engineReady;
82
+ /** 公式引擎是否已就绪(异步 warm 完成且对应当前簿);未开重算恒 false。 */
83
+ isRecalcReady(): boolean;
84
+ getEditingCell(): CellPos | null;
85
+ setEditing(cell: CellPos | null): void;
86
+ canUndo(): boolean;
87
+ canRedo(): boolean;
88
+ /** 查询任意格的完整快照(要求 5:事件之外也有查询 API) */
89
+ getCellSnapshot(row: number, col: number): CellSnapshot | null;
90
+ /** 切表/换簿时清空(交互态 + 命令栈作废) */
91
+ reset(): void;
92
+ /** 编辑单格;只读则不动,返回是否生效 */
93
+ editCell(row: number, col: number, value: CellValue): boolean;
94
+ /** 区域批量设值(2D,左上对齐 range.top/left);跳过只读格,返回是否有改动 */
95
+ editRange(range: MergeRange, values: CellValue[][]): boolean;
96
+ /** 清空区域(跳过只读) */
97
+ clearRange(range: MergeRange): boolean;
98
+ /** 给区域套样式覆盖(E5;跳过只读格)。返回是否有改动。前后 style 不同 → 发 cell-change。 */
99
+ setStyle(range: MergeRange, patch: CellStyleOverride): boolean;
100
+ insertRows(at: number, count?: number): boolean;
101
+ deleteRows(at: number, count?: number): boolean;
102
+ insertCols(at: number, count?: number): boolean;
103
+ deleteCols(at: number, count?: number): boolean;
104
+ private structEdit;
105
+ /** 读当前表全部图片锚点(克隆,防外部改)。 */
106
+ getImages(): ImageAnchor[];
107
+ /** 加一张图,返回插入索引(失败 -1)。 */
108
+ addImage(anchor: ImageAnchor): number;
109
+ /** 删一张图。 */
110
+ removeImage(index: number): boolean;
111
+ /**
112
+ * 补登一次图片移动/缩放(拖拽/programmatic:模型已被 setImageRect 改完,这里只补 undo + 发 image-change)。
113
+ * baseline 须在变更前由调用方 ensureBaseline() 捕获。
114
+ */
115
+ recordImageEdit(index: number, before: ImageAnchor, after: ImageAnchor): void;
116
+ /** 程序化设列宽/行高(API 路径:apply-via-command)。返回是否生效。 */
117
+ setDimension(axis: DimAxis, index: number, size: number): boolean;
118
+ /**
119
+ * 补登一次维度变更(拖拽/autofit 路径:模型已被 renderer 改完,这里只补 undo 项 + 发事件)。
120
+ * baseline 须在变更前(拖拽起始/autofit 前)由调用方 ensureBaseline() 捕获。
121
+ */
122
+ recordDimEdit(axis: DimAxis, index: number, beforeInfo: ColumnInfo | RowInfo | null, before: number, after: number): void;
123
+ /** editable 时懒捕获 baseline(首次编辑/resize 前调,模型仍原始);幂等。 */
124
+ ensureBaseline(): void;
125
+ isDirty(): boolean;
126
+ private markDirty;
127
+ /** 换新工作簿(非切表)时:作废 baseline + 清脏(切表保留,见 controller 判定)。 */
128
+ resetDirtyBaseline(): void;
129
+ /** 放弃全部修改,还原到刚加载的原件。返回是否还原(无 baseline → false)。 */
130
+ resetToOriginal(): boolean;
131
+ undo(): void;
132
+ redo(): void;
133
+ private collectEditable;
134
+ private pushUndo;
135
+ /** 应用一条命令:建前快照 → apply → 重绘 → 发事件(cell 族 cell-change / dim 族 dim-change)。返回逆命令。 */
136
+ private exec;
137
+ }
@@ -0,0 +1,40 @@
1
+ import { SheetModel, WorkbookModel, CellModel, CellStyleOverride } from '../model/types';
2
+ import { CellValue } from '../model/data-access';
3
+ import { CellSnapshot } from '../model/snapshot';
4
+ import { EditPermission } from './types';
5
+ export type Rect = {
6
+ x: number;
7
+ y: number;
8
+ w: number;
9
+ h: number;
10
+ };
11
+ /** commit 既可只给值,也可同时给样式(样式 E5 起生效) */
12
+ export type EditorCommitValue = CellValue | {
13
+ value: CellValue;
14
+ style?: CellStyleOverride;
15
+ };
16
+ export interface CellEditorContext {
17
+ /** 进入编辑时的完整前态快照 */
18
+ snapshot: CellSnapshot;
19
+ /** 单元格当前屏幕矩形(render-area 相对) */
20
+ rect: Rect;
21
+ sheet: SheetModel;
22
+ workbook: WorkbookModel;
23
+ permission: EditPermission;
24
+ /** 进入编辑的初始文本(打字进入时为该字符;否则 undefined → editor 用 snapshot.text) */
25
+ initialText?: string;
26
+ /** 提交编辑(走命令栈 + 事件);move 指示提交后活动格移动方向 */
27
+ commit(value: EditorCommitValue, move?: 'down' | 'right'): void;
28
+ /** 取消编辑(不改模型) */
29
+ cancel(): void;
30
+ }
31
+ /** 编辑器工厂:返回 DOM 元素,或 { el, destroy }(destroy 在卸载时清理) */
32
+ export type CellEditorFactory = (ctx: CellEditorContext) => HTMLElement | {
33
+ el: HTMLElement;
34
+ destroy?: () => void;
35
+ };
36
+ /** 编辑器解析器:按格决定用哪个工厂(无 → 该格无自定义编辑器) */
37
+ export type EditorResolver = (cell: CellModel | null, pos: {
38
+ row: number;
39
+ col: number;
40
+ }) => CellEditorFactory | void;
@@ -0,0 +1,22 @@
1
+ import { CellEditorContext, CellEditorFactory, Rect } from './editor-context';
2
+ export declare class CellEditorHost {
3
+ private container;
4
+ private rectOf;
5
+ private active;
6
+ constructor(container: HTMLElement, rectOf: (row: number, col: number) => Rect | null);
7
+ isActive(): boolean;
8
+ activeCell(): {
9
+ row: number;
10
+ col: number;
11
+ } | null;
12
+ /**
13
+ * 挂载一个编辑器(先卸旧)。返回是否成功(工厂产出有效 DOM)。
14
+ * rectOverride 给定时用它定位(合并单元格 → 整片合并区),否则按单格 rectOf。
15
+ */
16
+ mount(row: number, col: number, factory: CellEditorFactory, ctx: CellEditorContext, rectOverride?: () => Rect | null): boolean;
17
+ /** 按当前 rectOf 重定位活动编辑器(滚动/缩放后跟随) */
18
+ position(): void;
19
+ /** 卸载活动编辑器 */
20
+ unmount(): void;
21
+ dispose(): void;
22
+ }
@@ -0,0 +1,3 @@
1
+ import { SheetModel } from '../model/types';
2
+ import { EditConfig } from './types';
3
+ export declare function resolveEditable(sheet: SheetModel, row: number, col: number, cfg: EditConfig): boolean;
@@ -0,0 +1,23 @@
1
+ import { CellModel, MergeRange } from '../model/types';
2
+ import { FormulaEngineFactory } from '../formula/engine';
3
+ export interface EditConfig {
4
+ /** 总开关:默认 false = 只读(行为与历史完全一致) */
5
+ editable?: boolean;
6
+ /** 按格只读判定:返回 true = 该格只读。cell 为空格时传 null。pos 为 0-based 行列。 */
7
+ cellReadOnly?: (cell: CellModel | null, pos: {
8
+ row: number;
9
+ col: number;
10
+ }) => boolean | void;
11
+ /** 只读区域(0-based 闭区间);命中即只读 */
12
+ readOnlyRanges?: MergeRange[];
13
+ /**
14
+ * 公式重算(E4):默认 false = 沿用 Excel 缓存值(只读/无公式路径零成本)。
15
+ * 开启后,编辑公式格或被公式引用的格 → 依赖格自动重算并逐个发 cell-change。
16
+ * 默认引擎 HyperFormula(GPL-3.0/商业双授权,可选 peer);需 `npm i hyperformula`。
17
+ */
18
+ recalc?: boolean;
19
+ /** 自定义/自研公式引擎工厂(可换引擎);不给则用默认 HyperFormula 适配器。 */
20
+ formulaEngine?: FormulaEngineFactory;
21
+ }
22
+ /** 单元格编辑权限 */
23
+ export type EditPermission = 'editable' | 'readonly';
@@ -0,0 +1,18 @@
1
+ import { ExportToCanvasResult } from '../render/canvas-renderer';
2
+ import { ImageAnchor, ShapeSpec } from '../model/types';
3
+ export interface ExportDecorations {
4
+ /** 已加载的图片源(HTMLImageElement / 离屏 canvas 等) + 其锚点 */
5
+ images?: {
6
+ source: CanvasImageSource;
7
+ anchor: ImageAnchor;
8
+ }[];
9
+ /** 已栅格化的图表源(如 echarts getDataURL 加载成的 Image) + 锚点 */
10
+ charts?: {
11
+ source: CanvasImageSource;
12
+ anchor: ImageAnchor;
13
+ }[];
14
+ /** 形状/文本框(按 ShapeSpec 直接画) */
15
+ shapes?: ShapeSpec[];
16
+ }
17
+ /** 把装饰合成到 base.canvas(原地修改)。 */
18
+ export declare function compositeOverlays(base: ExportToCanvasResult, deco?: ExportDecorations): void;
@@ -0,0 +1,9 @@
1
+ import { SheetModel, WorkbookModel } from '../model/types';
2
+ import { SheetToJSONOptions } from '../model/data-access';
3
+ /** 一张表 → CSV 文本(默认格式化显示值,与渲染一致;行用 CRLF)。 */
4
+ export declare function toCsv(sheet: SheetModel, opts?: {
5
+ format?: boolean;
6
+ date1904?: boolean;
7
+ }): string;
8
+ /** 整簿 → JSON(各表首行作 key 的对象数组);复用 getWorkbookJSON。默认 raw 类型值(非显示串)。 */
9
+ export declare function toWorkbookJson(workbook: WorkbookModel, opts?: SheetToJSONOptions): string;
@@ -0,0 +1,64 @@
1
+ import { WorkbookModel } from '../model/types';
2
+ import { CanvasRenderer, RendererOptions } from '../render/canvas-renderer';
3
+ import { XlsxExportOptions } from './xlsx-writer';
4
+ import { SheetToJSONOptions } from '../model/data-access';
5
+ import { ImageExportOptions, PdfExportOptions, PrintOptions } from './types';
6
+ /** 导出取数器: 壳提供当前工作簿 / 活动表 / 复用渲染器 / 渲染配置 / 文件名 */
7
+ export interface ExporterHost {
8
+ getWorkbook(): WorkbookModel | null;
9
+ /** 活动表索引(决定 'active' 目标 + 哪张表能复用 live renderer) */
10
+ getActiveIndex(): number;
11
+ /** 当前活动表的在用 renderer(复用以省一次离屏构建);非活动表传 null 即可 */
12
+ getLiveRenderer(): CanvasRenderer | null;
13
+ /** 离屏渲染其它表时用的渲染配置(主题/cellStyle),须与 live 一致 */
14
+ getRendererOpts(): RendererOptions;
15
+ /** 文件名(下载默认名;缺省回退表名 / 'workbook') */
16
+ getFileName(): string | undefined;
17
+ /** 原始 .xlsx 字节(高保真 overlay 导出重载原件用;无则返回 null,overlay 回退 rebuild) */
18
+ getSourceBuffer?(): ArrayBuffer | null;
19
+ }
20
+ export declare class WorkbookExporter {
21
+ private host;
22
+ constructor(host: ExporterHost);
23
+ /** target → 工作表索引列表 */
24
+ private resolveTargets;
25
+ /** 取某表的 renderer: 活动表复用 live,其它表离屏新建 */
26
+ private rendererFor;
27
+ private baseName;
28
+ /** 离屏渲染一个图表为 dataURL(供非当前表 / 统一合成);echarts 不可用返回 null */
29
+ private chartDataUrl;
30
+ /** 收集一个工作表的叠加层装饰(图片/图表/形状),供合成到导出底图 */
31
+ private collectDecorations;
32
+ /**
33
+ * 为一个工作表生成合成底图(格子 + 图片/图表/形状)。
34
+ * withTitles(PDF/打印): 应用 pageSetup 打印标题行(抽出标题条 + 正文剔除标题行)与缩放。
35
+ */
36
+ private buildSheetImage;
37
+ /** 为一个工作表生成矢量导出输入(逐格信息 + 兜底底图 + 图片图表 + 标题行) */
38
+ private buildVectorSheet;
39
+ /** 从工作表原生 pageSetup 推导导出默认值(纸张/方向/边距/是否适应页宽) */
40
+ private pageSetupDefaults;
41
+ /** 导出当前/指定表为图片 Blob(图片为单表;多表请用 PDF) */
42
+ exportImage(opts?: ImageExportOptions): Promise<Blob>;
43
+ downloadImage(opts?: ImageExportOptions): Promise<void>;
44
+ /** 导出为 PDF Blob(每个目标表分页;需可选依赖 jspdf)。未显式指定的页面参数取自工作表 pageSetup。 */
45
+ exportPdf(opts?: PdfExportOptions): Promise<Blob>;
46
+ downloadPdf(opts?: PdfExportOptions): Promise<void>;
47
+ /** 打开系统打印(可在对话框另存为 PDF)。页面参数同样默认取自 pageSetup。 */
48
+ print(opts?: PrintOptions): Promise<void>;
49
+ /** 整簿 → JSON 文本(各表首行作 key 的对象数组)。 */
50
+ exportJson(opts?: SheetToJSONOptions): string;
51
+ downloadJson(opts?: SheetToJSONOptions): void;
52
+ /** 一张表 → CSV 文本(默认活动表、格式化显示值)。 */
53
+ exportCsv(opts?: {
54
+ target?: number;
55
+ format?: boolean;
56
+ }): string;
57
+ downloadCsv(opts?: {
58
+ target?: number;
59
+ format?: boolean;
60
+ }): void;
61
+ /** 整簿 → .xlsx Blob(默认从模型重建;`fidelity:'overlay'` 重载原件叠加编辑,保真更高)。 */
62
+ exportXlsx(opts?: XlsxExportOptions): Promise<Blob>;
63
+ downloadXlsx(opts?: XlsxExportOptions): Promise<void>;
64
+ }
@@ -0,0 +1,9 @@
1
+ /** 导出/打印模块出口 */
2
+ export type { ExportTarget, RenderExportOptions, ImageExportOptions, PageFormat, Orientation, Margins, PageSetup, PdfPageContext, BeforeRenderPage, PdfExportOptions, PrintOptions, } from './types';
3
+ export { canvasToBlob, canvasToDataURL, downloadBlob, loadImage, resolvePageSize, resolveMargins, MM_PER_PX } from './raster';
4
+ export { compositeOverlays, type ExportDecorations } from './composite';
5
+ export { sliceToPages, type SlicedPage } from './paginate';
6
+ export { exportToPdf, type ExportSheetImage } from './pdf';
7
+ export { exportToVectorPdf, type VectorSheet } from './vector-pdf';
8
+ export { printSheets } from './print';
9
+ export { WorkbookExporter, type ExporterHost } from './exporter';
@@ -0,0 +1,36 @@
1
+ export interface SlicedPage {
2
+ /** 该页的图像切片(设备像素) */
3
+ canvas: HTMLCanvasElement;
4
+ /** 贴到 PDF 页上的尺寸 mm */
5
+ widthMm: number;
6
+ heightMm: number;
7
+ }
8
+ export interface SliceOptions {
9
+ contentWmm: number;
10
+ contentHmm: number;
11
+ fitToWidth: boolean;
12
+ /** 非 fitToWidth 时的打印缩放(pageSetup.scale/100),默认 1 */
13
+ zoom?: number;
14
+ /** 打印标题行条(标题行 × 正文列),贴每页顶部 */
15
+ repeatTop?: {
16
+ canvas: HTMLCanvasElement;
17
+ heightCss: number;
18
+ };
19
+ /** 打印标题列条(标题列 × 正文行),贴每页左侧 */
20
+ repeatLeft?: {
21
+ canvas: HTMLCanvasElement;
22
+ widthCss: number;
23
+ };
24
+ /** 标题角(标题列 × 标题行),贴左上角 */
25
+ corner?: {
26
+ canvas: HTMLCanvasElement;
27
+ };
28
+ }
29
+ interface Band {
30
+ s: number;
31
+ len: number;
32
+ }
33
+ /** 把 total 像素按 bandSize 切成若干段(末段取余)。(导出供测) */
34
+ export declare function makeBands(total: number, bandSize: number): Band[];
35
+ export declare function sliceToPages(base: HTMLCanvasElement, bodyWcss: number, bodyHcss: number, page: SliceOptions): SlicedPage[];
36
+ export {};
@@ -0,0 +1,28 @@
1
+ import { PdfExportOptions } from './types';
2
+ /** 一个待导出工作表的合成底图 */
3
+ export interface ExportSheetImage {
4
+ /** 已合成(格子 + 图片/图表/形状)的底图,设备像素 */
5
+ canvas: HTMLCanvasElement;
6
+ /** 正文 css 宽高(zoom=1,不含表头) */
7
+ bodyWcss: number;
8
+ bodyHcss: number;
9
+ sheetName: string;
10
+ /** 打印标题: 每页顶部重复的标题行条(同 scale,等宽于 canvas) */
11
+ repeatTop?: {
12
+ canvas: HTMLCanvasElement;
13
+ heightCss: number;
14
+ };
15
+ /** 打印标题: 每页左侧重复的标题列条(同 scale,等高于 canvas) */
16
+ repeatLeft?: {
17
+ canvas: HTMLCanvasElement;
18
+ widthCss: number;
19
+ };
20
+ /** 标题角(标题列×标题行) */
21
+ corner?: {
22
+ canvas: HTMLCanvasElement;
23
+ };
24
+ /** 非 fitToWidth 时的打印缩放(pageSetup.scale/100) */
25
+ zoom?: number;
26
+ }
27
+ /** 生成 PDF,返回 Blob(不触发下载)。 */
28
+ export declare function exportToPdf(sheets: ExportSheetImage[], opts?: PdfExportOptions): Promise<Blob>;
@@ -0,0 +1,3 @@
1
+ import { PrintOptions } from './types';
2
+ import { ExportSheetImage } from './pdf';
3
+ export declare function printSheets(sheets: ExportSheetImage[], opts?: PrintOptions): void;
@@ -0,0 +1,13 @@
1
+ import { Margins, Orientation, PageFormat } from './types';
2
+ export declare function canvasToBlob(canvas: HTMLCanvasElement, type?: string, quality?: number): Promise<Blob>;
3
+ export declare function canvasToDataURL(canvas: HTMLCanvasElement, type?: string, quality?: number): string;
4
+ /** 触发浏览器下载一个 Blob */
5
+ export declare function downloadBlob(blob: Blob, fileName: string): void;
6
+ /** 从 URL / blobURL / dataURL 加载为 HTMLImageElement(用于合成到导出底图) */
7
+ export declare function loadImage(src: string): Promise<HTMLImageElement>;
8
+ /** 解析纸张为 [宽, 高] mm,应用方向 */
9
+ export declare function resolvePageSize(format?: PageFormat, orientation?: Orientation): [number, number];
10
+ /** 归一化页边距(数字 → 四边;部分 → 补默认 10) */
11
+ export declare function resolveMargins(margin: number | Partial<Margins> | undefined): Margins;
12
+ /** css px → mm(按 96dpi) */
13
+ export declare const MM_PER_PX: number;
@@ -0,0 +1,92 @@
1
+ import { MergeRange } from '../model/types';
2
+ /** 选哪些工作表导出 */
3
+ export type ExportTarget = 'active' | 'all' | number | number[];
4
+ /** 公共渲染选项(决定底图怎么画) */
5
+ export interface RenderExportOptions {
6
+ /** 仅当导出单个工作表时生效: 限定单元格区域(0-based 闭区间) */
7
+ range?: MergeRange;
8
+ /** 设备像素缩放,越大越清晰(默认 2) */
9
+ scale?: number;
10
+ /** 含行号/列字母表头(默认 false,同 Excel 打印) */
11
+ includeHeaders?: boolean;
12
+ /** 覆盖网格线显隐(缺省跟随工作表设置) */
13
+ gridlines?: boolean;
14
+ /** 背景色(默认白) */
15
+ background?: string;
16
+ }
17
+ /** 图片导出选项 */
18
+ export interface ImageExportOptions extends RenderExportOptions {
19
+ target?: ExportTarget;
20
+ /** 图片格式(默认 png) */
21
+ type?: 'png' | 'jpeg' | 'webp';
22
+ /** jpeg/webp 质量 0~1(默认 0.92) */
23
+ quality?: number;
24
+ /** 下载文件名(省略则用 "<表名>.png") */
25
+ fileName?: string;
26
+ }
27
+ export type PageFormat = 'a4' | 'a3' | 'letter' | [number, number];
28
+ export type Orientation = 'portrait' | 'landscape';
29
+ export interface Margins {
30
+ top: number;
31
+ right: number;
32
+ bottom: number;
33
+ left: number;
34
+ }
35
+ export interface PageSetup {
36
+ /** 纸张(默认 a4) */
37
+ format?: PageFormat;
38
+ /** 方向(默认 portrait) */
39
+ orientation?: Orientation;
40
+ /** 页边距 mm(数字=四边相同;默认 10) */
41
+ margin?: number | Partial<Margins>;
42
+ /** 把内容缩放到页宽(默认 true);false 则按自然尺寸,超宽会横向分页 */
43
+ fitToWidth?: boolean;
44
+ }
45
+ /** PDF 单页绘制上下文 —— 传给 beforeRenderPage 钩子(在页内容已贴图后调用) */
46
+ export interface PdfPageContext {
47
+ /** jsPDF 实例(可调 doc.text / doc.setFontSize / doc.line 等画页眉页脚水印) */
48
+ doc: any;
49
+ /** 全局页序(0-based) */
50
+ pageIndex: number;
51
+ /** 全局总页数 */
52
+ pageCount: number;
53
+ /** 本页所属工作表名 */
54
+ sheetName: string;
55
+ /** 本页所属工作表在导出集合中的序(0-based) */
56
+ sheetIndex: number;
57
+ /** 整页尺寸 mm */
58
+ pageWidth: number;
59
+ pageHeight: number;
60
+ /** 页边距 mm */
61
+ margin: Margins;
62
+ }
63
+ export type BeforeRenderPage = (ctx: PdfPageContext) => void;
64
+ /** PDF 导出选项 */
65
+ export interface PdfExportOptions extends RenderExportOptions, PageSetup {
66
+ target?: ExportTarget;
67
+ /** 下载文件名(省略则用 "<文件名|workbook>.pdf") */
68
+ fileName?: string;
69
+ /** 每页贴图后调用,用于画页眉/页脚/水印/页码等(扩展点) */
70
+ beforeRenderPage?: BeforeRenderPage;
71
+ /**
72
+ * 矢量 PDF: 逐格用 jsPDF 真文字/矢量绘制(可选可搜、清晰、文件小)。
73
+ * 默认 false = 位图 PDF(整表贴图)。
74
+ */
75
+ vector?: boolean;
76
+ /**
77
+ * 矢量模式扩展钩子: 建好 jsPDF doc 后调用一次,宿主可在此 addFont 注册中文等字体。
78
+ * configureDoc: (doc) => { doc.addFileToVFS('f.ttf', b64); doc.addFont('f.ttf','CN','normal'); doc.setFont('CN') }
79
+ * 注册了自定义字体 → 全矢量;否则非拉丁文本(中文)的单元格自动栅格兜底(不丢内容)。
80
+ */
81
+ configureDoc?: (doc: any) => void;
82
+ }
83
+ /** 打印选项 */
84
+ export interface PrintOptions extends RenderExportOptions, PageSetup {
85
+ target?: ExportTarget;
86
+ /** 打印窗口标题 */
87
+ title?: string;
88
+ /** 每页顶部 HTML 片段(如公司抬头);出现在每个打印页 */
89
+ headerHtml?: string;
90
+ /** 每页底部 HTML 片段 */
91
+ footerHtml?: string;
92
+ }
@@ -0,0 +1,42 @@
1
+ import { GridMetrics } from '../layout/grid-metrics';
2
+ import { CellDrawInfo } from '../render/canvas-renderer';
3
+ import { ImageAnchor, MergeRange } from '../model/types';
4
+ import { PdfExportOptions } from './types';
5
+ /** 一个待矢量导出的工作表 */
6
+ export interface VectorSheet {
7
+ sheetName: string;
8
+ metrics: GridMetrics;
9
+ /** 正文列范围(0-based 闭区间,已剔除标题列) */
10
+ bodyLeft: number;
11
+ bodyRight: number;
12
+ /** 正文行范围(0-based 闭区间,已剔除标题行) */
13
+ bodyTop: number;
14
+ bodyBottom: number;
15
+ /** 打印标题行 [r0,r1](每页顶部重复) */
16
+ titleRows?: [number, number];
17
+ /** 打印标题列 [c0,c1](每页左侧重复) */
18
+ titleCols?: [number, number];
19
+ merges: MergeRange[];
20
+ gridlines: boolean;
21
+ /** 非 fitToWidth 时的打印缩放(pageSetup.scale/100) */
22
+ zoom?: number;
23
+ /** 取一个格的绘制信息 */
24
+ getCell: (row: number, col: number) => CellDrawInfo | null;
25
+ /** 栅格兜底底图: 覆盖 [rasterTop..bodyBottom] 行 × [rasterLeft..bodyRight] 列,设备像素 */
26
+ rasterCanvas: HTMLCanvasElement;
27
+ rasterScale: number;
28
+ rasterTop: number;
29
+ rasterLeft: number;
30
+ /** 图片/图表(已加载源 + 锚点),addImage 贴上 */
31
+ images: {
32
+ source: CanvasImageSource;
33
+ anchor: ImageAnchor;
34
+ }[];
35
+ }
36
+ /** 含非拉丁字符(粗略: 码点 > 0x250) → jsPDF 内置字体画不了,需栅格兜底。(导出供测) */
37
+ export declare function hasNonLatin(s: string): boolean;
38
+ /** "#RRGGBB" → [r,g,b];非法返回黑。(导出供测) */
39
+ export declare function hexToRgb(hex: string): [number, number, number];
40
+ export declare function exportToVectorPdf(sheets: VectorSheet[], opts?: PdfExportOptions): Promise<Blob>;
41
+ /** 把一串索引按各自尺寸打包成多段(每段累计 ≤ maxMm;每段至少 1 个)。(导出供测) */
42
+ export declare function packBands(indices: number[], sizeMm: (i: number) => number, maxMm: number): number[][];
@@ -0,0 +1,15 @@
1
+ import { WorkbookModel } from '../model/types';
2
+ export interface XlsxExportOptions {
3
+ /**
4
+ * 保真模式:
5
+ * - `'rebuild'`(默认):从编辑后模型完整重建(干净,但丢原件里我们不建模的部分:条件格式/数据验证/VBA…)。
6
+ * - `'overlay'`:重载原始 .xlsx,只把编辑后的 值/样式/合并/行高列宽/冻结 叠加上去,**保留** ExcelJS
7
+ * 能往返的其余部分(条件格式/数据验证/打印设置/定义名/图表等)。需 `sourceBuffer`(壳自动注入);
8
+ * 缺原件时自动回退 rebuild。注:overlay 不反映 结构增删行列 / 图片 编辑(那类用 rebuild)。
9
+ */
10
+ fidelity?: 'rebuild' | 'overlay';
11
+ /** 原始 .xlsx 字节(overlay 模式用;由 exporter 从 host 注入,用方一般不直接传) */
12
+ sourceBuffer?: ArrayBuffer;
13
+ }
14
+ /** WorkbookModel → .xlsx Blob(懒加载 exceljs)。overlay 模式重载原件叠加编辑,否则从模型重建。 */
15
+ export declare function workbookToXlsxBlob(workbook: WorkbookModel, opts?: XlsxExportOptions): Promise<Blob>;
@@ -0,0 +1,10 @@
1
+ import { WorkbookModel } from './model/types';
2
+ /** 把解析层产出的图片字节转成 blob URL(只能在有 URL.createObjectURL 的主线程做) */
3
+ export declare function finalizeImages(model: WorkbookModel): void;
4
+ /** 释放之前 finalizeImages 生成的 blob URL,避免内存泄漏 */
5
+ export declare function revokeImages(model: WorkbookModel): void;
6
+ export type FormatKind = 'xlsx' | 'xls' | 'not-zip' | 'empty';
7
+ /** 看文件头几个字节判断格式,在真正解析前就能给出友好提示 */
8
+ export declare function detectFormat(buffer: ArrayBuffer): FormatKind;
9
+ /** 把底层异常翻成用户能懂的话 */
10
+ export declare function friendlyError(e: unknown): string;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * 内置数字格式 numFmtId → 格式代码字符串(ECMA-376 §18.8.30)。
3
+ * id 0-49 是保留内置格式;>=164 是自定义格式(从 styles.xml 的 numFmts 取)。
4
+ * 注: 14-22、45-47 等会随 locale 变,这里用通用形态。
5
+ */
6
+ export declare const BUILTIN_FORMATS: Record<number, string>;
7
+ export declare function builtinFormat(id: number): string | undefined;
@@ -0,0 +1,11 @@
1
+ import { CssColor } from '../model/types';
2
+ export declare function argbToCss(argb: string | undefined): CssColor | undefined;
3
+ export declare function indexedToCss(idx: number): CssColor | undefined;
4
+ /** 主题色 + tint → css。tint > 0 变亮,< 0 变暗(按 OOXML 规范的 HSL Luminance 调整)。 */
5
+ export declare function themeToCss(themeColors: CssColor[], themeIdx: number, tint?: number): CssColor | undefined;
6
+ export declare function applyTint(hexColor: CssColor, tint: number): CssColor;
7
+ /**
8
+ * 统一入口: ExcelJS 风格的颜色对象 → css。
9
+ * 形如 { argb }, { theme, tint }, { indexed }。
10
+ */
11
+ export declare function resolveColor(color: any, themeColors: CssColor[]): CssColor | undefined;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Excel 日期序列号 ↔ JS Date。
3
+ *
4
+ * 1900 系统: 序列号 1 = 1900-01-01。但 Excel 误把 1900 当闰年(序列号 60 = 不存在的
5
+ * 1900-02-29),这是为兼容 Lotus 1-2-3 故意保留的 bug。所以 >= 60 的序列号要减 1 天。
6
+ * 1904 系统(老 Mac): 序列号 0 = 1904-01-01,无闰年 bug。
7
+ */
8
+ /** 序列号(可能带小数表示时间) → Date(UTC 基准,渲染按本地读字段) */
9
+ export declare function serialToDate(serial: number, date1904?: boolean): Date;
10
+ /** 取序列号的小数部分对应的一天内秒数(用于纯时间格式) */
11
+ export declare function serialTimePart(serial: number): {
12
+ h: number;
13
+ m: number;
14
+ s: number;
15
+ frac: number;
16
+ };
@@ -0,0 +1,5 @@
1
+ export interface FormatResult {
2
+ text: string;
3
+ color?: string;
4
+ }
5
+ export declare function formatValue(value: number | string | boolean | Date | null, code: string | undefined, date1904?: boolean): FormatResult;