reamkit 1.13.0 → 1.15.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.
- package/README.md +34 -8
- package/dist/esm/core/converter/facade.d.ts +8 -1
- package/dist/esm/core/converter/facade.js +34 -8
- package/dist/esm/core/converter/ream.d.ts +1 -0
- package/dist/esm/core/converter/ream.js +13 -8
- package/dist/esm/core/document-model/types.d.ts +2 -0
- package/dist/esm/core/ir/features.d.ts +1 -0
- package/dist/esm/core/ir/features.js +1 -0
- package/dist/esm/core/ir/sheet.d.ts +42 -3
- package/dist/esm/core/ole/cfb.d.ts +19 -0
- package/dist/esm/core/ole/cfb.js +158 -0
- package/dist/esm/core/spreadsheet-model/index.d.ts +1 -1
- package/dist/esm/core/spreadsheet-model/types.d.ts +81 -1
- package/dist/esm/excel/activex-parser.d.ts +9 -0
- package/dist/esm/excel/activex-parser.js +188 -0
- package/dist/esm/excel/comments-parser.d.ts +4 -0
- package/dist/esm/excel/comments-parser.js +104 -0
- package/dist/esm/excel/conditional-format.d.ts +5 -3
- package/dist/esm/excel/conditional-format.js +248 -12
- package/dist/esm/excel/form-control-parser.d.ts +6 -0
- package/dist/esm/excel/form-control-parser.js +29 -0
- package/dist/esm/excel/formula/context.d.ts +11 -0
- package/dist/esm/excel/formula/dates.d.ts +11 -0
- package/dist/esm/excel/formula/dates.js +46 -0
- package/dist/esm/excel/formula/eval.d.ts +11 -0
- package/dist/esm/excel/formula/eval.js +196 -0
- package/dist/esm/excel/formula/functions.d.ts +7 -0
- package/dist/esm/excel/formula/functions.js +1359 -0
- package/dist/esm/excel/formula/index.d.ts +14 -0
- package/dist/esm/excel/formula/index.js +17 -0
- package/dist/esm/excel/formula/lexer.d.ts +8 -0
- package/dist/esm/excel/formula/lexer.js +163 -0
- package/dist/esm/excel/formula/parser.d.ts +57 -0
- package/dist/esm/excel/formula/parser.js +274 -0
- package/dist/esm/excel/formula/value.d.ts +52 -0
- package/dist/esm/excel/formula/value.js +102 -0
- package/dist/esm/excel/header-footer.d.ts +2 -0
- package/dist/esm/excel/header-footer.js +127 -0
- package/dist/esm/excel/index.d.ts +1 -1
- package/dist/esm/excel/number-format.d.ts +2 -0
- package/dist/esm/excel/number-format.js +5 -1
- package/dist/esm/excel/print-model.d.ts +7 -2
- package/dist/esm/excel/print-model.js +123 -16
- package/dist/esm/excel/shared-strings-parser.d.ts +6 -1
- package/dist/esm/excel/shared-strings-parser.js +91 -12
- package/dist/esm/excel/sheet-drawing.d.ts +13 -1
- package/dist/esm/excel/sheet-drawing.js +47 -14
- package/dist/esm/excel/sheet-shape-parser.d.ts +4 -0
- package/dist/esm/excel/sheet-shape-parser.js +96 -0
- package/dist/esm/excel/sheet-to-flow.d.ts +4 -1
- package/dist/esm/excel/sheet-to-flow.js +170 -3
- package/dist/esm/excel/styles-parser.js +37 -0
- package/dist/esm/excel/worksheet-parser.js +191 -1
- package/dist/esm/excel/xls/biff-chart.d.ts +8 -0
- package/dist/esm/excel/xls/biff-chart.js +121 -0
- package/dist/esm/excel/xls/biff-reader.d.ts +4 -0
- package/dist/esm/excel/xls/biff-reader.js +1418 -0
- package/dist/esm/excel/xls/biff-styles.d.ts +8 -0
- package/dist/esm/excel/xls/biff-styles.js +299 -0
- package/dist/esm/excel/xls/escher.d.ts +24 -0
- package/dist/esm/excel/xls/escher.js +171 -0
- package/dist/esm/excel/xls/xls-reader.d.ts +3 -0
- package/dist/esm/excel/xls/xls-reader.js +30 -0
- package/dist/esm/excel/xlsx-reader.d.ts +2 -1
- package/dist/esm/excel/xlsx-reader.js +134 -16
- package/dist/esm/excel/xlsx-to-pdf.d.ts +1 -0
- package/dist/esm/excel/xlsx-to-pdf.js +2 -2
- package/dist/esm/excel/xlsx-writer.js +12 -2
- package/dist/esm/layout/styled-layout.js +29 -0
- package/dist/esm/pptx/ppt/ppt-reader.d.ts +4 -0
- package/dist/esm/pptx/ppt/ppt-reader.js +337 -0
- package/dist/esm/pptx/ppt/ppt-text.d.ts +69 -0
- package/dist/esm/pptx/ppt/ppt-text.js +756 -0
- package/dist/esm/pptx/slide-parser.d.ts +4 -2
- package/dist/esm/pptx/slide-parser.js +1 -1
- package/dist/esm/word/doc/doc-reader.d.ts +4 -0
- package/dist/esm/word/doc/doc-reader.js +421 -0
- package/dist/esm/word/doc/doc-text.d.ts +79 -0
- package/dist/esm/word/doc/doc-text.js +706 -0
- package/package.json +1 -1
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { emuToPt, pt } from "../core/ir/units.js";
|
|
2
|
+
import { poChildren, poFirstChild, poIntAttr, poIs, poText } from "../core/po-helpers.js";
|
|
3
|
+
import { parseFill, parseLine } from "../word/drawing-parser.js";
|
|
4
|
+
import { parseGeometry, parseTxBody } from "../pptx/slide-parser.js";
|
|
5
|
+
import { parseXml } from "../pptx/pptx-reader.js";
|
|
6
|
+
import { makeColWidthPt, makeRowHeightPt } from "./sheet-drawing.js";
|
|
7
|
+
//#region src/excel/sheet-shape-parser.ts
|
|
8
|
+
var ANCHOR_KINDS = [
|
|
9
|
+
"xdr:twoCellAnchor",
|
|
10
|
+
"xdr:oneCellAnchor",
|
|
11
|
+
"xdr:absoluteAnchor"
|
|
12
|
+
];
|
|
13
|
+
function parseSheetShapes(drawingXml, worksheet, colors) {
|
|
14
|
+
const wsDr = parseXml(drawingXml).find((n) => poIs(n, "xdr:wsDr"));
|
|
15
|
+
if (!wsDr) return [];
|
|
16
|
+
const colWidthPt = makeColWidthPt(worksheet);
|
|
17
|
+
const rowHeightPt = makeRowHeightPt(worksheet);
|
|
18
|
+
const shapes = [];
|
|
19
|
+
for (const anchor of poChildren(wsDr)) {
|
|
20
|
+
if (!ANCHOR_KINDS.some((k) => poIs(anchor, k))) continue;
|
|
21
|
+
const sp = poChildren(anchor).find((c) => poIs(c, "xdr:sp"));
|
|
22
|
+
if (!sp) continue;
|
|
23
|
+
const box = anchorBox(anchor, colWidthPt, rowHeightPt);
|
|
24
|
+
if (!box) continue;
|
|
25
|
+
const spPr = poChildren(sp).find((c) => poIs(c, "xdr:spPr"));
|
|
26
|
+
const geometry = parseGeometry(spPr);
|
|
27
|
+
const fill = spPr ? parseFill(spPr, colors) : { kind: "none" };
|
|
28
|
+
const line = spPr ? parseLine(spPr, colors) : void 0;
|
|
29
|
+
const txBody = poChildren(sp).find((c) => poIs(c, "xdr:txBody"));
|
|
30
|
+
const text = txBody ? parseTxBody(txBody, void 0, void 0, colors, void 0) : void 0;
|
|
31
|
+
const visibleLine = line !== void 0 && line.fill !== "none";
|
|
32
|
+
if (!text && fill.kind === "none" && !visibleLine) continue;
|
|
33
|
+
shapes.push({
|
|
34
|
+
shape: {
|
|
35
|
+
width: pt(box.widthPt),
|
|
36
|
+
height: pt(box.heightPt),
|
|
37
|
+
geometry,
|
|
38
|
+
fill,
|
|
39
|
+
...line ? { line } : {},
|
|
40
|
+
...text ? { text } : {},
|
|
41
|
+
paragraphProperties: {}
|
|
42
|
+
},
|
|
43
|
+
anchorRow: box.anchorRow
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
shapes.sort((a, b) => a.anchorRow - b.anchorRow);
|
|
47
|
+
return shapes.map((s) => s.shape);
|
|
48
|
+
}
|
|
49
|
+
function anchorBox(anchor, colWidthPt, rowHeightPt) {
|
|
50
|
+
const from = marker(poChildren(anchor).find((c) => poIs(c, "xdr:from")));
|
|
51
|
+
if (poIs(anchor, "xdr:twoCellAnchor")) {
|
|
52
|
+
const to = marker(poChildren(anchor).find((c) => poIs(c, "xdr:to")));
|
|
53
|
+
if (!from || !to) return void 0;
|
|
54
|
+
const widthPt = span(from.col, from.colOffPt, to.col, to.colOffPt, colWidthPt);
|
|
55
|
+
const heightPt = span(from.row, from.rowOffPt, to.row, to.rowOffPt, rowHeightPt);
|
|
56
|
+
return widthPt > 0 && heightPt > 0 ? {
|
|
57
|
+
widthPt,
|
|
58
|
+
heightPt,
|
|
59
|
+
anchorRow: from.row
|
|
60
|
+
} : void 0;
|
|
61
|
+
}
|
|
62
|
+
const ext = poChildren(anchor).find((c) => poIs(c, "xdr:ext"));
|
|
63
|
+
if (!ext) return void 0;
|
|
64
|
+
const widthPt = emuToPt(poIntAttr(ext, "cx") ?? 0);
|
|
65
|
+
const heightPt = emuToPt(poIntAttr(ext, "cy") ?? 0);
|
|
66
|
+
return widthPt > 0 && heightPt > 0 ? {
|
|
67
|
+
widthPt,
|
|
68
|
+
heightPt,
|
|
69
|
+
anchorRow: from?.row ?? 0
|
|
70
|
+
} : void 0;
|
|
71
|
+
}
|
|
72
|
+
function marker(node) {
|
|
73
|
+
if (!node) return void 0;
|
|
74
|
+
const col = childInt(node, "xdr:col");
|
|
75
|
+
const row = childInt(node, "xdr:row");
|
|
76
|
+
if (col === void 0 || row === void 0) return void 0;
|
|
77
|
+
return {
|
|
78
|
+
col,
|
|
79
|
+
row,
|
|
80
|
+
colOffPt: emuToPt(childInt(node, "xdr:colOff") ?? 0),
|
|
81
|
+
rowOffPt: emuToPt(childInt(node, "xdr:rowOff") ?? 0)
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function childInt(parent, tag) {
|
|
85
|
+
const child = poFirstChild(parent, tag);
|
|
86
|
+
if (!child) return void 0;
|
|
87
|
+
const n = Number(poText(child));
|
|
88
|
+
return Number.isFinite(n) ? n : void 0;
|
|
89
|
+
}
|
|
90
|
+
function span(from, fromOffPt, to, toOffPt, trackPt) {
|
|
91
|
+
let total = 0;
|
|
92
|
+
for (let i = from; i < to; i++) total += trackPt(i);
|
|
93
|
+
return total - fromOffPt + toOffPt;
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
export { parseSheetShapes };
|
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
import { FlowDoc } from '../core/ir/flow.js';
|
|
2
2
|
import { SheetDoc } from '../core/ir/sheet.js';
|
|
3
|
-
export
|
|
3
|
+
export interface ProjectSheetOptions {
|
|
4
|
+
readonly now?: Date;
|
|
5
|
+
}
|
|
6
|
+
export declare function projectSheetDoc(sheet: SheetDoc, options?: ProjectSheetOptions): FlowDoc;
|
|
@@ -2,14 +2,18 @@ import { pt } from "../core/ir/units.js";
|
|
|
2
2
|
import { EMPTY_STYLE_SHEET, resolveBodyStyles } from "../core/style-cascade/resolver.js";
|
|
3
3
|
import "../core/style-cascade/index.js";
|
|
4
4
|
import { resolvePrintArea, resolvePrintTitleRows, sectionFromWorksheet, slicerTable, worksheetToBody } from "./print-model.js";
|
|
5
|
+
import { buildHeaderFooterContent } from "./header-footer.js";
|
|
5
6
|
//#region src/excel/sheet-to-flow.ts
|
|
6
|
-
|
|
7
|
+
var HEADER_REL = "_xlsxHeaderDefault";
|
|
8
|
+
var FOOTER_REL = "_xlsxFooterDefault";
|
|
9
|
+
function projectSheetDoc(sheet, options = {}) {
|
|
7
10
|
const body = [];
|
|
8
11
|
let firstSheetSection;
|
|
12
|
+
const headersFooters = /* @__PURE__ */ new Map();
|
|
9
13
|
const sheetGrids = new Map(sheet.sheets.map((s) => [s.name, s.grid]));
|
|
10
14
|
for (let sheetIdx = 0; sheetIdx < sheet.sheets.length; sheetIdx++) {
|
|
11
15
|
const ws = sheet.sheets[sheetIdx];
|
|
12
|
-
if (sheetIdx === 0) firstSheetSection = sectionFromWorksheet(ws.grid);
|
|
16
|
+
if (sheetIdx === 0) firstSheetSection = withHeaderFooter(sectionFromWorksheet(ws.grid), ws, headersFooters);
|
|
13
17
|
if (sheetIdx > 0) body.push({
|
|
14
18
|
kind: "paragraph",
|
|
15
19
|
paragraph: {
|
|
@@ -24,7 +28,12 @@ function projectSheetDoc(sheet) {
|
|
|
24
28
|
...printArea ? { printArea } : {},
|
|
25
29
|
...titleRows ? { titleRows } : {},
|
|
26
30
|
gridLines,
|
|
27
|
-
sheetGrids
|
|
31
|
+
sheetGrids,
|
|
32
|
+
sheetName: ws.name,
|
|
33
|
+
definedNames: sheet.definedNames,
|
|
34
|
+
...ws.hyperlinks ? { hyperlinks: ws.hyperlinks } : {},
|
|
35
|
+
...sheet.sharedStringRuns ? { sharedStringRuns: sheet.sharedStringRuns } : {},
|
|
36
|
+
...options.now ? { now: options.now } : {}
|
|
28
37
|
}));
|
|
29
38
|
for (const ref of ws.charts ?? []) body.push({
|
|
30
39
|
kind: "chart",
|
|
@@ -35,10 +44,26 @@ function projectSheetDoc(sheet) {
|
|
|
35
44
|
paragraphProperties: {}
|
|
36
45
|
}
|
|
37
46
|
});
|
|
47
|
+
for (const img of ws.images ?? []) body.push({
|
|
48
|
+
kind: "image",
|
|
49
|
+
image: {
|
|
50
|
+
resource: img.resourceId,
|
|
51
|
+
width: pt(img.widthPt),
|
|
52
|
+
height: pt(img.heightPt),
|
|
53
|
+
paragraphProperties: {}
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
for (const shape of ws.shapes ?? []) body.push({
|
|
57
|
+
kind: "shape",
|
|
58
|
+
shape
|
|
59
|
+
});
|
|
38
60
|
for (const slicer of ws.slicers ?? []) body.push({
|
|
39
61
|
kind: "table",
|
|
40
62
|
table: slicerTable(slicer)
|
|
41
63
|
});
|
|
64
|
+
if (ws.comments && ws.comments.length > 0) body.push(...commentBlocks(ws.comments));
|
|
65
|
+
if (ws.formControls && ws.formControls.length > 0) body.push(...formControlBlocks(ws.formControls));
|
|
66
|
+
if (ws.activeXControls && ws.activeXControls.length > 0) body.push(...activeXBlocks(ws.activeXControls));
|
|
42
67
|
}
|
|
43
68
|
return {
|
|
44
69
|
kind: "flow",
|
|
@@ -48,8 +73,150 @@ function projectSheetDoc(sheet) {
|
|
|
48
73
|
styles: EMPTY_STYLE_SHEET,
|
|
49
74
|
resources: sheet.resources,
|
|
50
75
|
...sheet.chartData && sheet.chartData.size > 0 ? { charts: sheet.chartData } : {},
|
|
76
|
+
...headersFooters.size > 0 ? { headersFooters } : {},
|
|
51
77
|
...sheet.info ? { info: sheet.info } : {}
|
|
52
78
|
};
|
|
53
79
|
}
|
|
80
|
+
function commentBlocks(comments) {
|
|
81
|
+
const out = [{
|
|
82
|
+
kind: "paragraph",
|
|
83
|
+
paragraph: {
|
|
84
|
+
properties: {},
|
|
85
|
+
runs: [{
|
|
86
|
+
text: "Comments",
|
|
87
|
+
properties: { bold: true }
|
|
88
|
+
}]
|
|
89
|
+
}
|
|
90
|
+
}];
|
|
91
|
+
for (const c of comments) {
|
|
92
|
+
const body = c.text.replace(/\s+/g, " ").trim();
|
|
93
|
+
const label = c.author ? `${c.ref} — ${c.author}: ` : `${c.ref}: `;
|
|
94
|
+
out.push({
|
|
95
|
+
kind: "paragraph",
|
|
96
|
+
paragraph: {
|
|
97
|
+
properties: {},
|
|
98
|
+
runs: [{
|
|
99
|
+
text: label,
|
|
100
|
+
properties: { bold: true }
|
|
101
|
+
}, ...body.length > 0 ? [{
|
|
102
|
+
text: body,
|
|
103
|
+
properties: {}
|
|
104
|
+
}] : []]
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
function formControlBlocks(controls) {
|
|
111
|
+
const out = [{
|
|
112
|
+
kind: "paragraph",
|
|
113
|
+
paragraph: {
|
|
114
|
+
properties: {},
|
|
115
|
+
runs: [{
|
|
116
|
+
text: "Form controls",
|
|
117
|
+
properties: { bold: true }
|
|
118
|
+
}]
|
|
119
|
+
}
|
|
120
|
+
}];
|
|
121
|
+
for (const c of controls) out.push({
|
|
122
|
+
kind: "paragraph",
|
|
123
|
+
paragraph: {
|
|
124
|
+
properties: {},
|
|
125
|
+
runs: [{
|
|
126
|
+
text: formControlLabel(c),
|
|
127
|
+
properties: {}
|
|
128
|
+
}]
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
return out;
|
|
132
|
+
}
|
|
133
|
+
function formControlLabel(c) {
|
|
134
|
+
const name = c.name ?? c.objectType ?? "Control";
|
|
135
|
+
switch ((c.objectType ?? "").toLowerCase()) {
|
|
136
|
+
case "checkbox": return `${c.checked ? "[x]" : "[ ]"} ${name}`;
|
|
137
|
+
case "radio": return `${c.checked ? "(o)" : "( )"} ${name}`;
|
|
138
|
+
case "buttons": return `[ ${name} ]`;
|
|
139
|
+
case "spin":
|
|
140
|
+
case "scroll": return c.value !== void 0 ? `${name} (value ${c.value})` : name;
|
|
141
|
+
case "drop":
|
|
142
|
+
case "list": return `${name} (list)`;
|
|
143
|
+
default: return c.objectType ? `${name} (${c.objectType})` : name;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function activeXBlocks(controls) {
|
|
147
|
+
const out = [{
|
|
148
|
+
kind: "paragraph",
|
|
149
|
+
paragraph: {
|
|
150
|
+
properties: {},
|
|
151
|
+
runs: [{
|
|
152
|
+
text: "ActiveX controls",
|
|
153
|
+
properties: { bold: true }
|
|
154
|
+
}]
|
|
155
|
+
}
|
|
156
|
+
}];
|
|
157
|
+
for (const c of controls) out.push({
|
|
158
|
+
kind: "paragraph",
|
|
159
|
+
paragraph: {
|
|
160
|
+
properties: {},
|
|
161
|
+
runs: [{
|
|
162
|
+
text: activeXLabel(c),
|
|
163
|
+
properties: {}
|
|
164
|
+
}]
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
return out;
|
|
168
|
+
}
|
|
169
|
+
function activeXLabel(c) {
|
|
170
|
+
const label = c.caption && c.caption.length > 0 ? c.caption : c.type;
|
|
171
|
+
const on = c.value === "1" || c.value?.toLowerCase() === "true";
|
|
172
|
+
switch (c.type) {
|
|
173
|
+
case "checkbox": return `${on ? "[x]" : "[ ]"} ${label}`;
|
|
174
|
+
case "option": return `${on ? "(o)" : "( )"} ${label}`;
|
|
175
|
+
case "button":
|
|
176
|
+
case "toggle": return `[ ${label} ]`;
|
|
177
|
+
case "textbox": return `[ ${c.value ?? c.caption ?? ""} ]`;
|
|
178
|
+
case "combo":
|
|
179
|
+
case "list": return `${label} (list)`;
|
|
180
|
+
case "spin":
|
|
181
|
+
case "scroll": return c.value !== void 0 ? `${label} (value ${c.value})` : label;
|
|
182
|
+
case "label": return c.caption ?? "Label";
|
|
183
|
+
default: return label;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function withHeaderFooter(section, ws, headersFooters) {
|
|
187
|
+
const hf = ws.grid.headerFooter;
|
|
188
|
+
if (!hf || !hf.oddHeader && !hf.oddFooter) return section;
|
|
189
|
+
const headers = [];
|
|
190
|
+
const footers = [];
|
|
191
|
+
if (hf.oddHeader) {
|
|
192
|
+
const content = buildHeaderFooterContent(hf.oddHeader, ws.name);
|
|
193
|
+
if (content.length > 0) {
|
|
194
|
+
headersFooters.set(HEADER_REL, resolveBodyStyles(content, EMPTY_STYLE_SHEET));
|
|
195
|
+
headers.push({
|
|
196
|
+
type: "default",
|
|
197
|
+
relationshipId: HEADER_REL
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (hf.oddFooter) {
|
|
202
|
+
const content = buildHeaderFooterContent(hf.oddFooter, ws.name);
|
|
203
|
+
if (content.length > 0) {
|
|
204
|
+
headersFooters.set(FOOTER_REL, resolveBodyStyles(content, EMPTY_STYLE_SHEET));
|
|
205
|
+
footers.push({
|
|
206
|
+
type: "default",
|
|
207
|
+
relationshipId: FOOTER_REL
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (headers.length === 0 && footers.length === 0) return section;
|
|
212
|
+
return {
|
|
213
|
+
...section ?? {
|
|
214
|
+
headers: [],
|
|
215
|
+
footers: []
|
|
216
|
+
},
|
|
217
|
+
headers,
|
|
218
|
+
footers
|
|
219
|
+
};
|
|
220
|
+
}
|
|
54
221
|
//#endregion
|
|
55
222
|
export { projectSheetDoc };
|
|
@@ -101,6 +101,12 @@ function parseBorders(root) {
|
|
|
101
101
|
if (right) border.right = right;
|
|
102
102
|
if (bottom) border.bottom = bottom;
|
|
103
103
|
if (left) border.left = left;
|
|
104
|
+
const diagonal = parseBorderEdge(asObject(obj["diagonal"]));
|
|
105
|
+
if (diagonal) {
|
|
106
|
+
border.diagonal = diagonal;
|
|
107
|
+
if (boolAttr(obj, "diagonalUp")) border.diagonalUp = true;
|
|
108
|
+
if (boolAttr(obj, "diagonalDown")) border.diagonalDown = true;
|
|
109
|
+
}
|
|
104
110
|
out.push(border);
|
|
105
111
|
}
|
|
106
112
|
return out;
|
|
@@ -169,6 +175,13 @@ function parseFills(root) {
|
|
|
169
175
|
if (fg) fill.fgColorHex = fg;
|
|
170
176
|
if (bg) fill.bgColorHex = bg;
|
|
171
177
|
}
|
|
178
|
+
if (!fill.patternType) {
|
|
179
|
+
const avg = averageGradientColor(asObject(obj["gradientFill"]));
|
|
180
|
+
if (avg) {
|
|
181
|
+
fill.patternType = "solid";
|
|
182
|
+
fill.fgColorHex = avg;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
172
185
|
out.push(fill);
|
|
173
186
|
}
|
|
174
187
|
return out;
|
|
@@ -205,6 +218,11 @@ function parseCellXfs(root) {
|
|
|
205
218
|
if (h) a.horizontal = h;
|
|
206
219
|
if (v) a.vertical = v;
|
|
207
220
|
if (wrap !== void 0) a.wrapText = wrap;
|
|
221
|
+
const indent = numAttr(align, "indent");
|
|
222
|
+
if (indent !== void 0 && indent > 0) a.indent = indent;
|
|
223
|
+
const rotation = numAttr(align, "textRotation");
|
|
224
|
+
if (rotation !== void 0 && rotation !== 0) a.textRotation = rotation;
|
|
225
|
+
if (boolAttr(align, "shrinkToFit")) a.shrinkToFit = true;
|
|
208
226
|
if (Object.keys(a).length > 0) xf.alignment = a;
|
|
209
227
|
}
|
|
210
228
|
out.push(xf);
|
|
@@ -250,6 +268,25 @@ function childToggle(obj, childName) {
|
|
|
250
268
|
if (val === void 0) return true;
|
|
251
269
|
return !(val === "false" || val === "0");
|
|
252
270
|
}
|
|
271
|
+
function averageGradientColor(gf) {
|
|
272
|
+
if (!gf) return void 0;
|
|
273
|
+
let r = 0;
|
|
274
|
+
let g = 0;
|
|
275
|
+
let b = 0;
|
|
276
|
+
let n = 0;
|
|
277
|
+
for (const s of asArray(gf["stop"])) {
|
|
278
|
+
const so = asObject(s);
|
|
279
|
+
const hex = so ? colorOf(asObject(so["color"])) : void 0;
|
|
280
|
+
if (!hex) continue;
|
|
281
|
+
r += parseInt(hex.slice(0, 2), 16);
|
|
282
|
+
g += parseInt(hex.slice(2, 4), 16);
|
|
283
|
+
b += parseInt(hex.slice(4, 6), 16);
|
|
284
|
+
n++;
|
|
285
|
+
}
|
|
286
|
+
if (n === 0) return void 0;
|
|
287
|
+
const h = (x) => Math.round(x / n).toString(16).padStart(2, "0").toUpperCase();
|
|
288
|
+
return `${h(r)}${h(g)}${h(b)}`;
|
|
289
|
+
}
|
|
253
290
|
function colorOf(node) {
|
|
254
291
|
if (!node) return void 0;
|
|
255
292
|
const rgb = strAttr(node, "rgb");
|
|
@@ -38,6 +38,10 @@ function parseWorksheet(data) {
|
|
|
38
38
|
const drawingRelId = drawingNode && typeof drawingNode === "object" ? strAttr(drawingNode, "id") : void 0;
|
|
39
39
|
const conditionalFormats = parseConditionalFormatting(wsObj);
|
|
40
40
|
const dataValidations = parseDataValidations(wsObj);
|
|
41
|
+
const hyperlinks = parseHyperlinks(wsObj);
|
|
42
|
+
const headerFooter = parseHeaderFooter(wsObj);
|
|
43
|
+
const formControls = parseFormControls(wsObj);
|
|
44
|
+
const oleObjects = parseOleObjects(wsObj);
|
|
41
45
|
const sparklines = parseSparklines(wsObj);
|
|
42
46
|
const tablePartRelIds = parseTableParts(wsObj);
|
|
43
47
|
const printModel = {
|
|
@@ -51,6 +55,10 @@ function parseWorksheet(data) {
|
|
|
51
55
|
...drawingRelId !== void 0 ? { drawingRelId } : {},
|
|
52
56
|
...conditionalFormats.length > 0 ? { conditionalFormats } : {},
|
|
53
57
|
...dataValidations.length > 0 ? { dataValidations } : {},
|
|
58
|
+
...hyperlinks.length > 0 ? { hyperlinks } : {},
|
|
59
|
+
...headerFooter ? { headerFooter } : {},
|
|
60
|
+
...formControls.length > 0 ? { formControls } : {},
|
|
61
|
+
...oleObjects.length > 0 ? { oleObjects } : {},
|
|
54
62
|
...sparklines.length > 0 ? { sparklines } : {},
|
|
55
63
|
...tablePartRelIds.length > 0 ? { tablePartRelIds } : {}
|
|
56
64
|
};
|
|
@@ -354,6 +362,41 @@ function boolAttr(obj, key) {
|
|
|
354
362
|
const raw = strAttr(obj, key);
|
|
355
363
|
return raw === "1" || raw === "true";
|
|
356
364
|
}
|
|
365
|
+
function parseHeaderFooter(ws) {
|
|
366
|
+
const node = asObjectNode(ws["headerFooter"]);
|
|
367
|
+
if (!node) return void 0;
|
|
368
|
+
const oddHeader = formulaText(node["oddHeader"]);
|
|
369
|
+
const oddFooter = formulaText(node["oddFooter"]);
|
|
370
|
+
if (!oddHeader && !oddFooter) return void 0;
|
|
371
|
+
return {
|
|
372
|
+
...oddHeader ? { oddHeader } : {},
|
|
373
|
+
...oddFooter ? { oddFooter } : {}
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
function parseHyperlinks(ws) {
|
|
377
|
+
const node = asObjectNode(ws["hyperlinks"]);
|
|
378
|
+
if (!node) return [];
|
|
379
|
+
const out = [];
|
|
380
|
+
for (const h of toArray(node["hyperlink"])) {
|
|
381
|
+
const obj = asObjectNode(h);
|
|
382
|
+
if (!obj) continue;
|
|
383
|
+
const ref = strAttr(obj, "ref");
|
|
384
|
+
if (!ref) continue;
|
|
385
|
+
const relId = strAttr(obj, "id");
|
|
386
|
+
const location = strAttr(obj, "location");
|
|
387
|
+
if (relId === void 0 && location === void 0) continue;
|
|
388
|
+
const display = strAttr(obj, "display");
|
|
389
|
+
const tooltip = strAttr(obj, "tooltip");
|
|
390
|
+
out.push({
|
|
391
|
+
ref,
|
|
392
|
+
...relId !== void 0 ? { relId } : {},
|
|
393
|
+
...location !== void 0 ? { location } : {},
|
|
394
|
+
...display !== void 0 ? { display } : {},
|
|
395
|
+
...tooltip !== void 0 ? { tooltip } : {}
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
return out;
|
|
399
|
+
}
|
|
357
400
|
function parseSqref(sqref) {
|
|
358
401
|
const out = [];
|
|
359
402
|
for (const token of sqref.split(/\s+/)) {
|
|
@@ -380,14 +423,113 @@ var CF_OPERATORS = new Set([
|
|
|
380
423
|
]);
|
|
381
424
|
function parseCfRule(obj) {
|
|
382
425
|
const priority = parseNumericAttr(obj, "priority") ?? 0;
|
|
383
|
-
|
|
426
|
+
const type = strAttr(obj, "type");
|
|
427
|
+
switch (type) {
|
|
384
428
|
case "cellIs": return parseCellIsRule(obj, priority);
|
|
385
429
|
case "colorScale": return parseColorScaleRule(obj, priority);
|
|
386
430
|
case "dataBar": return parseDataBarRule(obj, priority);
|
|
387
431
|
case "iconSet": return parseIconSetRule(obj, priority);
|
|
432
|
+
case "top10": return parseTop10Rule(obj, priority);
|
|
433
|
+
case "aboveAverage": return parseAboveAverageRule(obj, priority);
|
|
434
|
+
case "duplicateValues":
|
|
435
|
+
case "uniqueValues": return parseDupUniqueRule(type, obj, priority);
|
|
436
|
+
case "containsText":
|
|
437
|
+
case "notContainsText":
|
|
438
|
+
case "beginsWith":
|
|
439
|
+
case "endsWith": return parseTextRule(type, obj, priority);
|
|
440
|
+
case "expression": return parseExpressionRule(obj, priority);
|
|
441
|
+
case "timePeriod": return parseTimePeriodRule(obj, priority);
|
|
388
442
|
default: return;
|
|
389
443
|
}
|
|
390
444
|
}
|
|
445
|
+
var TIME_PERIODS = new Set([
|
|
446
|
+
"today",
|
|
447
|
+
"yesterday",
|
|
448
|
+
"tomorrow",
|
|
449
|
+
"last7Days",
|
|
450
|
+
"thisWeek",
|
|
451
|
+
"lastWeek",
|
|
452
|
+
"nextWeek",
|
|
453
|
+
"thisMonth",
|
|
454
|
+
"lastMonth",
|
|
455
|
+
"nextMonth"
|
|
456
|
+
]);
|
|
457
|
+
function parseExpressionRule(obj, priority) {
|
|
458
|
+
const dxfId = parseNumericAttr(obj, "dxfId");
|
|
459
|
+
if (dxfId === void 0) return void 0;
|
|
460
|
+
const formula = formulaText(obj["formula"]);
|
|
461
|
+
if (formula === void 0) return void 0;
|
|
462
|
+
return {
|
|
463
|
+
type: "expression",
|
|
464
|
+
priority,
|
|
465
|
+
formula,
|
|
466
|
+
dxfId
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
function parseTimePeriodRule(obj, priority) {
|
|
470
|
+
const dxfId = parseNumericAttr(obj, "dxfId");
|
|
471
|
+
if (dxfId === void 0) return void 0;
|
|
472
|
+
const period = strAttr(obj, "timePeriod");
|
|
473
|
+
if (period === void 0 || !TIME_PERIODS.has(period)) return void 0;
|
|
474
|
+
const formula = formulaText(obj["formula"]);
|
|
475
|
+
return {
|
|
476
|
+
type: "timePeriod",
|
|
477
|
+
priority,
|
|
478
|
+
timePeriod: period,
|
|
479
|
+
dxfId,
|
|
480
|
+
...formula !== void 0 ? { formula } : {}
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
function parseTop10Rule(obj, priority) {
|
|
484
|
+
const dxfId = parseNumericAttr(obj, "dxfId");
|
|
485
|
+
if (dxfId === void 0) return void 0;
|
|
486
|
+
return {
|
|
487
|
+
type: "top10",
|
|
488
|
+
priority,
|
|
489
|
+
rank: parseNumericAttr(obj, "rank") ?? 10,
|
|
490
|
+
percent: boolAttr(obj, "percent"),
|
|
491
|
+
bottom: boolAttr(obj, "bottom"),
|
|
492
|
+
dxfId
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
function parseAboveAverageRule(obj, priority) {
|
|
496
|
+
const dxfId = parseNumericAttr(obj, "dxfId");
|
|
497
|
+
if (dxfId === void 0) return void 0;
|
|
498
|
+
const aboveRaw = strAttr(obj, "aboveAverage");
|
|
499
|
+
const aboveAverage = aboveRaw === void 0 ? true : aboveRaw === "1" || aboveRaw === "true";
|
|
500
|
+
const stdDev = parseNumericAttr(obj, "stdDev");
|
|
501
|
+
return {
|
|
502
|
+
type: "aboveAverage",
|
|
503
|
+
priority,
|
|
504
|
+
aboveAverage,
|
|
505
|
+
equalAverage: boolAttr(obj, "equalAverage"),
|
|
506
|
+
...stdDev !== void 0 ? { stdDev } : {},
|
|
507
|
+
dxfId
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
function parseDupUniqueRule(type, obj, priority) {
|
|
511
|
+
const dxfId = parseNumericAttr(obj, "dxfId");
|
|
512
|
+
if (dxfId === void 0) return void 0;
|
|
513
|
+
return {
|
|
514
|
+
type,
|
|
515
|
+
priority,
|
|
516
|
+
dxfId
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
function parseTextRule(type, obj, priority) {
|
|
520
|
+
const dxfId = parseNumericAttr(obj, "dxfId");
|
|
521
|
+
if (dxfId === void 0) return void 0;
|
|
522
|
+
const text = strAttr(obj, "text");
|
|
523
|
+
if (text === void 0) return void 0;
|
|
524
|
+
const formula = formulaText(obj["formula"]);
|
|
525
|
+
return {
|
|
526
|
+
type,
|
|
527
|
+
priority,
|
|
528
|
+
text,
|
|
529
|
+
dxfId,
|
|
530
|
+
...formula !== void 0 ? { formula } : {}
|
|
531
|
+
};
|
|
532
|
+
}
|
|
391
533
|
function parseIconSetRule(obj, priority) {
|
|
392
534
|
const is = obj["iconSet"];
|
|
393
535
|
if (!is || typeof is !== "object") return void 0;
|
|
@@ -545,6 +687,54 @@ function parseSparklines(ws) {
|
|
|
545
687
|
}
|
|
546
688
|
return out;
|
|
547
689
|
}
|
|
690
|
+
function parseFormControls(ws) {
|
|
691
|
+
const out = [];
|
|
692
|
+
const seen = /* @__PURE__ */ new Set();
|
|
693
|
+
collectControls(asObjectNode(ws["controls"]), out, seen);
|
|
694
|
+
for (const ext of toArray(asObjectNode(ws["extLst"])?.["ext"])) collectControls(asObjectNode(asObjectNode(ext)?.["controls"]), out, seen);
|
|
695
|
+
return out;
|
|
696
|
+
}
|
|
697
|
+
function collectControls(node, out, seen) {
|
|
698
|
+
if (!node) return;
|
|
699
|
+
const direct = toArray(node["control"]);
|
|
700
|
+
const fromChoice = toArray(asObjectNode(node["AlternateContent"])?.["Choice"]).flatMap((c) => toArray(asObjectNode(c)?.["control"]));
|
|
701
|
+
for (const c of [...direct, ...fromChoice]) {
|
|
702
|
+
const obj = asObjectNode(c);
|
|
703
|
+
if (!obj) continue;
|
|
704
|
+
const relId = strAttr(obj, "id");
|
|
705
|
+
if (!relId || seen.has(relId)) continue;
|
|
706
|
+
seen.add(relId);
|
|
707
|
+
const name = strAttr(obj, "name");
|
|
708
|
+
out.push({
|
|
709
|
+
relId,
|
|
710
|
+
...name ? { name } : {}
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
function parseOleObjects(ws) {
|
|
715
|
+
const out = [];
|
|
716
|
+
const seen = /* @__PURE__ */ new Set();
|
|
717
|
+
collectOleObjects(asObjectNode(ws["oleObjects"]), out, seen);
|
|
718
|
+
for (const ext of toArray(asObjectNode(ws["extLst"])?.["ext"])) collectOleObjects(asObjectNode(asObjectNode(ext)?.["oleObjects"]), out, seen);
|
|
719
|
+
return out;
|
|
720
|
+
}
|
|
721
|
+
function collectOleObjects(node, out, seen) {
|
|
722
|
+
if (!node) return;
|
|
723
|
+
const direct = toArray(node["oleObject"]);
|
|
724
|
+
const fromChoice = toArray(asObjectNode(node["AlternateContent"])?.["Choice"]).flatMap((c) => toArray(asObjectNode(c)?.["oleObject"]));
|
|
725
|
+
for (const o of [...direct, ...fromChoice]) {
|
|
726
|
+
const obj = asObjectNode(o);
|
|
727
|
+
if (!obj) continue;
|
|
728
|
+
const relId = strAttr(obj, "id");
|
|
729
|
+
if (!relId || seen.has(relId)) continue;
|
|
730
|
+
seen.add(relId);
|
|
731
|
+
const progId = strAttr(obj, "progId");
|
|
732
|
+
out.push({
|
|
733
|
+
relId,
|
|
734
|
+
...progId ? { progId } : {}
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
}
|
|
548
738
|
function asObjectNode(v) {
|
|
549
739
|
return v && typeof v === "object" && !Array.isArray(v) ? v : void 0;
|
|
550
740
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Chart } from '../../core/document-model/index.js';
|
|
2
|
+
import { WorksheetCell } from '../../core/spreadsheet-model/index.js';
|
|
3
|
+
interface Rec {
|
|
4
|
+
readonly type: number;
|
|
5
|
+
readonly data: Uint8Array;
|
|
6
|
+
}
|
|
7
|
+
export declare function parseBiffChart(records: ReadonlyArray<Rec>, cells: ReadonlyArray<WorksheetCell>, sharedStrings: ReadonlyArray<string>): Chart | undefined;
|
|
8
|
+
export {};
|