reamkit 1.30.0 → 1.32.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 +70 -24
- package/dist/esm/core/bidi/index.d.ts +10 -0
- package/dist/esm/core/bidi/index.js +18 -2
- package/dist/esm/core/converter/facade.js +10 -5
- package/dist/esm/core/converter/project.js +4 -1
- package/dist/esm/core/converter/ream.js +17 -6
- package/dist/esm/core/converter/sheet-images.d.ts +17 -0
- package/dist/esm/core/converter/sheet-images.js +33 -0
- package/dist/esm/core/crypto/offcrypto.js +1 -1
- package/dist/esm/core/document-model/index.d.ts +1 -1
- package/dist/esm/core/document-model/types.d.ts +175 -0
- package/dist/esm/core/drawingml/chart-geometry.d.ts +21 -8
- package/dist/esm/core/drawingml/chart-geometry.js +198 -108
- package/dist/esm/core/drawingml/chart-parser.js +73 -2
- package/dist/esm/core/drawingml/colors.d.ts +6 -0
- package/dist/esm/core/drawingml/colors.js +23 -3
- package/dist/esm/core/drawingml/shape-render.d.ts +3 -1
- package/dist/esm/core/drawingml/shape-render.js +4 -2
- package/dist/esm/core/font/index.d.ts +2 -0
- package/dist/esm/core/font/measure.d.ts +9 -0
- package/dist/esm/core/font/measure.js +9 -1
- package/dist/esm/core/font/ttf-build.d.ts +113 -0
- package/dist/esm/core/font/ttf-build.js +1224 -0
- package/dist/esm/core/font/ttf-subset.d.ts +19 -0
- package/dist/esm/core/font/ttf-subset.js +14 -1
- package/dist/esm/core/fonts/families.js +4 -2
- package/dist/esm/core/fonts/provider.d.ts +17 -0
- package/dist/esm/core/fonts/provider.js +27 -2
- package/dist/esm/core/fonts/remote-fonts.js +8 -1
- package/dist/esm/core/fonts/scripts.js +4 -2
- package/dist/esm/core/ir/flow.d.ts +77 -1
- package/dist/esm/core/ir/sheet.d.ts +43 -0
- package/dist/esm/core/number-format.js +16 -11
- package/dist/esm/core/numbering/index.d.ts +1 -1
- package/dist/esm/core/numbering/state.d.ts +11 -1
- package/dist/esm/core/numbering/state.js +10 -1
- package/dist/esm/core/spreadsheet-model/index.d.ts +1 -1
- package/dist/esm/core/spreadsheet-model/types.d.ts +96 -0
- package/dist/esm/core/style-cascade/resolver.js +39 -6
- package/dist/esm/core/style-cascade/types.d.ts +19 -1
- package/dist/esm/core/style-cascade/types.js +3 -0
- package/dist/esm/excel/column-bands.d.ts +39 -6
- package/dist/esm/excel/column-bands.js +41 -17
- package/dist/esm/excel/comments-parser.js +19 -0
- package/dist/esm/excel/conditional-format.d.ts +7 -3
- package/dist/esm/excel/conditional-format.js +77 -39
- package/dist/esm/excel/formula/context.d.ts +18 -0
- package/dist/esm/excel/formula/eval.js +51 -0
- package/dist/esm/excel/formula/index.d.ts +2 -2
- package/dist/esm/excel/formula/lexer.d.ts +1 -1
- package/dist/esm/excel/formula/lexer.js +41 -0
- package/dist/esm/excel/formula/parser.d.ts +25 -0
- package/dist/esm/excel/formula/parser.js +95 -0
- package/dist/esm/excel/print-model.d.ts +38 -1
- package/dist/esm/excel/print-model.js +522 -80
- package/dist/esm/excel/shared-strings-parser.d.ts +9 -0
- package/dist/esm/excel/shared-strings-parser.js +11 -1
- package/dist/esm/excel/sheet-drawing.d.ts +38 -2
- package/dist/esm/excel/sheet-drawing.js +47 -13
- package/dist/esm/excel/sheet-shape-parser.d.ts +6 -2
- package/dist/esm/excel/sheet-shape-parser.js +18 -6
- package/dist/esm/excel/sheet-to-flow.d.ts +17 -0
- package/dist/esm/excel/sheet-to-flow.js +434 -47
- package/dist/esm/excel/styles-parser.d.ts +9 -0
- package/dist/esm/excel/styles-parser.js +80 -26
- package/dist/esm/excel/table-parser.js +5 -0
- package/dist/esm/excel/table-style-presets.d.ts +26 -0
- package/dist/esm/excel/table-style-presets.js +1555 -0
- package/dist/esm/excel/table-style.d.ts +13 -0
- package/dist/esm/excel/table-style.js +75 -0
- package/dist/esm/excel/tint.d.ts +10 -0
- package/dist/esm/excel/tint.js +75 -0
- package/dist/esm/excel/vml-drawing.d.ts +41 -3
- package/dist/esm/excel/vml-drawing.js +143 -10
- package/dist/esm/excel/worksheet-parser.js +89 -15
- package/dist/esm/excel/xls/biff-reader.js +10 -2
- package/dist/esm/excel/xlsx-reader.js +195 -14
- package/dist/esm/excel/xlsx-writer.js +8 -7
- package/dist/esm/html/html-writer.js +202 -20
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/layout/fit-pages.d.ts +11 -0
- package/dist/esm/layout/fit-pages.js +86 -0
- package/dist/esm/layout/line-paint.d.ts +58 -0
- package/dist/esm/layout/line-paint.js +107 -0
- package/dist/esm/layout/page-doc.d.ts +61 -3
- package/dist/esm/layout/page-doc.js +141 -1
- package/dist/esm/layout/styled-layout.d.ts +55 -7
- package/dist/esm/layout/styled-layout.js +1154 -169
- package/dist/esm/layout/turned-section.d.ts +38 -0
- package/dist/esm/layout/turned-section.js +205 -0
- package/dist/esm/markdown/markdown-writer.js +17 -6
- package/dist/esm/pdf/styled-page-emitter.js +114 -60
- package/dist/esm/pdf/styled-page-renderer.js +1 -1
- package/dist/esm/pdf-reader/cff-outline.d.ts +27 -0
- package/dist/esm/pdf-reader/cff-outline.js +169 -21
- package/dist/esm/pdf-reader/content.d.ts +53 -0
- package/dist/esm/pdf-reader/content.js +9 -1
- package/dist/esm/pdf-reader/display.d.ts +36 -0
- package/dist/esm/pdf-reader/display.js +66 -1
- package/dist/esm/pdf-reader/document.js +5 -1
- package/dist/esm/pdf-reader/embedded-fonts.d.ts +2 -1
- package/dist/esm/pdf-reader/embedded-fonts.js +32 -2
- package/dist/esm/pdf-reader/encodings.d.ts +8 -0
- package/dist/esm/pdf-reader/encodings.js +25 -3
- package/dist/esm/pdf-reader/face-outlines.d.ts +78 -0
- package/dist/esm/pdf-reader/face-outlines.js +362 -0
- package/dist/esm/pdf-reader/figures.d.ts +52 -0
- package/dist/esm/pdf-reader/figures.js +433 -0
- package/dist/esm/pdf-reader/flow-build.d.ts +131 -5
- package/dist/esm/pdf-reader/flow-build.js +345 -26
- package/dist/esm/pdf-reader/font.js +321 -36
- package/dist/esm/pdf-reader/glyf-outline.d.ts +33 -0
- package/dist/esm/pdf-reader/glyf-outline.js +135 -1
- package/dist/esm/pdf-reader/glyph-names.js +154 -1
- package/dist/esm/pdf-reader/layout.d.ts +93 -0
- package/dist/esm/pdf-reader/layout.js +1703 -214
- package/dist/esm/pdf-reader/page-numbers.d.ts +53 -0
- package/dist/esm/pdf-reader/page-numbers.js +167 -0
- package/dist/esm/pdf-reader/tagged.js +182 -23
- package/dist/esm/pdf-reader/text.d.ts +6 -3
- package/dist/esm/pdf-reader/text.js +98 -9
- package/dist/esm/pdf-reader/type1-outline.d.ts +11 -0
- package/dist/esm/pdf-reader/type1-outline.js +63 -8
- package/dist/esm/pdf-reader/vector.js +71 -1
- package/dist/esm/svg/svg-text.d.ts +58 -0
- package/dist/esm/svg/svg-text.js +322 -0
- package/dist/esm/svg/svg-writer.js +135 -71
- package/dist/esm/word/doc/doc-reader.js +6 -2
- package/dist/esm/word/doc/doc-text.d.ts +6 -0
- package/dist/esm/word/doc/doc-text.js +19 -1
- package/dist/esm/word/document-parser.d.ts +2 -2
- package/dist/esm/word/document-parser.js +11 -1
- package/dist/esm/word/docx-reader.js +5 -3
- package/dist/esm/word/docx-writer.js +218 -23
- package/dist/esm/word/drawing-parser.d.ts +5 -3
- package/dist/esm/word/drawing-parser.js +49 -8
- package/dist/esm/word/font-embed.d.ts +30 -0
- package/dist/esm/word/font-embed.js +173 -0
- package/dist/esm/word/font-table.d.ts +10 -0
- package/dist/esm/word/font-table.js +13 -1
- package/dist/esm/word/index.js +1 -1
- package/dist/esm/word/numbering-parser.d.ts +3 -1
- package/dist/esm/word/numbering-parser.js +2 -1
- package/dist/esm/word/paragraph-properties.d.ts +7 -6
- package/dist/esm/word/paragraph-properties.js +14 -2
- package/dist/esm/word/run-properties.js +26 -0
- package/package.json +12 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { serialFromDate, timePeriodMatches } from "./formula/dates.js";
|
|
2
|
-
import { BLANK, bool, err, num, str } from "./formula/value.js";
|
|
2
|
+
import { BLANK, bool, err, num, str, toNumber } from "./formula/value.js";
|
|
3
3
|
import { NO_SHIFT, evaluate } from "./formula/eval.js";
|
|
4
4
|
import { compileFormula, evaluateToBool } from "./formula/index.js";
|
|
5
5
|
//#region src/excel/conditional-format.ts
|
|
@@ -23,7 +23,8 @@ import { compileFormula, evaluateToBool } from "./formula/index.js";
|
|
|
23
23
|
* driving `TODAY()`/`NOW()` and the `timePeriod` windows;
|
|
24
24
|
* absent ⇒ those constructs no-op (deterministic output).
|
|
25
25
|
* @param sheetGrids The whole workbook, for an `expression` rule that reaches
|
|
26
|
-
* another sheet (`Sheet2!A1`)
|
|
26
|
+
* another sheet (`Sheet2!A1`), a defined name or a table
|
|
27
|
+
* by its columns (`tblIncome[Amount]`); absent ⇒
|
|
27
28
|
* same-sheet references only.
|
|
28
29
|
* @param currentSheet The rule sheet's name, for resolving sheet-local names.
|
|
29
30
|
* @param definedNames The workbook defined names visible to `expression` rules.
|
|
@@ -31,21 +32,40 @@ import { compileFormula, evaluateToBool } from "./formula/index.js";
|
|
|
31
32
|
function buildConditionalFormatter(conditionalFormats, styles, cells, resolveText, date1904 = false, now, sheetGrids, currentSheet, definedNames) {
|
|
32
33
|
if (!conditionalFormats || conditionalFormats.length === 0) return void 0;
|
|
33
34
|
const dxfs = styles.dxfs ?? [];
|
|
35
|
+
const hasExpr = conditionalFormats.some((cf) => cf.rules.some((r) => r.type === "expression"));
|
|
36
|
+
const formulaStops = conditionalFormats.some((cf) => cf.rules.some((r) => (r.type === "colorScale" || r.type === "dataBar" || r.type === "iconSet") && r.cfvos.some((c) => c.val !== void 0 && !Number.isFinite(Number(c.val)))));
|
|
37
|
+
const nowSerial = now !== void 0 ? serialFromDate(now, date1904) : void 0;
|
|
38
|
+
const cross = (hasExpr || formulaStops) && sheetGrids ? {
|
|
39
|
+
sheets: [...sheetGrids].map(([name, ws]) => ({
|
|
40
|
+
name,
|
|
41
|
+
cells: ws.cells,
|
|
42
|
+
...ws.tables ? { tables: ws.tables } : {}
|
|
43
|
+
})),
|
|
44
|
+
...currentSheet !== void 0 ? { currentSheet } : {},
|
|
45
|
+
definedNames: definedNames ?? []
|
|
46
|
+
} : void 0;
|
|
47
|
+
const ctx = hasExpr || formulaStops ? buildEvalContext(cells, resolveText, nowSerial, date1904, cross) : void 0;
|
|
48
|
+
const stop = ctx ? (formula) => {
|
|
49
|
+
const compiled = compileFormula(formula.startsWith("=") ? formula.slice(1) : formula);
|
|
50
|
+
if (!compiled) return void 0;
|
|
51
|
+
const n = toNumber(evaluate(compiled.ast, ctx, NO_SHIFT), ctx);
|
|
52
|
+
return typeof n === "number" && Number.isFinite(n) ? n : void 0;
|
|
53
|
+
} : void 0;
|
|
34
54
|
const flat = [];
|
|
35
55
|
for (const cf of conditionalFormats) for (const rule of cf.rules) if (rule.type === "colorScale") flat.push({
|
|
36
56
|
ranges: cf.ranges,
|
|
37
57
|
rule,
|
|
38
|
-
scale: resolveColorScale(rule, cf.ranges, cells)
|
|
58
|
+
scale: resolveColorScale(rule, cf.ranges, cells, stop)
|
|
39
59
|
});
|
|
40
60
|
else if (rule.type === "dataBar") flat.push({
|
|
41
61
|
ranges: cf.ranges,
|
|
42
62
|
rule,
|
|
43
|
-
bar: resolveDataBar(rule, cf.ranges, cells)
|
|
63
|
+
bar: resolveDataBar(rule, cf.ranges, cells, stop)
|
|
44
64
|
});
|
|
45
65
|
else if (rule.type === "iconSet") flat.push({
|
|
46
66
|
ranges: cf.ranges,
|
|
47
67
|
rule,
|
|
48
|
-
iconThresholds: resolveIconThresholds(rule, cf.ranges, cells)
|
|
68
|
+
iconThresholds: resolveIconThresholds(rule, cf.ranges, cells, stop)
|
|
49
69
|
});
|
|
50
70
|
else if (rule.type === "top10") flat.push({
|
|
51
71
|
ranges: cf.ranges,
|
|
@@ -78,17 +98,6 @@ function buildConditionalFormatter(conditionalFormats, styles, cells, resolveTex
|
|
|
78
98
|
rule
|
|
79
99
|
});
|
|
80
100
|
flat.sort((a, b) => a.rule.priority - b.rule.priority);
|
|
81
|
-
const hasExpr = flat.some((f) => f.rule.type === "expression");
|
|
82
|
-
const nowSerial = now !== void 0 ? serialFromDate(now, date1904) : void 0;
|
|
83
|
-
const cross = hasExpr && sheetGrids ? {
|
|
84
|
-
sheets: [...sheetGrids].map(([name, ws]) => ({
|
|
85
|
-
name,
|
|
86
|
-
cells: ws.cells
|
|
87
|
-
})),
|
|
88
|
-
...currentSheet !== void 0 ? { currentSheet } : {},
|
|
89
|
-
definedNames: definedNames ?? []
|
|
90
|
-
} : void 0;
|
|
91
|
-
const ctx = hasExpr ? buildEvalContext(cells, resolveText, nowSerial, date1904, cross) : void 0;
|
|
92
101
|
return (row, col, value, text, blank) => {
|
|
93
102
|
if (!hasExpr && value === void 0 && (text === void 0 || text.length === 0)) return;
|
|
94
103
|
const dupKey = blank === true ? void 0 : dupKeyOf(value, text);
|
|
@@ -124,6 +133,7 @@ function buildConditionalFormatter(conditionalFormats, styles, cells, resolveTex
|
|
|
124
133
|
if (!icon && value !== void 0 && iconThresholds) {
|
|
125
134
|
const bucket = iconBucket(iconThresholds, value);
|
|
126
135
|
icon = iconToCell(rule.iconSet, iconThresholds.length, bucket, rule.reverse ?? false);
|
|
136
|
+
if (rule.showValue === false) hideValue = true;
|
|
127
137
|
}
|
|
128
138
|
break;
|
|
129
139
|
case "top10":
|
|
@@ -206,12 +216,34 @@ function buildEvalContext(cells, resolveText, nowSerial, date1904, cross) {
|
|
|
206
216
|
const key = dn.name.toLowerCase();
|
|
207
217
|
if (dn.localSheetId !== void 0 || !nameMap.has(key)) nameMap.set(key, dn);
|
|
208
218
|
}
|
|
219
|
+
const tables = /* @__PURE__ */ new Map();
|
|
220
|
+
const onThisSheet = [];
|
|
221
|
+
cross.sheets.forEach((s, i) => {
|
|
222
|
+
for (const t of s.tables ?? []) {
|
|
223
|
+
const table = {
|
|
224
|
+
...i !== currentIdx ? { sheet: i } : {},
|
|
225
|
+
ref: {
|
|
226
|
+
r0: t.ref.startRow,
|
|
227
|
+
c0: t.ref.startColumn,
|
|
228
|
+
r1: t.ref.endRow,
|
|
229
|
+
c1: t.ref.endColumn
|
|
230
|
+
},
|
|
231
|
+
headerRowCount: t.headerRowCount,
|
|
232
|
+
totalsRowCount: t.totalsRowCount ?? 0,
|
|
233
|
+
columns: t.columns ?? []
|
|
234
|
+
};
|
|
235
|
+
if (t.name !== void 0) tables.set(t.name.toLowerCase(), table);
|
|
236
|
+
if (i === currentIdx) onThisSheet.push(table);
|
|
237
|
+
}
|
|
238
|
+
});
|
|
209
239
|
const resolving = /* @__PURE__ */ new Set();
|
|
210
240
|
const ctx = {
|
|
211
241
|
...base,
|
|
212
242
|
sheetIndex: (name) => sheetByName.get(name.toLowerCase()),
|
|
213
243
|
getCellOn: (sheet, row, col) => sheetData(sheet).byKey.get(row * COLS + col) ?? BLANK,
|
|
214
244
|
eachCellOn: (sheet, rect, visit) => eachInMap(sheetData(sheet), rect, visit),
|
|
245
|
+
table: (name) => tables.get(name.toLowerCase()),
|
|
246
|
+
tableAt: (row, col) => onThisSheet.find((t) => row >= t.ref.r0 && row <= t.ref.r1 && col >= t.ref.c0 && col <= t.ref.c1),
|
|
215
247
|
resolveName: (rawName) => {
|
|
216
248
|
const key = rawName.toLowerCase();
|
|
217
249
|
const dn = nameMap.get(key);
|
|
@@ -222,7 +254,6 @@ function buildEvalContext(cells, resolveText, nowSerial, date1904, cross) {
|
|
|
222
254
|
if (ast.k === "num") return num(ast.v);
|
|
223
255
|
if (ast.k === "str") return str(ast.v);
|
|
224
256
|
if (ast.k === "bool") return bool(ast.v);
|
|
225
|
-
if (ast.k !== "cell" && ast.k !== "range") return void 0;
|
|
226
257
|
resolving.add(key);
|
|
227
258
|
try {
|
|
228
259
|
return evaluate(ast, ctx, NO_SHIFT);
|
|
@@ -358,7 +389,7 @@ function collectRangeValues(cells, ranges) {
|
|
|
358
389
|
}
|
|
359
390
|
return out;
|
|
360
391
|
}
|
|
361
|
-
function resolveColorScale(rule, ranges, cells) {
|
|
392
|
+
function resolveColorScale(rule, ranges, cells, stop) {
|
|
362
393
|
const vals = collectRangeValues(cells, ranges);
|
|
363
394
|
if (vals.length === 0) return void 0;
|
|
364
395
|
const sorted = [...vals].sort((a, b) => a - b);
|
|
@@ -366,7 +397,7 @@ function resolveColorScale(rule, ranges, cells) {
|
|
|
366
397
|
const vmax = sorted[sorted.length - 1];
|
|
367
398
|
const thresholds = [];
|
|
368
399
|
for (const [i, cfvo] of rule.cfvos.entries()) {
|
|
369
|
-
const t = resolveCfvo(cfvo, vmin, vmax, sorted, i === rule.cfvos.length - 1);
|
|
400
|
+
const t = resolveCfvo(cfvo, vmin, vmax, sorted, i === rule.cfvos.length - 1, stop);
|
|
370
401
|
if (t === void 0) return void 0;
|
|
371
402
|
thresholds.push(t);
|
|
372
403
|
}
|
|
@@ -383,24 +414,26 @@ function resolveColorScale(rule, ranges, cells) {
|
|
|
383
414
|
colors
|
|
384
415
|
};
|
|
385
416
|
}
|
|
386
|
-
function resolveCfvo(cfvo, vmin, vmax, sorted, isLast = false) {
|
|
417
|
+
function resolveCfvo(cfvo, vmin, vmax, sorted, isLast = false, stop) {
|
|
418
|
+
const given = () => {
|
|
419
|
+
const n = Number(cfvo.val);
|
|
420
|
+
if (Number.isFinite(n)) return n;
|
|
421
|
+
return cfvo.val !== void 0 ? stop?.(cfvo.val) : void 0;
|
|
422
|
+
};
|
|
387
423
|
switch (cfvo.type) {
|
|
388
424
|
case "min":
|
|
389
425
|
case "autoMin": return vmin;
|
|
390
426
|
case "max":
|
|
391
427
|
case "autoMax": return vmax;
|
|
392
|
-
case "num": return
|
|
393
|
-
case "formula":
|
|
394
|
-
const n = Number(cfvo.val);
|
|
395
|
-
return Number.isFinite(n) ? n : isLast ? vmax : vmin;
|
|
396
|
-
}
|
|
428
|
+
case "num": return given();
|
|
429
|
+
case "formula": return given() ?? (isLast ? vmax : vmin);
|
|
397
430
|
case "percent": {
|
|
398
|
-
const p =
|
|
399
|
-
return
|
|
431
|
+
const p = given();
|
|
432
|
+
return p !== void 0 ? vmin + (vmax - vmin) * (p / 100) : void 0;
|
|
400
433
|
}
|
|
401
434
|
case "percentile": {
|
|
402
|
-
const p =
|
|
403
|
-
return
|
|
435
|
+
const p = given();
|
|
436
|
+
return p !== void 0 ? percentile(sorted, p) : void 0;
|
|
404
437
|
}
|
|
405
438
|
}
|
|
406
439
|
}
|
|
@@ -445,50 +478,55 @@ function rgbHex([r, g, b]) {
|
|
|
445
478
|
const h = (n) => Math.max(0, Math.min(255, Math.round(n))).toString(16).padStart(2, "0").toUpperCase();
|
|
446
479
|
return `${h(r)}${h(g)}${h(b)}`;
|
|
447
480
|
}
|
|
448
|
-
function resolveDataBar(rule, ranges, cells) {
|
|
481
|
+
function resolveDataBar(rule, ranges, cells, stop) {
|
|
449
482
|
const vals = collectRangeValues(cells, ranges);
|
|
450
483
|
if (vals.length === 0) return void 0;
|
|
451
484
|
const sorted = [...vals].sort((a, b) => a - b);
|
|
452
485
|
const vmin = sorted[0];
|
|
453
486
|
const vmax = sorted[sorted.length - 1];
|
|
454
|
-
const lower = resolveCfvo(rule.cfvos[0], vmin, vmax, sorted);
|
|
455
|
-
const upper = resolveCfvo(rule.cfvos[1], vmin, vmax, sorted, true);
|
|
487
|
+
const lower = resolveCfvo(rule.cfvos[0], vmin, vmax, sorted, false, stop);
|
|
488
|
+
const upper = resolveCfvo(rule.cfvos[1], vmin, vmax, sorted, true, stop);
|
|
456
489
|
if (lower === void 0 || upper === void 0) return void 0;
|
|
457
490
|
return {
|
|
458
491
|
lower,
|
|
459
492
|
upper,
|
|
460
493
|
colorHex: rule.colorHex,
|
|
461
494
|
negativeColorHex: "FF0000",
|
|
462
|
-
minLen: (rule.minLength ??
|
|
463
|
-
maxLen: (rule.maxLength ??
|
|
495
|
+
minLen: (rule.minLength ?? 10) / 100,
|
|
496
|
+
maxLen: (rule.maxLength ?? 90) / 100,
|
|
497
|
+
solid: rule.gradient === false
|
|
464
498
|
};
|
|
465
499
|
}
|
|
466
500
|
function dataBarBar(bar, value) {
|
|
501
|
+
const solid = bar.solid ? { solid: true } : {};
|
|
467
502
|
if (bar.lower < 0 && bar.upper > 0) {
|
|
468
503
|
const axis = -bar.lower / (bar.upper - bar.lower);
|
|
469
504
|
if (value >= 0) return {
|
|
470
505
|
fraction: value / bar.upper * (1 - axis),
|
|
471
506
|
colorHex: bar.colorHex,
|
|
472
|
-
startFraction: axis
|
|
507
|
+
startFraction: axis,
|
|
508
|
+
...solid
|
|
473
509
|
};
|
|
474
510
|
const w = Math.abs(value) / Math.abs(bar.lower) * axis;
|
|
475
511
|
return {
|
|
476
512
|
fraction: w,
|
|
477
513
|
colorHex: bar.negativeColorHex,
|
|
478
514
|
startFraction: axis - w,
|
|
479
|
-
negative: true
|
|
515
|
+
negative: true,
|
|
516
|
+
...solid
|
|
480
517
|
};
|
|
481
518
|
}
|
|
482
519
|
return {
|
|
483
520
|
fraction: dataBarFraction(bar, value),
|
|
484
|
-
colorHex: bar.colorHex
|
|
521
|
+
colorHex: bar.colorHex,
|
|
522
|
+
...solid
|
|
485
523
|
};
|
|
486
524
|
}
|
|
487
525
|
function dataBarFraction(bar, value) {
|
|
488
526
|
const t = bar.upper > bar.lower ? Math.min(1, Math.max(0, (value - bar.lower) / (bar.upper - bar.lower))) : value >= bar.upper ? 1 : 0;
|
|
489
527
|
return bar.minLen + t * (bar.maxLen - bar.minLen);
|
|
490
528
|
}
|
|
491
|
-
function resolveIconThresholds(rule, ranges, cells) {
|
|
529
|
+
function resolveIconThresholds(rule, ranges, cells, stop) {
|
|
492
530
|
const vals = collectRangeValues(cells, ranges);
|
|
493
531
|
if (vals.length === 0) return void 0;
|
|
494
532
|
const sorted = [...vals].sort((a, b) => a - b);
|
|
@@ -496,7 +534,7 @@ function resolveIconThresholds(rule, ranges, cells) {
|
|
|
496
534
|
const vmax = sorted[sorted.length - 1];
|
|
497
535
|
const out = [];
|
|
498
536
|
for (const cfvo of rule.cfvos) {
|
|
499
|
-
const t = resolveCfvo(cfvo, vmin, vmax, sorted);
|
|
537
|
+
const t = resolveCfvo(cfvo, vmin, vmax, sorted, false, stop);
|
|
500
538
|
if (t === void 0) return void 0;
|
|
501
539
|
out.push(t);
|
|
502
540
|
}
|
|
@@ -45,4 +45,22 @@ export interface EvalContext {
|
|
|
45
45
|
* Rect, optionally on another sheet) or a literal scalar; undefined ⇒ `#NAME?`.
|
|
46
46
|
*/
|
|
47
47
|
readonly resolveName?: (name: string) => FValue | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* §18.5 — a table by its name (case-insensitive), for a structured reference
|
|
50
|
+
* (`tblIncome[Amount]`); undefined ⇒ `#REF!`.
|
|
51
|
+
*/
|
|
52
|
+
readonly table?: (name: string) => FormulaTable | undefined;
|
|
53
|
+
/** The table a cell stands in, for a reference that names none (`[@Amount]`). */
|
|
54
|
+
readonly tableAt?: (row: number, col: number) => FormulaTable | undefined;
|
|
55
|
+
}
|
|
56
|
+
/** What a structured reference needs of a table (§18.5.1.2). */
|
|
57
|
+
export interface FormulaTable {
|
|
58
|
+
/** The sheet it is on, when not the formula's own; undefined ⇒ the formula's sheet. */
|
|
59
|
+
readonly sheet?: number;
|
|
60
|
+
/** Its whole range — headers, data and totals. */
|
|
61
|
+
readonly ref: Rect;
|
|
62
|
+
readonly headerRowCount: number;
|
|
63
|
+
readonly totalsRowCount: number;
|
|
64
|
+
/** Its columns' names, left to right. */
|
|
65
|
+
readonly columns: ReadonlyArray<string>;
|
|
48
66
|
}
|
|
@@ -56,6 +56,7 @@ function evaluate(ast, ctx, shift) {
|
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
58
|
case "name": return ctx.resolveName?.(ast.name) ?? err("#NAME?");
|
|
59
|
+
case "sref": return structuredRef(ast.ref, ctx, shift);
|
|
59
60
|
case "array": return {
|
|
60
61
|
t: "arr",
|
|
61
62
|
rows: ast.rows.map((row) => row.map((el) => deref(evaluate(el, ctx, shift), ctx)))
|
|
@@ -69,6 +70,56 @@ function evaluate(ast, ctx, shift) {
|
|
|
69
70
|
case "call": return callFn(ast.name, ast.args, (a) => evaluate(a, ctx, shift), ctx, shift);
|
|
70
71
|
}
|
|
71
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* §18.17.6.4 — the cells a structured reference names: the parts of the table
|
|
75
|
+
* it asks for (its data rows when it names none), across the columns it names
|
|
76
|
+
* (all of them when it names none). `#This Row` is the current cell's row.
|
|
77
|
+
*
|
|
78
|
+
* @param ref The reference.
|
|
79
|
+
* @param ctx The evaluation context, which knows the tables.
|
|
80
|
+
* @param shift The current cell, for `#This Row` and for a reference naming no table.
|
|
81
|
+
* @returns The range, or `#REF!` for a table, column or part that is not there.
|
|
82
|
+
*/
|
|
83
|
+
function structuredRef(ref, ctx, shift) {
|
|
84
|
+
const table = ref.table.length > 0 ? ctx.table?.(ref.table) : shift.curRow !== void 0 && shift.curCol !== void 0 ? ctx.tableAt?.(shift.curRow, shift.curCol) : void 0;
|
|
85
|
+
if (!table) return err("#REF!");
|
|
86
|
+
const { r0, c0, r1, c1 } = table.ref;
|
|
87
|
+
const headerEnd = r0 + table.headerRowCount - 1;
|
|
88
|
+
const totalsStart = r1 - table.totalsRowCount + 1;
|
|
89
|
+
const rows = (area) => {
|
|
90
|
+
switch (area) {
|
|
91
|
+
case "#All": return [r0, r1];
|
|
92
|
+
case "#Data": return [headerEnd + 1, totalsStart - 1];
|
|
93
|
+
case "#Headers": return table.headerRowCount > 0 ? [r0, headerEnd] : void 0;
|
|
94
|
+
case "#Totals": return table.totalsRowCount > 0 ? [totalsStart, r1] : void 0;
|
|
95
|
+
case "#This Row": return shift.curRow !== void 0 ? [shift.curRow, shift.curRow] : void 0;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
const spans = (ref.areas.length > 0 ? ref.areas : ["#Data"]).map(rows);
|
|
99
|
+
if (spans.some((s) => s === void 0 || s[1] < s[0])) return err("#REF!");
|
|
100
|
+
const top = Math.min(...spans.map((s) => s[0]));
|
|
101
|
+
const bottom = Math.max(...spans.map((s) => s[1]));
|
|
102
|
+
let left = c0;
|
|
103
|
+
let right = c1;
|
|
104
|
+
if (ref.columns) {
|
|
105
|
+
const at = (name) => table.columns.findIndex((c) => c.toLowerCase() === name.toLowerCase());
|
|
106
|
+
const a = at(ref.columns[0]);
|
|
107
|
+
const b = at(ref.columns[1]);
|
|
108
|
+
if (a < 0 || b < 0) return err("#REF!");
|
|
109
|
+
left = c0 + Math.min(a, b);
|
|
110
|
+
right = c0 + Math.max(a, b);
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
t: "ref",
|
|
114
|
+
rect: {
|
|
115
|
+
r0: top,
|
|
116
|
+
c0: left,
|
|
117
|
+
r1: bottom,
|
|
118
|
+
c1: right
|
|
119
|
+
},
|
|
120
|
+
...table.sheet !== void 0 ? { sheet: table.sheet } : {}
|
|
121
|
+
};
|
|
122
|
+
}
|
|
72
123
|
function resolveRef(ref, shift) {
|
|
73
124
|
const row = ref.row.abs ? ref.row.index : ref.row.index + shift.dRow;
|
|
74
125
|
const col = ref.col.abs ? ref.col.index : ref.col.index + shift.dCol;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Ast } from './parser.js';
|
|
2
2
|
import { EvalContext } from './context.js';
|
|
3
3
|
import { Shift } from './eval.js';
|
|
4
|
-
export type { EvalContext } from './context.js';
|
|
4
|
+
export type { EvalContext, FormulaTable } from './context.js';
|
|
5
5
|
export type { Shift } from './eval.js';
|
|
6
6
|
export type { Scalar, FValue, Rect, FErr } from './value.js';
|
|
7
|
-
export { num, str, bool, err, BLANK } from './value.js';
|
|
7
|
+
export { num, str, bool, err, BLANK, toNumber } from './value.js';
|
|
8
8
|
export { serialFromDate, serialToParts, timePeriodMatches } from './dates.js';
|
|
9
9
|
export { NO_SHIFT, evaluate } from './eval.js';
|
|
10
10
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** The lexical categories the {@link tokenize} pass emits. */
|
|
2
|
-
export type TokenKind = 'num' | 'str' | 'err' | 'word' | 'sheetq' | 'op' | 'eof';
|
|
2
|
+
export type TokenKind = 'num' | 'str' | 'err' | 'word' | 'sheetq' | 'sref' | 'op' | 'eof';
|
|
3
3
|
/** One token: its {@link TokenKind} and the matched source text. */
|
|
4
4
|
export interface Token {
|
|
5
5
|
readonly kind: TokenKind;
|
|
@@ -21,6 +21,29 @@ function isWordPart(ch) {
|
|
|
21
21
|
return isWordStart(ch) || isDigit(ch) || ch === ".";
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
|
+
* Where the bracket group that opens at `start` closes: past its matching `]`,
|
|
25
|
+
* nested groups included. A `'` escapes the character after it — a column
|
|
26
|
+
* named `Q[1]` is written `[Q'[1']]`.
|
|
27
|
+
*
|
|
28
|
+
* @param src The formula source.
|
|
29
|
+
* @param start The index of the opening `[`.
|
|
30
|
+
* @returns The index just past the closing `]`.
|
|
31
|
+
* @throws LexError when the group never closes.
|
|
32
|
+
*/
|
|
33
|
+
function bracketsEnd(src, start) {
|
|
34
|
+
let depth = 0;
|
|
35
|
+
for (let j = start; j < src.length; j++) {
|
|
36
|
+
const c = src[j];
|
|
37
|
+
if (c === "'") {
|
|
38
|
+
j++;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (c === "[") depth++;
|
|
42
|
+
else if (c === "]" && --depth === 0) return j + 1;
|
|
43
|
+
}
|
|
44
|
+
throw new LexError("unclosed [");
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
24
47
|
* Tokenize a formula string into a flat token stream terminated by an `eof`
|
|
25
48
|
* token. Whitespace separates tokens but is otherwise dropped.
|
|
26
49
|
*
|
|
@@ -122,6 +145,15 @@ function tokenize(src) {
|
|
|
122
145
|
if (isWordStart(ch)) {
|
|
123
146
|
let j = i + 1;
|
|
124
147
|
while (j < n && isWordPart(src[j])) j++;
|
|
148
|
+
if (src[j] === "[") {
|
|
149
|
+
const end = bracketsEnd(src, j);
|
|
150
|
+
out.push({
|
|
151
|
+
kind: "sref",
|
|
152
|
+
text: src.slice(i, end)
|
|
153
|
+
});
|
|
154
|
+
i = end;
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
125
157
|
out.push({
|
|
126
158
|
kind: "word",
|
|
127
159
|
text: src.slice(i, j)
|
|
@@ -129,6 +161,15 @@ function tokenize(src) {
|
|
|
129
161
|
i = j;
|
|
130
162
|
continue;
|
|
131
163
|
}
|
|
164
|
+
if (ch === "[") {
|
|
165
|
+
const end = bracketsEnd(src, i);
|
|
166
|
+
out.push({
|
|
167
|
+
kind: "sref",
|
|
168
|
+
text: src.slice(i, end)
|
|
169
|
+
});
|
|
170
|
+
i = end;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
132
173
|
if (ch === "<" && src[i + 1] === "=") {
|
|
133
174
|
out.push({
|
|
134
175
|
kind: "op",
|
|
@@ -15,6 +15,19 @@ export interface CellRef {
|
|
|
15
15
|
readonly col: Axis;
|
|
16
16
|
readonly row: Axis;
|
|
17
17
|
}
|
|
18
|
+
/** A table's part a structured reference names (§18.17.6.4); none named ⇒ `#Data`. */
|
|
19
|
+
export type TableArea = '#All' | '#Data' | '#Headers' | '#Totals' | '#This Row';
|
|
20
|
+
/**
|
|
21
|
+
* §18.17.6.4 — a structured reference: the table (empty for the one the cell
|
|
22
|
+
* is in), the parts of it, and the columns, first to last (all of them when
|
|
23
|
+
* undefined). `tblIncome[Amount]` is `{ table: 'tblIncome', areas: [],
|
|
24
|
+
* columns: ['Amount', 'Amount'] }`.
|
|
25
|
+
*/
|
|
26
|
+
export interface StructuredRef {
|
|
27
|
+
readonly table: string;
|
|
28
|
+
readonly areas: ReadonlyArray<TableArea>;
|
|
29
|
+
readonly columns?: readonly [string, string];
|
|
30
|
+
}
|
|
18
31
|
/** The formula syntax tree — a discriminated union over the node kind `k`. */
|
|
19
32
|
export type Ast = {
|
|
20
33
|
readonly k: 'num';
|
|
@@ -40,6 +53,9 @@ export type Ast = {
|
|
|
40
53
|
} | {
|
|
41
54
|
readonly k: 'name';
|
|
42
55
|
readonly name: string;
|
|
56
|
+
} | {
|
|
57
|
+
readonly k: 'sref';
|
|
58
|
+
readonly ref: StructuredRef;
|
|
43
59
|
} | {
|
|
44
60
|
readonly k: 'array';
|
|
45
61
|
readonly rows: ReadonlyArray<ReadonlyArray<Ast>>;
|
|
@@ -75,3 +91,12 @@ export declare class ParseError extends Error {
|
|
|
75
91
|
* @throws ParseError on a malformed formula (or {@link LexError} from tokenizing).
|
|
76
92
|
*/
|
|
77
93
|
export declare function parse(src: string): Ast;
|
|
94
|
+
/**
|
|
95
|
+
* §18.17.6.4 — read a structured reference's text: `Table[Col]`, `Table[]`,
|
|
96
|
+
* `Table[#Totals]`, `Table[[#Headers],[A]:[C]]`, `[@Col]`, `[@[Col 2]]`.
|
|
97
|
+
*
|
|
98
|
+
* @param text The token: the table's name, if any, and its brackets.
|
|
99
|
+
* @returns The reference.
|
|
100
|
+
* @throws ParseError when the brackets name nothing a table has.
|
|
101
|
+
*/
|
|
102
|
+
export declare function parseStructuredRef(text: string): StructuredRef;
|
|
@@ -148,6 +148,10 @@ var Parser = class {
|
|
|
148
148
|
case "sheetq":
|
|
149
149
|
this.expect("!");
|
|
150
150
|
return this.parseSheetCell(t.text);
|
|
151
|
+
case "sref": return {
|
|
152
|
+
k: "sref",
|
|
153
|
+
ref: parseStructuredRef(t.text)
|
|
154
|
+
};
|
|
151
155
|
case "op":
|
|
152
156
|
if (t.text === "(") {
|
|
153
157
|
const e = this.parseExpr(0);
|
|
@@ -323,5 +327,96 @@ function columnToIndex(letters) {
|
|
|
323
327
|
for (let i = 0; i < up.length; i++) idx = idx * 26 + (up.charCodeAt(i) - 64);
|
|
324
328
|
return idx - 1;
|
|
325
329
|
}
|
|
330
|
+
var AREAS = new Map([
|
|
331
|
+
["#all", "#All"],
|
|
332
|
+
["#data", "#Data"],
|
|
333
|
+
["#headers", "#Headers"],
|
|
334
|
+
["#totals", "#Totals"],
|
|
335
|
+
["#this row", "#This Row"]
|
|
336
|
+
]);
|
|
337
|
+
/**
|
|
338
|
+
* §18.17.6.4 — read a structured reference's text: `Table[Col]`, `Table[]`,
|
|
339
|
+
* `Table[#Totals]`, `Table[[#Headers],[A]:[C]]`, `[@Col]`, `[@[Col 2]]`.
|
|
340
|
+
*
|
|
341
|
+
* @param text The token: the table's name, if any, and its brackets.
|
|
342
|
+
* @returns The reference.
|
|
343
|
+
* @throws ParseError when the brackets name nothing a table has.
|
|
344
|
+
*/
|
|
345
|
+
function parseStructuredRef(text) {
|
|
346
|
+
const open = text.indexOf("[");
|
|
347
|
+
const table = text.slice(0, open);
|
|
348
|
+
let inner = text.slice(open + 1, -1).trim();
|
|
349
|
+
const areas = [];
|
|
350
|
+
let columns;
|
|
351
|
+
if (inner.startsWith("@")) {
|
|
352
|
+
areas.push("#This Row");
|
|
353
|
+
inner = inner.slice(1).trim();
|
|
354
|
+
if (inner.length > 0 && !inner.startsWith("[")) inner = `[${inner}]`;
|
|
355
|
+
} else if (inner.length > 0 && !inner.startsWith("[")) inner = `[${inner}]`;
|
|
356
|
+
for (const item of splitTopLevel(inner)) {
|
|
357
|
+
const range = splitRange(item);
|
|
358
|
+
if (range) {
|
|
359
|
+
columns = [unescapeName(range[0]), unescapeName(range[1])];
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
const body = item.slice(1, -1);
|
|
363
|
+
const area = AREAS.get(body.trim().toLowerCase());
|
|
364
|
+
if (area) areas.push(area);
|
|
365
|
+
else {
|
|
366
|
+
const name = unescapeName(body);
|
|
367
|
+
columns = [name, name];
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return {
|
|
371
|
+
table,
|
|
372
|
+
areas,
|
|
373
|
+
...columns ? { columns } : {}
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
/** The bracket groups of a list `[a],[b]:[c]`, each with its `:` partner. */
|
|
377
|
+
function splitTopLevel(inner) {
|
|
378
|
+
const out = [];
|
|
379
|
+
let depth = 0;
|
|
380
|
+
let start = 0;
|
|
381
|
+
for (let i = 0; i < inner.length; i++) {
|
|
382
|
+
const c = inner[i];
|
|
383
|
+
if (c === "'") {
|
|
384
|
+
i++;
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
if (c === "[") depth++;
|
|
388
|
+
else if (c === "]") depth--;
|
|
389
|
+
else if (c === "," && depth === 0) {
|
|
390
|
+
out.push(inner.slice(start, i).trim());
|
|
391
|
+
start = i + 1;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
const last = inner.slice(start).trim();
|
|
395
|
+
if (last.length > 0) out.push(last);
|
|
396
|
+
for (const item of out) if (!item.startsWith("[") || !item.endsWith("]")) throw new ParseError(`bad structured reference part ${item}`);
|
|
397
|
+
return out;
|
|
398
|
+
}
|
|
399
|
+
/** `[A]:[C]` → the two columns' bracketed bodies, or undefined for one group. */
|
|
400
|
+
function splitRange(item) {
|
|
401
|
+
let depth = 0;
|
|
402
|
+
for (let i = 0; i < item.length; i++) {
|
|
403
|
+
const c = item[i];
|
|
404
|
+
if (c === "'") {
|
|
405
|
+
i++;
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
if (c === "[") depth++;
|
|
409
|
+
else if (c === "]") depth--;
|
|
410
|
+
else if (c === ":" && depth === 0) {
|
|
411
|
+
const a = item.slice(0, i).trim();
|
|
412
|
+
const b = item.slice(i + 1).trim();
|
|
413
|
+
return [a.slice(1, -1), b.slice(1, -1)];
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
/** A column name as written in a reference, its `'` escapes undone. */
|
|
418
|
+
function unescapeName(name) {
|
|
419
|
+
return name.trim().replace(/'(.)/g, "$1");
|
|
420
|
+
}
|
|
326
421
|
//#endregion
|
|
327
422
|
export { parse };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { BodyElement, SectionProperties, Table } from '../core/document-model/index.js';
|
|
1
|
+
import { BodyElement, CellNoteFlag, SectionProperties, Table } from '../core/document-model/index.js';
|
|
2
2
|
import { CellRange, DefinedName, ParsedWorksheet, SheetRichRun, WorksheetCell, XlsxStyles } from './index.js';
|
|
3
3
|
import { SheetHyperlink, SheetSlicer } from '../core/ir/sheet.js';
|
|
4
4
|
import { Loss } from '../core/ir/loss.js';
|
|
5
|
+
import { DrawingBox } from './column-bands.js';
|
|
5
6
|
/**
|
|
6
7
|
* Excel "character width" → twips: the default font's Maximum Digit Width,
|
|
7
8
|
* ~7 px at 96 DPI ≈ 5.25 pt ≈ 105 twips.
|
|
@@ -36,11 +37,37 @@ export declare const COL_PADDING_TWIPS = 75;
|
|
|
36
37
|
* @returns The rendered column width in twips.
|
|
37
38
|
*/
|
|
38
39
|
export declare function columnTwips(chars: number, charTwips: number): number;
|
|
40
|
+
/**
|
|
41
|
+
* §18.3.1.81 — the DEFAULT column, in twips: the sheet's `defaultColWidth`
|
|
42
|
+
* where it declares one — a stored width, padding included — and otherwise
|
|
43
|
+
* `baseColWidth` digits and their padding, rounded up to Excel's step of eight
|
|
44
|
+
* pixels. Padding a `baseColWidth` twice once stood in for that rounding: it
|
|
45
|
+
* gives 47668.xlsx's 80px as well, and nothing else.
|
|
46
|
+
*
|
|
47
|
+
* @param worksheet The sheet.
|
|
48
|
+
* @param charTwips The Maximum Digit Width, in twips.
|
|
49
|
+
* @returns The default column width in twips.
|
|
50
|
+
*/
|
|
51
|
+
export declare function defaultColumnTwips(worksheet: ParsedWorksheet, charTwips: number): number;
|
|
39
52
|
/**
|
|
40
53
|
* Excel's default column width is 8.43 "characters" ≈ 64px ≈ 960 twips. Used for
|
|
41
54
|
* columns without an explicit `<col width="..">`.
|
|
42
55
|
*/
|
|
43
56
|
export declare const DEFAULT_COL_TWIPS = 960;
|
|
57
|
+
/**
|
|
58
|
+
* §18.3.1.13 — the unit a sheet's columns are measured in: the Maximum Digit
|
|
59
|
+
* Width of the workbook's Normal font, in twips — the font's own where the
|
|
60
|
+
* workbook names it, the face we render with where it names none. A drawing's
|
|
61
|
+
* anchor counts columns in the same unit, or it lands beside the cells it is
|
|
62
|
+
* anchored to: 45540_form_Footer.xlsx sets its form in 宋体 12, whose digit
|
|
63
|
+
* is 8px, and anchored at Excel's 7px its check boxes stood a column off
|
|
64
|
+
* their labels.
|
|
65
|
+
*
|
|
66
|
+
* @param styles The workbook's styles (its first font is the Normal style's).
|
|
67
|
+
* @param digitWidthPt The render font's digit width, for a workbook that names no font.
|
|
68
|
+
* @returns The unit, in twips.
|
|
69
|
+
*/
|
|
70
|
+
export declare function columnUnitTwips(styles: XlsxStyles, digitWidthPt?: number): number;
|
|
44
71
|
/**
|
|
45
72
|
* The row height a sheet that declares none inherits from the workbook's
|
|
46
73
|
* Normal font. Sizes outside Excel's table scale from its 10pt entry and snap
|
|
@@ -94,6 +121,8 @@ export declare function printableWidthPt(worksheet: ParsedWorksheet): number;
|
|
|
94
121
|
*/
|
|
95
122
|
export declare function printableHeightPt(worksheet: ParsedWorksheet): number;
|
|
96
123
|
interface PrintModelOptions {
|
|
124
|
+
readonly screen?: boolean;
|
|
125
|
+
readonly image?: boolean;
|
|
97
126
|
readonly printArea?: CellRange;
|
|
98
127
|
readonly gridLines: boolean;
|
|
99
128
|
readonly titleRows?: {
|
|
@@ -114,10 +143,16 @@ interface PrintModelOptions {
|
|
|
114
143
|
readonly bandSink?: {
|
|
115
144
|
lefts: Array<number>;
|
|
116
145
|
};
|
|
146
|
+
readonly headingSink?: {
|
|
147
|
+
dxPt: number;
|
|
148
|
+
dyPt: number;
|
|
149
|
+
};
|
|
150
|
+
readonly noteFlags?: ReadonlyMap<string, CellNoteFlag>;
|
|
117
151
|
readonly drawingExtentPt?: {
|
|
118
152
|
readonly widthPt: number;
|
|
119
153
|
readonly heightPt: number;
|
|
120
154
|
};
|
|
155
|
+
readonly drawingBoxesPt?: ReadonlyArray<DrawingBox>;
|
|
121
156
|
readonly losses?: Array<Loss>;
|
|
122
157
|
}
|
|
123
158
|
/**
|
|
@@ -149,6 +184,8 @@ export declare function worksheetToBody(worksheet: ParsedWorksheet, sharedString
|
|
|
149
184
|
* @returns The resolved display string.
|
|
150
185
|
*/
|
|
151
186
|
export declare function resolveCellText(cell: WorksheetCell, sharedStrings: ReadonlyArray<string>, styles: XlsxStyles, date1904: boolean): string;
|
|
187
|
+
/** The key {@link PrintModelOptions.noteFlags} is looked up by: absolute row and column. */
|
|
188
|
+
export declare function noteKey(row: number, col: number): string;
|
|
152
189
|
/**
|
|
153
190
|
* Whether an EMPTY cell still draws something of its own — a fill or a border.
|
|
154
191
|
*
|