@shbernal/ts-xlsx 3.1.0 → 3.2.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 +30 -23
- package/dist/bytes.d.ts +3 -2
- package/dist/core/address.d.ts +36 -0
- package/dist/core/address.js +47 -9
- package/dist/core/array-formula-ranges.d.ts +33 -0
- package/dist/core/array-formula-ranges.js +62 -0
- package/dist/core/color-resolution.js +2 -2
- package/dist/core/column.js +3 -2
- package/dist/core/comment-thread.d.ts +7 -3
- package/dist/core/conditional-formatting-overlay.d.ts +9 -0
- package/dist/core/conditional-formatting-overlay.js +28 -1
- package/dist/core/conditional-formatting.d.ts +98 -10
- package/dist/core/conditional-formatting.js +42 -1
- package/dist/core/data-validation-overlay.d.ts +5 -0
- package/dist/core/data-validation-overlay.js +15 -0
- package/dist/core/data-validation.d.ts +16 -0
- package/dist/core/data-validation.js +15 -0
- package/dist/core/date-format.js +14 -4
- package/dist/core/date.js +1 -1
- package/dist/core/formula-references.d.ts +26 -0
- package/dist/core/formula-references.js +173 -0
- package/dist/core/formula-scan.d.ts +2 -0
- package/dist/core/formula-scan.js +58 -0
- package/dist/core/formula.d.ts +51 -18
- package/dist/core/formula.js +77 -86
- package/dist/core/function-values.d.ts +4 -0
- package/dist/core/function-values.js +58 -0
- package/dist/core/future-functions.d.ts +3 -0
- package/dist/core/{modern-functions.js → future-functions.js} +119 -88
- package/dist/core/grid-edits.d.ts +28 -0
- package/dist/core/grid-edits.js +193 -25
- package/dist/core/hyperlink.d.ts +39 -0
- package/dist/core/hyperlink.js +88 -0
- package/dist/core/image.d.ts +36 -5
- package/dist/core/image.js +9 -0
- package/dist/core/internal.d.ts +3 -1
- package/dist/core/limits.d.ts +5 -3
- package/dist/core/merge.d.ts +13 -0
- package/dist/core/merge.js +15 -1
- package/dist/core/page-setup.d.ts +26 -11
- package/dist/core/pivot-table.d.ts +49 -10
- package/dist/core/pivot-table.js +55 -21
- package/dist/core/protection.d.ts +66 -4
- package/dist/core/protection.js +4 -0
- package/dist/core/row.js +3 -2
- package/dist/core/structured-reference.d.ts +7 -0
- package/dist/core/structured-reference.js +7 -0
- package/dist/core/table.d.ts +38 -8
- package/dist/core/table.js +37 -7
- package/dist/core/theme.d.ts +2 -0
- package/dist/core/theme.js +4 -1
- package/dist/core/value.d.ts +51 -28
- package/dist/core/value.js +15 -12
- package/dist/core/workbook-styles.d.ts +17 -1
- package/dist/core/workbook-styles.js +4 -0
- package/dist/core/workbook-theme.js +5 -3
- package/dist/core/workbook.d.ts +20 -3
- package/dist/core/workbook.js +26 -5
- package/dist/core/worksheet-merges.d.ts +9 -4
- package/dist/core/worksheet-merges.js +17 -11
- package/dist/core/worksheet-model.d.ts +1 -1
- package/dist/core/worksheet-model.js +4 -0
- package/dist/core/worksheet-pictures.d.ts +3 -3
- package/dist/core/worksheet-pictures.js +7 -6
- package/dist/core/worksheet.d.ts +110 -21
- package/dist/core/worksheet.js +174 -49
- package/dist/entries/core.d.ts +7 -5
- package/dist/entries/core.js +4 -3
- package/dist/entries/errors.d.ts +1 -0
- package/dist/entries/errors.js +1 -0
- package/dist/errors.js +1 -1
- package/dist/io/cell-metadata/metadata.d.ts +42 -0
- package/dist/io/cell-metadata/metadata.js +35 -0
- package/dist/io/cell-metadata/rich-values.d.ts +11 -0
- package/dist/io/cell-metadata/rich-values.js +80 -0
- package/dist/io/csv/delimiter.d.ts +14 -2
- package/dist/io/csv/delimiter.js +12 -0
- package/dist/io/csv/errors.d.ts +14 -0
- package/dist/io/csv/errors.js +5 -0
- package/dist/io/csv/read.d.ts +6 -1
- package/dist/io/csv/read.js +46 -24
- package/dist/io/csv/write.d.ts +10 -3
- package/dist/io/csv/write.js +16 -7
- package/dist/io/opc/part-paths.js +4 -4
- package/dist/io/opc/read-opc.d.ts +4 -0
- package/dist/io/opc/read-opc.js +10 -4
- package/dist/io/opc/strict-relationships.d.ts +2 -0
- package/dist/io/opc/strict-relationships.js +12 -0
- package/dist/io/read-policy/column-budget.d.ts +26 -0
- package/dist/io/{xlsx → read-policy}/column-budget.js +4 -8
- package/dist/io/read-policy/read-repair.d.ts +74 -0
- package/dist/io/read-policy/read-repair.js +119 -0
- package/dist/io/style/cell-style-resolution.d.ts +25 -0
- package/dist/io/style/cell-style-resolution.js +30 -0
- package/dist/io/xlsb/formula.js +4 -2
- package/dist/io/xlsb/ptg-functions.js +110 -0
- package/dist/io/xlsb/read-metadata.d.ts +7 -0
- package/dist/io/xlsb/read-metadata.js +69 -0
- package/dist/io/xlsb/read-worksheet.d.ts +6 -0
- package/dist/io/xlsb/read-worksheet.js +95 -37
- package/dist/io/xlsb/read.js +26 -8
- package/dist/io/xlsb/record-types.d.ts +13 -0
- package/dist/io/xlsb/record-types.js +13 -0
- package/dist/io/xlsb/sheet-protection.d.ts +20 -0
- package/dist/io/xlsb/sheet-protection.js +60 -0
- package/dist/io/xlsx/cell-accumulator.d.ts +20 -12
- package/dist/io/xlsx/cell-accumulator.js +49 -19
- package/dist/io/xlsx/cell-metadata.d.ts +39 -0
- package/dist/io/xlsx/cell-metadata.js +162 -0
- package/dist/io/xlsx/cell-value.d.ts +16 -4
- package/dist/io/xlsx/cell-value.js +38 -21
- package/dist/io/xlsx/color-xml.js +1 -1
- package/dist/io/xlsx/column-span.d.ts +11 -0
- package/dist/io/xlsx/column-span.js +9 -0
- package/dist/io/xlsx/comments.d.ts +3 -28
- package/dist/io/xlsx/comments.js +3 -65
- package/dist/io/xlsx/conditional-formatting.d.ts +42 -25
- package/dist/io/xlsx/conditional-formatting.js +424 -129
- package/dist/io/xlsx/data-validation.d.ts +12 -7
- package/dist/io/xlsx/data-validation.js +41 -29
- package/dist/io/xlsx/edit-vba.js +43 -36
- package/dist/io/xlsx/hyperlinks.d.ts +16 -50
- package/dist/io/xlsx/hyperlinks.js +8 -37
- package/dist/io/xlsx/images.d.ts +49 -16
- package/dist/io/xlsx/images.js +145 -44
- package/dist/io/xlsx/namespaces.d.ts +8 -0
- package/dist/io/xlsx/namespaces.js +4 -0
- package/dist/io/xlsx/package-plan.d.ts +48 -15
- package/dist/io/xlsx/package-plan.js +46 -9
- package/dist/io/xlsx/part-names.d.ts +6 -8
- package/dist/io/xlsx/part-names.js +3 -7
- package/dist/io/xlsx/pivot.d.ts +5 -5
- package/dist/io/xlsx/pivot.js +23 -22
- package/dist/io/xlsx/preserved-splices.d.ts +6 -0
- package/dist/io/xlsx/preserved-splices.js +74 -0
- package/dist/io/xlsx/read-comments.d.ts +29 -0
- package/dist/io/xlsx/read-comments.js +75 -0
- package/dist/io/xlsx/read-parts.d.ts +2 -2
- package/dist/io/xlsx/read-parts.js +44 -37
- package/dist/io/xlsx/read-pivot.js +9 -3
- package/dist/io/xlsx/read-rich-runs.d.ts +8 -5
- package/dist/io/xlsx/read-rich-runs.js +18 -1
- package/dist/io/xlsx/read-rows.d.ts +18 -7
- package/dist/io/xlsx/read-rows.js +47 -37
- package/dist/io/xlsx/read-styles.d.ts +0 -25
- package/dist/io/xlsx/read-styles.js +39 -34
- package/dist/io/xlsx/read-workbook-xml.d.ts +6 -0
- package/dist/io/xlsx/read-workbook-xml.js +9 -4
- package/dist/io/xlsx/read-worksheet.d.ts +8 -3
- package/dist/io/xlsx/read-worksheet.js +45 -23
- package/dist/io/xlsx/read.d.ts +0 -4
- package/dist/io/xlsx/read.js +17 -21
- package/dist/io/xlsx/relationships.d.ts +3 -0
- package/dist/io/xlsx/relationships.js +4 -0
- package/dist/io/xlsx/row-position.d.ts +3 -1
- package/dist/io/xlsx/row-xml.d.ts +18 -7
- package/dist/io/xlsx/row-xml.js +54 -35
- package/dist/io/xlsx/sheet-properties.js +68 -42
- package/dist/io/xlsx/strict-parts.d.ts +7 -0
- package/dist/io/xlsx/strict-parts.js +171 -0
- package/dist/io/xlsx/style-elements.d.ts +0 -2
- package/dist/io/xlsx/style-elements.js +9 -29
- package/dist/io/xlsx/styles.d.ts +5 -0
- package/dist/io/xlsx/styles.js +11 -5
- package/dist/io/xlsx/tables.d.ts +10 -2
- package/dist/io/xlsx/tables.js +49 -42
- package/dist/io/xlsx/theme-xml.d.ts +6 -0
- package/dist/io/xlsx/theme-xml.js +16 -19
- package/dist/io/xlsx/threaded-comments.d.ts +6 -1
- package/dist/io/xlsx/threaded-comments.js +14 -7
- package/dist/io/xlsx/workbook-xml.d.ts +13 -24
- package/dist/io/xlsx/workbook-xml.js +15 -33
- package/dist/io/xlsx/worksheet-xml.d.ts +5 -2
- package/dist/io/xlsx/worksheet-xml.js +37 -69
- package/dist/io/xlsx/write-stream.d.ts +28 -6
- package/dist/io/xlsx/write-stream.js +42 -17
- package/dist/io/xlsx/write.d.ts +11 -4
- package/dist/io/xlsx/write.js +153 -90
- package/dist/rel-type.d.ts +9 -0
- package/dist/rel-type.js +3 -0
- package/dist/vba/bytes.d.ts +2 -0
- package/dist/vba/bytes.js +11 -0
- package/dist/vba/cfb-format.d.ts +47 -0
- package/dist/vba/cfb-format.js +34 -0
- package/dist/vba/cfb-writer.d.ts +1 -2
- package/dist/vba/cfb-writer.js +33 -36
- package/dist/vba/cfb.d.ts +9 -4
- package/dist/vba/cfb.js +55 -43
- package/dist/vba/dir-records.d.ts +6 -0
- package/dist/vba/dir-records.js +10 -2
- package/dist/vba/errors.d.ts +4 -4
- package/dist/vba/index.d.ts +0 -2
- package/dist/vba/index.js +0 -2
- package/dist/vba/ms-ovba.d.ts +6 -2
- package/dist/vba/ms-ovba.js +15 -6
- package/dist/vba/project-editor.js +102 -87
- package/dist/vba/project.d.ts +4 -0
- package/dist/vba/project.js +12 -6
- package/dist/vba/vba-encoding.d.ts +4 -10
- package/dist/vba/vba-encoding.js +2 -15
- package/dist/xml/xml-read.d.ts +29 -1
- package/dist/xml/xml-read.js +56 -0
- package/dist/xml/xml-scan.d.ts +13 -0
- package/dist/xml/xml-scan.js +58 -7
- package/dist/xml/xml.d.ts +33 -1
- package/dist/xml/xml.js +22 -0
- package/package.json +5 -4
- package/skills/ts-xlsx-upstream/SKILL.md +21 -13
- package/dist/core/modern-functions.d.ts +0 -1
- package/dist/io/xlsx/cell-style-resolution.d.ts +0 -25
- package/dist/io/xlsx/cell-style-resolution.js +0 -29
- package/dist/io/xlsx/column-budget.d.ts +0 -26
- package/dist/io/xlsx/read-repair.d.ts +0 -26
- package/dist/io/xlsx/read-repair.js +0 -39
package/dist/core/table.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { AuthoringError, quoted } from '../errors.js';
|
|
2
2
|
import { tokenSet } from '../token-set.js';
|
|
3
|
-
import { decodeCellRef, encodeAddress, encodeRect, MAX_COLUMN, MAX_ROW, numberToColumn, } from './address.js';
|
|
3
|
+
import { decodeCellRef, encodeAddress, encodeRect, MAX_COLUMN, MAX_ROW, nameReadsAsReference, numberToColumn, } from './address.js';
|
|
4
4
|
import { cloneWith } from './clone.js';
|
|
5
5
|
import { isDeletedSpan, shiftIndex } from './grid-shift.js';
|
|
6
|
+
import { INTERNAL } from './internal.js';
|
|
6
7
|
import { MAX_TABLE_NAME_LENGTH, TABLE_NAME_PATTERN } from './limits.js';
|
|
8
|
+
import { structuredColumnReference } from './structured-reference.js';
|
|
7
9
|
const STYLE_INFO_CLONE = {
|
|
8
10
|
name: (name) => (name === 'None' ? undefined : name),
|
|
9
11
|
showFirstColumn: 'value',
|
|
@@ -11,6 +13,12 @@ const STYLE_INFO_CLONE = {
|
|
|
11
13
|
showRowStripes: 'value',
|
|
12
14
|
showColumnStripes: 'value',
|
|
13
15
|
};
|
|
16
|
+
export const TABLE_STYLE_FLAGS = [
|
|
17
|
+
'showFirstColumn',
|
|
18
|
+
'showLastColumn',
|
|
19
|
+
'showRowStripes',
|
|
20
|
+
'showColumnStripes',
|
|
21
|
+
];
|
|
14
22
|
function cloneStyleInfo(style) {
|
|
15
23
|
const clone = cloneWith(style, STYLE_INFO_CLONE);
|
|
16
24
|
if (clone.name === undefined)
|
|
@@ -57,11 +65,13 @@ function validateTableName(name) {
|
|
|
57
65
|
throw new SyntaxError(`table name ${quoted(name)} is not a valid Excel identifier: it must start with a letter, ` +
|
|
58
66
|
'underscore, or backslash and contain only letters, digits, periods, and underscores');
|
|
59
67
|
}
|
|
68
|
+
if (nameReadsAsReference(name)) {
|
|
69
|
+
throw new SyntaxError(`table name ${quoted(name)} reads as a cell reference, an R1C1 reference or a boolean, ` +
|
|
70
|
+
'which Excel does not accept as a name');
|
|
71
|
+
}
|
|
60
72
|
}
|
|
61
73
|
export class Table {
|
|
62
74
|
name;
|
|
63
|
-
displayName;
|
|
64
|
-
columns;
|
|
65
75
|
headerRow;
|
|
66
76
|
totalsRow;
|
|
67
77
|
totalsRowShown;
|
|
@@ -70,7 +80,24 @@ export class Table {
|
|
|
70
80
|
#anchorCol;
|
|
71
81
|
#anchorRow;
|
|
72
82
|
#dataRowCount;
|
|
83
|
+
#columns;
|
|
73
84
|
#grid;
|
|
85
|
+
[INTERNAL] = {
|
|
86
|
+
rewriteFormulas: (rewrite) => {
|
|
87
|
+
this.#columns = this.#columns.map((column) => {
|
|
88
|
+
const { calculatedColumnFormula: calculated, totalsRowFormula: totals } = column;
|
|
89
|
+
const nextCalculated = calculated === undefined ? undefined : rewrite(calculated);
|
|
90
|
+
const nextTotals = totals === undefined ? undefined : rewrite(totals);
|
|
91
|
+
if (nextCalculated === calculated && nextTotals === totals)
|
|
92
|
+
return column;
|
|
93
|
+
return {
|
|
94
|
+
...column,
|
|
95
|
+
...(nextCalculated === undefined ? {} : { calculatedColumnFormula: nextCalculated }),
|
|
96
|
+
...(nextTotals === undefined ? {} : { totalsRowFormula: nextTotals }),
|
|
97
|
+
};
|
|
98
|
+
});
|
|
99
|
+
},
|
|
100
|
+
};
|
|
74
101
|
constructor(options, grid) {
|
|
75
102
|
validateTableName(options.name);
|
|
76
103
|
if (options.columns.length === 0) {
|
|
@@ -84,14 +111,15 @@ export class Table {
|
|
|
84
111
|
anchor = decodeCellRef(options.ref);
|
|
85
112
|
}
|
|
86
113
|
catch (cause) {
|
|
114
|
+
if (cause instanceof RangeError)
|
|
115
|
+
throw cause;
|
|
87
116
|
throw new SyntaxError(`table ref ${quoted(options.ref)} must anchor at a single cell (e.g. "A1")`, {
|
|
88
117
|
cause,
|
|
89
118
|
});
|
|
90
119
|
}
|
|
91
120
|
const { col, row } = anchor;
|
|
92
121
|
this.name = options.name;
|
|
93
|
-
this
|
|
94
|
-
this.columns = disambiguateColumnNames(options.columns);
|
|
122
|
+
this.#columns = disambiguateColumnNames(options.columns);
|
|
95
123
|
this.headerRow = options.headerRow ?? true;
|
|
96
124
|
this.totalsRow = options.totalsRow ?? false;
|
|
97
125
|
this.totalsRowShown = options.totalsRowShown;
|
|
@@ -115,6 +143,9 @@ export class Table {
|
|
|
115
143
|
if (grid !== undefined)
|
|
116
144
|
this.#materializeFrame(grid);
|
|
117
145
|
}
|
|
146
|
+
get columns() {
|
|
147
|
+
return this.#columns;
|
|
148
|
+
}
|
|
118
149
|
get columnCount() {
|
|
119
150
|
return this.columns.length;
|
|
120
151
|
}
|
|
@@ -173,7 +204,7 @@ export class Table {
|
|
|
173
204
|
const code = TOTALS_ROW_SUBTOTAL_CODE[column.totalsRowFunction];
|
|
174
205
|
if (code !== undefined) {
|
|
175
206
|
grid.writeCell(bottom, col, {
|
|
176
|
-
formula: `SUBTOTAL(${code},${this.name
|
|
207
|
+
formula: `SUBTOTAL(${code},${structuredColumnReference(this.name, column.name)})`,
|
|
177
208
|
});
|
|
178
209
|
}
|
|
179
210
|
else if (column.totalsRowFunction === 'custom' && column.totalsRowFormula !== undefined) {
|
|
@@ -208,7 +239,6 @@ export class Table {
|
|
|
208
239
|
get options() {
|
|
209
240
|
const options = {
|
|
210
241
|
name: this.name,
|
|
211
|
-
displayName: this.displayName,
|
|
212
242
|
ref: encodeAddress(this.#anchorCol, this.#anchorRow),
|
|
213
243
|
columns: this.columns.map((column) => ({ ...column })),
|
|
214
244
|
rowCount: this.#dataRowCount,
|
package/dist/core/theme.d.ts
CHANGED
|
@@ -48,6 +48,8 @@ export interface ThemeOverrides {
|
|
|
48
48
|
readonly colors?: Readonly<Partial<Record<ThemeColorSlot, string>>> | undefined;
|
|
49
49
|
readonly fonts?: ThemeFontScheme | undefined;
|
|
50
50
|
}
|
|
51
|
+
/** Whether a value is the bare 6-hex RGB a theme colour slot holds, in either casing. */
|
|
52
|
+
export declare function isThemeRgb(value: string): boolean;
|
|
51
53
|
/** Reduce an authored theme colour to the bare 6-hex RGB DrawingML wants.
|
|
52
54
|
*
|
|
53
55
|
* A theme colour is a bare 6-hex RGB: DrawingML has no alpha channel on `<a:srgbClr val>`. The two
|
package/dist/core/theme.js
CHANGED
|
@@ -37,10 +37,13 @@ export const DEFAULT_THEME_FONTS = {
|
|
|
37
37
|
major: 'Calibri Light',
|
|
38
38
|
minor: OFFICE_BODY_FACE,
|
|
39
39
|
};
|
|
40
|
+
export function isThemeRgb(value) {
|
|
41
|
+
return /^[0-9A-Fa-f]{6}$/.test(value);
|
|
42
|
+
}
|
|
40
43
|
export function normalizeThemeColor(value) {
|
|
41
44
|
const argb = parseArgb(value);
|
|
42
45
|
if (argb === undefined) {
|
|
43
|
-
throw new SyntaxError(`invalid theme colour ${quoted(value)}: expected
|
|
46
|
+
throw new SyntaxError(`invalid theme colour ${quoted(value)}: expected RRGGBB or AARRGGBB hexadecimal digits, optionally after '#'`);
|
|
44
47
|
}
|
|
45
48
|
return argb.slice(2).toUpperCase();
|
|
46
49
|
}
|
package/dist/core/value.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Font } from './style.ts';
|
|
2
|
-
/** The observable kind of a cell's value.
|
|
2
|
+
/** The observable kind of a cell's value. Every formula kind reports as `Formula`. */
|
|
3
3
|
export declare const ValueType: {
|
|
4
4
|
readonly Null: 'null';
|
|
5
5
|
readonly Number: 'number';
|
|
@@ -9,11 +9,19 @@ export declare const ValueType: {
|
|
|
9
9
|
readonly Error: 'error';
|
|
10
10
|
readonly Formula: 'formula';
|
|
11
11
|
readonly RichText: 'richText';
|
|
12
|
-
readonly Hyperlink: 'hyperlink';
|
|
13
12
|
};
|
|
14
13
|
export type ValueType = (typeof ValueType)[keyof typeof ValueType];
|
|
15
|
-
/**
|
|
16
|
-
|
|
14
|
+
/**
|
|
15
|
+
* The errors a cell (or formula result) can hold.
|
|
16
|
+
*
|
|
17
|
+
* They are stored two ways. The classic seven, `#GETTING_DATA` and `#BUSY!` are literals: a typed cell
|
|
18
|
+
* holds the spelling and Excel reads it back as that error. Excel has no literal for `#SPILL!`,
|
|
19
|
+
* `#CONNECT!`, `#BLOCKED!`, `#UNKNOWN!`, `#FIELD!` and `#CALC!`, and stores each as `#VALUE!` beside a
|
|
20
|
+
* rich value naming the real one, which is how they are read and written here. `#PYTHON!`, `#EXTERNAL!`
|
|
21
|
+
* and `#TIMEOUT!` are not here: Excel reads no literal spelling of them, and no rich value was seen to
|
|
22
|
+
* read back as one of them unambiguously (Excel 16.0 build 20326).
|
|
23
|
+
*/
|
|
24
|
+
export declare const ERROR_CODES: readonly ['#N/A', '#REF!', '#NAME?', '#DIV/0!', '#NULL!', '#VALUE!', '#NUM!', '#GETTING_DATA', '#BUSY!', '#SPILL!', '#CONNECT!', '#BLOCKED!', '#UNKNOWN!', '#FIELD!', '#CALC!'];
|
|
17
25
|
export type ErrorCode = (typeof ERROR_CODES)[number];
|
|
18
26
|
/**
|
|
19
27
|
* The error a spreadsheet puts in place of a reference that has nowhere left to point.
|
|
@@ -37,16 +45,6 @@ export interface RichTextRun {
|
|
|
37
45
|
export interface RichTextValue {
|
|
38
46
|
readonly richText: readonly RichTextRun[];
|
|
39
47
|
}
|
|
40
|
-
/** A hyperlink cell: a URL plus the text (plain or rich) shown in the cell. */
|
|
41
|
-
export interface HyperlinkValue {
|
|
42
|
-
readonly hyperlink: string;
|
|
43
|
-
readonly text: string | RichTextValue;
|
|
44
|
-
readonly tooltip?: string;
|
|
45
|
-
/** The clickable extent (`'D1:H1'`) when the link spans a range whose top-left corner is this
|
|
46
|
-
* cell. Absent for an ordinary single-cell link. The destination and label live on the top-left
|
|
47
|
-
* cell; `range` records how far Excel highlights the clickable area so it survives a round-trip. */
|
|
48
|
-
readonly range?: string;
|
|
49
|
-
}
|
|
50
48
|
/** The cached result a formula carries: any scalar, a date, or an error. */
|
|
51
49
|
export type FormulaResult = number | string | boolean | Date | ErrorValue;
|
|
52
50
|
/** A cell whose value is computed by its own formula. */
|
|
@@ -68,6 +66,26 @@ export interface SharedFormulaValue {
|
|
|
68
66
|
readonly formula?: string;
|
|
69
67
|
readonly result?: FormulaResult;
|
|
70
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* A cell holding an array formula (`<f t="array">`): one formula whose result fills {@link ref}, a
|
|
71
|
+
* range starting at this cell. The other cells of the range hold only the values the formula
|
|
72
|
+
* produced, which is how Excel stores them, so they are plain values here too.
|
|
73
|
+
*
|
|
74
|
+
* Excel stores two kinds this way. A legacy array formula, entered with Ctrl+Shift+Enter, shows in
|
|
75
|
+
* braces and fills the range it was entered over. A dynamic-array formula is {@link dynamic}: it
|
|
76
|
+
* spills, `ref` is the range its last calculation filled, and no braces are shown. Excel keeps that
|
|
77
|
+
* mark in the workbook's cell metadata rather than on the formula, and a formula that loses it opens
|
|
78
|
+
* as a legacy array formula that no longer spills.
|
|
79
|
+
*/
|
|
80
|
+
export interface ArrayFormulaValue {
|
|
81
|
+
readonly shareType: 'array';
|
|
82
|
+
readonly formula: string;
|
|
83
|
+
/** The range the result fills, starting at this cell: `'B1:B3'`, or `'B1'` for one cell. */
|
|
84
|
+
readonly ref: string;
|
|
85
|
+
/** Whether Excel evaluates the formula as a dynamic array rather than a Ctrl+Shift+Enter one. */
|
|
86
|
+
readonly dynamic?: boolean;
|
|
87
|
+
readonly result?: FormulaResult;
|
|
88
|
+
}
|
|
71
89
|
/**
|
|
72
90
|
* A cell computed by a What-If-Analysis data table (`<f t="dataTable">`), the OOXML formula kind that
|
|
73
91
|
* fills a range by re-evaluating a model against a grid of substituted input cells. The library does
|
|
@@ -86,25 +104,36 @@ export interface DataTableFormulaValue {
|
|
|
86
104
|
readonly r1?: string;
|
|
87
105
|
/** The second (column) input-cell reference, present for a 2-D table. */
|
|
88
106
|
readonly r2?: string;
|
|
107
|
+
/**
|
|
108
|
+
* Whether the cell {@link r1} named has been deleted. Excel keeps the reference as it was written and
|
|
109
|
+
* sets this flag, and the table then shows `#REF!`; a row or column delete that takes the input cell
|
|
110
|
+
* does the same here.
|
|
111
|
+
*/
|
|
112
|
+
readonly r1Deleted?: boolean;
|
|
113
|
+
/** Whether the cell {@link r2} named has been deleted, as {@link r1Deleted} is for {@link r1}. */
|
|
114
|
+
readonly r2Deleted?: boolean;
|
|
89
115
|
readonly result?: FormulaResult;
|
|
90
116
|
}
|
|
91
117
|
/** Everything a cell's value can be. `null` is the empty cell. */
|
|
92
|
-
export type CellValue = null | number | string | boolean | Date | ErrorValue | FormulaValue | SharedFormulaValue |
|
|
118
|
+
export type CellValue = null | number | string | boolean | Date | ErrorValue | FormulaValue | SharedFormulaValue | ArrayFormulaValue | DataTableFormulaValue | RichTextValue;
|
|
93
119
|
/**
|
|
94
120
|
* Whether a value is an in-cell error ({@link ErrorValue}). The narrowing counterpart of
|
|
95
121
|
* `detectValueType(value) === ValueType.Error`: use this one when the branch goes on to read
|
|
96
|
-
* `.error`, and {@link detectValueType} when it dispatches over all
|
|
122
|
+
* `.error`, and {@link detectValueType} when it dispatches over all eight kinds at once.
|
|
97
123
|
*/
|
|
98
124
|
export declare function isErrorValue(value: CellValue): value is ErrorValue;
|
|
99
125
|
/**
|
|
100
|
-
* Whether a value is a cell's own formula ({@link FormulaValue}): a master, or a
|
|
101
|
-
* belonging to no
|
|
102
|
-
* {@link isSharedFormulaValue}
|
|
103
|
-
* formula-shaped cell" wants
|
|
126
|
+
* Whether a value is a cell's own plain formula ({@link FormulaValue}): a shared-formula master, or a
|
|
127
|
+
* formula belonging to no group. A shared-formula clone is **not** one of these, and nor is an array
|
|
128
|
+
* formula; see {@link isSharedFormulaValue} and {@link isArrayFormulaValue}. Every formula kind reports
|
|
129
|
+
* as `ValueType.Formula`, so a caller that means "any formula-shaped cell" wants
|
|
130
|
+
* {@link detectValueType}, not this.
|
|
104
131
|
*/
|
|
105
132
|
export declare function isFormulaValue(value: CellValue): value is FormulaValue;
|
|
106
133
|
/** Whether a value is a clone participating in a shared formula ({@link SharedFormulaValue}). */
|
|
107
134
|
export declare function isSharedFormulaValue(value: CellValue): value is SharedFormulaValue;
|
|
135
|
+
/** Whether a value is an array formula, legacy or dynamic ({@link ArrayFormulaValue}). */
|
|
136
|
+
export declare function isArrayFormulaValue(value: CellValue): value is ArrayFormulaValue;
|
|
108
137
|
/** Whether a value is a What-If-Analysis data-table formula ({@link DataTableFormulaValue}). */
|
|
109
138
|
export declare function isDataTableFormulaValue(value: CellValue): value is DataTableFormulaValue;
|
|
110
139
|
/**
|
|
@@ -112,11 +141,6 @@ export declare function isDataTableFormulaValue(value: CellValue): value is Data
|
|
|
112
141
|
* make before {@link richTextToPlain}, which accepts nothing else.
|
|
113
142
|
*/
|
|
114
143
|
export declare function isRichTextValue(value: CellValue): value is RichTextValue;
|
|
115
|
-
/**
|
|
116
|
-
* Whether a value is a hyperlink ({@link HyperlinkValue}). Note that its `text` is itself either
|
|
117
|
-
* a string or a {@link RichTextValue}, so reading the label out means one more narrowing.
|
|
118
|
-
*/
|
|
119
|
-
export declare function isHyperlinkValue(value: CellValue): value is HyperlinkValue;
|
|
120
144
|
/**
|
|
121
145
|
* Flatten a rich-text value to its plain text by concatenating every run's text in order. This is the
|
|
122
146
|
* text a consumer that cannot render per-run formatting (a CSV field, a pivot cache entry) sees, and
|
|
@@ -137,9 +161,8 @@ export declare function richTextToPlain(value: RichTextValue): string;
|
|
|
137
161
|
* - a `Date` → a full ISO-8601 timestamp
|
|
138
162
|
* - an error → its literal, e.g. `"#REF!"`, the same string the grid shows
|
|
139
163
|
* - rich text → every run concatenated ({@link richTextToPlain})
|
|
140
|
-
* -
|
|
141
|
-
*
|
|
142
|
-
* carries no cached result: the formula source is not text the sheet ever displayed
|
|
164
|
+
* - any formula kind → the text of the *cached result*, and `""` when the cell carries no cached
|
|
165
|
+
* result: the formula source is not text the sheet ever displayed
|
|
143
166
|
*/
|
|
144
167
|
export declare function cellValueToText(value: CellValue): string;
|
|
145
168
|
/**
|
package/dist/core/value.js
CHANGED
|
@@ -7,7 +7,6 @@ export const ValueType = {
|
|
|
7
7
|
Error: 'error',
|
|
8
8
|
Formula: 'formula',
|
|
9
9
|
RichText: 'richText',
|
|
10
|
-
Hyperlink: 'hyperlink',
|
|
11
10
|
};
|
|
12
11
|
export const ERROR_CODES = [
|
|
13
12
|
'#N/A',
|
|
@@ -17,9 +16,14 @@ export const ERROR_CODES = [
|
|
|
17
16
|
'#NULL!',
|
|
18
17
|
'#VALUE!',
|
|
19
18
|
'#NUM!',
|
|
19
|
+
'#GETTING_DATA',
|
|
20
|
+
'#BUSY!',
|
|
20
21
|
'#SPILL!',
|
|
22
|
+
'#CONNECT!',
|
|
23
|
+
'#BLOCKED!',
|
|
24
|
+
'#UNKNOWN!',
|
|
25
|
+
'#FIELD!',
|
|
21
26
|
'#CALC!',
|
|
22
|
-
'#GETTING_DATA',
|
|
23
27
|
];
|
|
24
28
|
export const REF_ERROR = '#REF!';
|
|
25
29
|
const ERROR_SET = new Set(ERROR_CODES);
|
|
@@ -30,20 +34,20 @@ export function isErrorValue(value) {
|
|
|
30
34
|
return hasKey(value, 'error');
|
|
31
35
|
}
|
|
32
36
|
export function isFormulaValue(value) {
|
|
33
|
-
return hasKey(value, 'formula') && !('sharedFormula' in value);
|
|
37
|
+
return hasKey(value, 'formula') && !('sharedFormula' in value) && !('shareType' in value);
|
|
34
38
|
}
|
|
35
39
|
export function isSharedFormulaValue(value) {
|
|
36
40
|
return hasKey(value, 'sharedFormula');
|
|
37
41
|
}
|
|
42
|
+
export function isArrayFormulaValue(value) {
|
|
43
|
+
return hasKey(value, 'shareType') && value.shareType === 'array';
|
|
44
|
+
}
|
|
38
45
|
export function isDataTableFormulaValue(value) {
|
|
39
46
|
return hasKey(value, 'shareType') && value.shareType === 'dataTable';
|
|
40
47
|
}
|
|
41
48
|
export function isRichTextValue(value) {
|
|
42
49
|
return hasKey(value, 'richText');
|
|
43
50
|
}
|
|
44
|
-
export function isHyperlinkValue(value) {
|
|
45
|
-
return hasKey(value, 'hyperlink');
|
|
46
|
-
}
|
|
47
51
|
export function richTextToPlain(value) {
|
|
48
52
|
return value.richText.map((run) => run.text).join('');
|
|
49
53
|
}
|
|
@@ -68,9 +72,10 @@ function classify(value, visit) {
|
|
|
68
72
|
}
|
|
69
73
|
if (value instanceof Date)
|
|
70
74
|
return visit.date(value);
|
|
71
|
-
if (
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
if (isFormulaValue(value) ||
|
|
76
|
+
isSharedFormulaValue(value) ||
|
|
77
|
+
isArrayFormulaValue(value) ||
|
|
78
|
+
isDataTableFormulaValue(value)) {
|
|
74
79
|
return visit.formula(value);
|
|
75
80
|
}
|
|
76
81
|
if (isRichTextValue(value))
|
|
@@ -88,7 +93,6 @@ const TO_TYPE = {
|
|
|
88
93
|
error: () => ValueType.Error,
|
|
89
94
|
formula: () => ValueType.Formula,
|
|
90
95
|
richText: () => ValueType.RichText,
|
|
91
|
-
hyperlink: () => ValueType.Hyperlink,
|
|
92
96
|
};
|
|
93
97
|
const TO_TEXT = {
|
|
94
98
|
null: () => '',
|
|
@@ -99,7 +103,6 @@ const TO_TEXT = {
|
|
|
99
103
|
error: (value) => value.error,
|
|
100
104
|
formula: (value) => (value.result === undefined ? '' : cellValueToText(value.result)),
|
|
101
105
|
richText: richTextToPlain,
|
|
102
|
-
hyperlink: (value) => (typeof value.text === 'string' ? value.text : richTextToPlain(value.text)),
|
|
103
106
|
};
|
|
104
107
|
function unsupportedValue(value) {
|
|
105
108
|
throw new TypeError(`unsupported cell value: ${describe(value)}`);
|
|
@@ -117,7 +120,7 @@ export function coerceCellValue(value) {
|
|
|
117
120
|
if (value === undefined)
|
|
118
121
|
return null;
|
|
119
122
|
detectValueType(value);
|
|
120
|
-
if (isFormulaValue(value)) {
|
|
123
|
+
if (isFormulaValue(value) || isArrayFormulaValue(value)) {
|
|
121
124
|
const formula = stripLeadingEquals(value.formula);
|
|
122
125
|
return formula === value.formula ? value : { ...value, formula };
|
|
123
126
|
}
|
|
@@ -43,7 +43,7 @@ export type DifferentialStyle = Pick<CellStyle, 'font' | 'numFmt' | 'fill' | 'bo
|
|
|
43
43
|
* are held decoded.
|
|
44
44
|
*/
|
|
45
45
|
export interface TableStyleTable {
|
|
46
|
-
readonly styles: readonly
|
|
46
|
+
readonly styles: readonly TableStyleDefinition[];
|
|
47
47
|
readonly defaultTableStyle?: string | undefined;
|
|
48
48
|
readonly defaultPivotStyle?: string | undefined;
|
|
49
49
|
/**
|
|
@@ -59,6 +59,21 @@ export interface TableStyleTable {
|
|
|
59
59
|
*/
|
|
60
60
|
readonly namespaces?: readonly TableStyleNamespace[];
|
|
61
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* One preserved `<tableStyle>` definition: its bytes, and the `name` a table's style info matches it by.
|
|
64
|
+
*
|
|
65
|
+
* The name travels beside the fragment rather than being read back out of it. An authored style
|
|
66
|
+
* replaces the preserved definition it shares a name with, and a pattern pulling `name="…"` out of
|
|
67
|
+
* the bytes did not see `name='…'`, which is the same attribute in single quotes: the writer emitted
|
|
68
|
+
* both definitions under one name, the duplicate {@link Workbook.addTableStyle} promises cannot happen.
|
|
69
|
+
* The reader takes the name from the scanner that read the element, decoded, whatever its quoting.
|
|
70
|
+
*/
|
|
71
|
+
export interface TableStyleDefinition {
|
|
72
|
+
/** The style's `name`, decoded; empty for a fragment that declared none. */
|
|
73
|
+
readonly name: string;
|
|
74
|
+
/** The `<tableStyle>…</tableStyle>` element exactly as the file spelled it. */
|
|
75
|
+
readonly xml: string;
|
|
76
|
+
}
|
|
62
77
|
/** One namespace declaration a preserved `<tableStyle>` fragment depends on. */
|
|
63
78
|
export interface TableStyleNamespace {
|
|
64
79
|
readonly prefix: string;
|
|
@@ -85,6 +100,7 @@ export declare class WorkbookStyleTables {
|
|
|
85
100
|
addCustomTableStyle(style: TableStyle): void;
|
|
86
101
|
indexedPalette(): readonly string[];
|
|
87
102
|
restoreDifferentialStyles(fragments: readonly string[]): void;
|
|
103
|
+
adoptDifferentialStyle(fragment: string): number;
|
|
88
104
|
restoreNamedStyles(styles: readonly NamedCellStyle[]): void;
|
|
89
105
|
restoreIndexedColors(fragments: readonly string[]): void;
|
|
90
106
|
restoreMruColors(fragments: readonly string[]): void;
|
|
@@ -33,6 +33,10 @@ export class WorkbookStyleTables {
|
|
|
33
33
|
restoreDifferentialStyles(fragments) {
|
|
34
34
|
replaceContents(this.#differentialStyles, fragments);
|
|
35
35
|
}
|
|
36
|
+
adoptDifferentialStyle(fragment) {
|
|
37
|
+
const existing = this.#differentialStyles.indexOf(fragment);
|
|
38
|
+
return existing === -1 ? this.#differentialStyles.push(fragment) - 1 : existing;
|
|
39
|
+
}
|
|
36
40
|
restoreNamedStyles(styles) {
|
|
37
41
|
replaceContents(this.#namedStyles, styles);
|
|
38
42
|
}
|
|
@@ -19,9 +19,11 @@ export class WorkbookTheme {
|
|
|
19
19
|
this.#declared = declared;
|
|
20
20
|
}
|
|
21
21
|
author(overrides) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
const colors = Object.fromEntries(Object.entries(overrides.colors ?? {}).map(([slot, value]) => [
|
|
23
|
+
slot,
|
|
24
|
+
normalizeThemeColor(value),
|
|
25
|
+
]));
|
|
26
|
+
Object.assign(this.#authored.colors, colors);
|
|
25
27
|
this.#authored.fonts = { ...this.#authored.fonts, ...overrides.fonts };
|
|
26
28
|
}
|
|
27
29
|
get colors() {
|
package/dist/core/workbook.d.ts
CHANGED
|
@@ -2,7 +2,8 @@ import { type CustomUiDocument } from '../customui/index.ts';
|
|
|
2
2
|
import { type VbaLibraryReference, type VbaProject, type VbaProjectSignature } from '../vba/index.ts';
|
|
3
3
|
import { type Person } from './comment-thread.ts';
|
|
4
4
|
import type { DateEpoch } from './date.ts';
|
|
5
|
-
import
|
|
5
|
+
import { type SheetSplice } from './formula-references.ts';
|
|
6
|
+
import { type WorkbookImage, type WorksheetImages } from './image.ts';
|
|
6
7
|
import { INTERNAL } from './internal.ts';
|
|
7
8
|
import type { PreservedPart, PreservedRootReference } from './preserved.ts';
|
|
8
9
|
import type { Color, Font } from './style.ts';
|
|
@@ -345,7 +346,8 @@ export declare class Workbook {
|
|
|
345
346
|
* slot left unauthored keeps the source's own encoding, including the `<a:sysClr>` form Excel uses
|
|
346
347
|
* for `dk1`/`lt1` so they follow the viewer's window colours.
|
|
347
348
|
*
|
|
348
|
-
* @throws {
|
|
349
|
+
* @throws {SyntaxError} if a colour is not 6 or 8 hexadecimal digits, with or without a leading `#`.
|
|
350
|
+
* Every colour is read before any is stored, so a refused call changes nothing.
|
|
349
351
|
*/
|
|
350
352
|
setTheme(overrides: ThemeOverrides): void;
|
|
351
353
|
/**
|
|
@@ -354,6 +356,9 @@ export declare class Workbook {
|
|
|
354
356
|
*
|
|
355
357
|
* Note the slot *order*: `theme="0"` is `lt1` and `theme="1"` is `dk1`, which is not the order the
|
|
356
358
|
* slots appear in the theme part. See {@link THEME_COLOR_SLOTS}.
|
|
359
|
+
*
|
|
360
|
+
* Every slot reads back as six uppercase hexadecimal digits, whichever spelling {@link setTheme} was
|
|
361
|
+
* given or the theme part used.
|
|
357
362
|
*/
|
|
358
363
|
get themeColors(): ThemeColorScheme;
|
|
359
364
|
/** The theme's major (heading) and minor (body) typefaces, authored values over the source's. */
|
|
@@ -413,7 +418,8 @@ export declare class Workbook {
|
|
|
413
418
|
*
|
|
414
419
|
* A serializer composes these *over* the existing part rather than generating one from scratch, so
|
|
415
420
|
* a preserved theme keeps its format scheme, its unauthored slots' exact encoding, and the
|
|
416
|
-
* relationships it carries.
|
|
421
|
+
* relationships it carries. Its colours are already reduced to the six uppercase hexadecimal digits
|
|
422
|
+
* a slot holds.
|
|
417
423
|
*/
|
|
418
424
|
get themeOverrides(): ThemeOverrides | undefined;
|
|
419
425
|
/**
|
|
@@ -561,6 +567,12 @@ export interface WorkbookInternals {
|
|
|
561
567
|
* re-write.
|
|
562
568
|
*/
|
|
563
569
|
restoreDifferentialStyles(fragments: readonly string[]): void;
|
|
570
|
+
/**
|
|
571
|
+
* The index of a `<dxf>` fragment a sheet carried inline, found among the differential styles or
|
|
572
|
+
* appended after them, so a conditional format read from the extension form holds a `dxfId` like any
|
|
573
|
+
* other rule.
|
|
574
|
+
*/
|
|
575
|
+
adoptDifferentialStyle(fragment: string): number;
|
|
564
576
|
/**
|
|
565
577
|
* Reinstate the custom indexed-color palette (`<colors><indexedColors>`) read from a file, each
|
|
566
578
|
* entry a verbatim `<rgbColor rgb="…"/>` fragment, so a colour referenced by `indexed="…"` keeps
|
|
@@ -617,4 +629,9 @@ export interface WorkbookInternals {
|
|
|
617
629
|
* {@link Workbook.addPerson} is the authoring verb.
|
|
618
630
|
*/
|
|
619
631
|
restorePersons(persons: readonly Person[]): void;
|
|
632
|
+
/**
|
|
633
|
+
* Every row and column splice made to the workbook's sheets, in the order they were made, for the
|
|
634
|
+
* writer to replay over the references a preserved part spells.
|
|
635
|
+
*/
|
|
636
|
+
splices(): readonly SheetSplice[];
|
|
620
637
|
}
|
package/dist/core/workbook.js
CHANGED
|
@@ -2,6 +2,8 @@ import { isCustomUiRelType, parseCustomUi } from '../customui/index.js';
|
|
|
2
2
|
import { AuthoringError, quoted } from '../errors.js';
|
|
3
3
|
import { addVbaReference, removeVbaModule, } from '../vba/index.js';
|
|
4
4
|
import { commentThreadGuid } from './comment-thread.js';
|
|
5
|
+
import { spliceFormula } from './formula-references.js';
|
|
6
|
+
import { pictureProperties } from './image.js';
|
|
5
7
|
import { INTERNAL } from './internal.js';
|
|
6
8
|
import { INVALID_SHEET_NAME_CHARS, MAX_SHEET_NAME_LENGTH } from './limits.js';
|
|
7
9
|
import { checkTableStyle } from './table-style.js';
|
|
@@ -32,6 +34,7 @@ export class Workbook {
|
|
|
32
34
|
#styles = new WorkbookStyleTables();
|
|
33
35
|
#theme = new WorkbookTheme(() => this.#styles.indexedPalette());
|
|
34
36
|
#preservedReferences = [];
|
|
37
|
+
#splices = [];
|
|
35
38
|
#persons = new Map();
|
|
36
39
|
get worksheets() {
|
|
37
40
|
return this.#worksheets;
|
|
@@ -192,9 +195,10 @@ export class Workbook {
|
|
|
192
195
|
exportImages(sheet) {
|
|
193
196
|
const background = sheet.backgroundImageId;
|
|
194
197
|
return {
|
|
195
|
-
anchored: sheet.images.map((
|
|
196
|
-
image: this.#media.require(imageId, sheet.name),
|
|
197
|
-
anchor,
|
|
198
|
+
anchored: sheet.images.map((picture) => ({
|
|
199
|
+
image: this.#media.require(picture.imageId, sheet.name),
|
|
200
|
+
anchor: picture.anchor,
|
|
201
|
+
...pictureProperties(picture),
|
|
198
202
|
})),
|
|
199
203
|
background: background === undefined ? undefined : this.#media.require(background, sheet.name),
|
|
200
204
|
};
|
|
@@ -203,8 +207,8 @@ export class Workbook {
|
|
|
203
207
|
for (const id of new Set(sheet.images.map((image) => image.imageId)))
|
|
204
208
|
sheet.removeImage(id);
|
|
205
209
|
sheet.removeBackgroundImage();
|
|
206
|
-
for (const
|
|
207
|
-
sheet.addImageAnchor(this.#media.registerExisting(image), anchor);
|
|
210
|
+
for (const picture of images.anchored) {
|
|
211
|
+
sheet.addImageAnchor(this.#media.registerExisting(picture.image), picture.anchor, pictureProperties(picture));
|
|
208
212
|
}
|
|
209
213
|
if (images.background !== undefined) {
|
|
210
214
|
sheet.addBackgroundImage(this.#media.registerExisting(images.background));
|
|
@@ -225,9 +229,24 @@ export class Workbook {
|
|
|
225
229
|
addWorksheet(name, options = {}) {
|
|
226
230
|
this.#assertValidSheetName(name);
|
|
227
231
|
const sheet = new Worksheet(name, this.#nextSheetId++, options.state ?? 'visible');
|
|
232
|
+
sheet[INTERNAL].setFormulaHost((edit) => {
|
|
233
|
+
this.#spliceFormulasBeyond(sheet, edit);
|
|
234
|
+
});
|
|
228
235
|
this.#worksheets.push(sheet);
|
|
229
236
|
return sheet;
|
|
230
237
|
}
|
|
238
|
+
#spliceFormulasBeyond(spliced, edit) {
|
|
239
|
+
this.#splices.push(edit);
|
|
240
|
+
for (const sheet of this.#worksheets) {
|
|
241
|
+
if (sheet !== spliced)
|
|
242
|
+
sheet[INTERNAL].spliceFormulas(edit);
|
|
243
|
+
}
|
|
244
|
+
for (const [index, definedName] of this.#definedNames.entries()) {
|
|
245
|
+
const refersTo = spliceFormula(definedName.refersTo, definedName.scope, edit);
|
|
246
|
+
if (refersTo !== definedName.refersTo)
|
|
247
|
+
this.#definedNames[index] = { ...definedName, refersTo };
|
|
248
|
+
}
|
|
249
|
+
}
|
|
231
250
|
getWorksheet(nameOrId) {
|
|
232
251
|
if (typeof nameOrId === 'number') {
|
|
233
252
|
return this.#worksheets.find((sheet) => sheet.id === nameOrId);
|
|
@@ -273,6 +292,7 @@ export class Workbook {
|
|
|
273
292
|
restoreDifferentialStyles: (fragments) => {
|
|
274
293
|
this.#styles.restoreDifferentialStyles(fragments);
|
|
275
294
|
},
|
|
295
|
+
adoptDifferentialStyle: (fragment) => this.#styles.adoptDifferentialStyle(fragment),
|
|
276
296
|
restoreIndexedColors: (fragments) => {
|
|
277
297
|
this.#styles.restoreIndexedColors(fragments);
|
|
278
298
|
},
|
|
@@ -296,5 +316,6 @@ export class Workbook {
|
|
|
296
316
|
for (const person of persons)
|
|
297
317
|
this.#persons.set(person.id, person);
|
|
298
318
|
},
|
|
319
|
+
splices: () => this.#splices,
|
|
299
320
|
};
|
|
300
321
|
}
|
|
@@ -20,13 +20,20 @@ export declare class WorksheetMerges {
|
|
|
20
20
|
get rects(): readonly MergeRect[];
|
|
21
21
|
/**
|
|
22
22
|
* Declare a merged range, returning the rectangle it covers, or `undefined` for an unbounded
|
|
23
|
-
* whole-row/column range, which is declared and overlap-checks against nothing.
|
|
23
|
+
* whole-row/column range, which is declared and overlap-checks against nothing. The range is stored
|
|
24
|
+
* in canonical form (see {@link canonicalMerge}).
|
|
24
25
|
*
|
|
26
|
+
* @throws {SyntaxError} if the range is unparseable or names a worksheet.
|
|
25
27
|
* @throws {AuthoringError} if the range overlaps an already-merged region. Excel forbids
|
|
26
28
|
* overlapping merges and writes such geometry as a file it then offers to repair.
|
|
27
29
|
*/
|
|
28
30
|
add(range: string): MergeRect | undefined;
|
|
29
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Drop a declared range and, with it, the rectangle it covers. The inverse of {@link add}, and it
|
|
33
|
+
* matches however the range is spelled, since both sides are compared in canonical form.
|
|
34
|
+
*
|
|
35
|
+
* @throws {SyntaxError} if the range is unparseable or names a worksheet.
|
|
36
|
+
*/
|
|
30
37
|
remove(range: string): MergeRemoval;
|
|
31
38
|
/**
|
|
32
39
|
* Resolve a position to the top-left of the region covering it, or to itself when none does. This
|
|
@@ -38,7 +45,5 @@ export declare class WorksheetMerges {
|
|
|
38
45
|
};
|
|
39
46
|
/** Replace every declared range and rectangle at once: what a structural splice re-anchors to. */
|
|
40
47
|
replaceAll(ranges: readonly string[], rects: readonly MergeRect[]): void;
|
|
41
|
-
/** Report that something outside has rewritten the grid under these regions. */
|
|
42
|
-
invalidate(): void;
|
|
43
48
|
clear(): void;
|
|
44
49
|
}
|