@shbernal/ts-xlsx 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/bytes.d.ts +7 -0
- package/dist/bytes.js +22 -0
- package/dist/core/address.d.ts +60 -2
- package/dist/core/address.js +40 -24
- package/dist/core/autofilter.d.ts +4 -3
- package/dist/core/autofilter.js +31 -30
- package/dist/core/axis-handle.d.ts +2 -0
- package/dist/core/axis-handle.js +5 -2
- package/dist/core/cell.d.ts +4 -3
- package/dist/core/cell.js +4 -6
- package/dist/core/clone.d.ts +29 -0
- package/dist/core/clone.js +24 -0
- package/dist/core/color-resolution.js +2 -4
- package/dist/core/column.d.ts +1 -0
- package/dist/core/column.js +3 -0
- package/dist/core/comment-thread.js +2 -1
- package/dist/core/conditional-formatting-overlay.d.ts +2 -1
- package/dist/core/conditional-formatting-overlay.js +2 -2
- package/dist/core/conditional-formatting.d.ts +9 -1
- package/dist/core/conditional-formatting.js +34 -18
- package/dist/core/containers.d.ts +12 -0
- package/dist/core/containers.js +5 -0
- package/dist/core/data-validation-overlay.d.ts +2 -1
- package/dist/core/data-validation-overlay.js +4 -4
- package/dist/core/data-validation.d.ts +6 -0
- package/dist/core/data-validation.js +15 -4
- package/dist/core/date-format.d.ts +20 -0
- package/dist/core/date-format.js +160 -0
- package/dist/core/date.d.ts +43 -8
- package/dist/core/date.js +18 -2
- package/dist/core/formula.d.ts +26 -0
- package/dist/core/formula.js +20 -4
- package/dist/core/grid-edits.d.ts +2 -3
- package/dist/core/grid-edits.js +69 -70
- package/dist/core/grid-shift.d.ts +58 -9
- package/dist/core/grid-shift.js +26 -4
- package/dist/core/image.d.ts +13 -9
- package/dist/core/image.js +7 -5
- package/dist/core/internal.d.ts +8 -2
- package/dist/core/limits.d.ts +23 -0
- package/dist/core/limits.js +4 -0
- package/dist/core/merge.d.ts +5 -4
- package/dist/core/merge.js +18 -19
- package/dist/core/pivot-table.js +63 -45
- package/dist/core/protection.js +2 -11
- package/dist/core/range.js +34 -30
- package/dist/core/row-input.js +2 -2
- package/dist/core/row.d.ts +1 -0
- package/dist/core/row.js +3 -0
- package/dist/core/style.d.ts +85 -70
- package/dist/core/style.js +92 -28
- package/dist/core/table-style.d.ts +1 -1
- package/dist/core/table-style.js +4 -4
- package/dist/core/table.d.ts +27 -9
- package/dist/core/table.js +51 -34
- package/dist/core/theme.js +6 -5
- package/dist/core/value.d.ts +9 -0
- package/dist/core/value.js +36 -34
- package/dist/core/workbook-media.d.ts +34 -0
- package/dist/core/workbook-media.js +44 -0
- package/dist/core/workbook-styles.d.ts +67 -1
- package/dist/core/workbook-vba.js +3 -2
- package/dist/core/workbook.d.ts +23 -2
- package/dist/core/workbook.js +24 -40
- package/dist/core/worksheet-comments.d.ts +2 -1
- package/dist/core/worksheet-comments.js +20 -13
- package/dist/core/worksheet-merges.d.ts +44 -0
- package/dist/core/worksheet-merges.js +59 -0
- package/dist/core/worksheet-model.d.ts +9 -1
- package/dist/core/worksheet-model.js +24 -9
- package/dist/core/worksheet.d.ts +55 -6
- package/dist/core/worksheet.js +36 -44
- package/dist/customui/ribbon.js +2 -1
- package/dist/entries/core.d.ts +18 -13
- package/dist/entries/core.js +12 -6
- package/dist/entries/xlsx.d.ts +1 -1
- package/dist/errors.d.ts +64 -0
- package/dist/errors.js +22 -0
- package/dist/hex.d.ts +8 -0
- package/dist/hex.js +3 -0
- package/dist/io/csv/delimiter.d.ts +9 -0
- package/dist/io/csv/delimiter.js +6 -0
- package/dist/io/csv/read.js +11 -4
- package/dist/io/csv/write.d.ts +9 -2
- package/dist/io/csv/write.js +9 -38
- package/dist/io/opc/inflate.js +14 -0
- package/dist/io/opc/namespaces.d.ts +16 -0
- package/dist/io/opc/namespaces.js +4 -0
- package/dist/io/opc/part-paths.d.ts +9 -0
- package/dist/io/opc/part-paths.js +1 -1
- package/dist/io/opc/read-opc.d.ts +54 -14
- package/dist/io/opc/read-opc.js +42 -20
- package/dist/io/opc/read-options.d.ts +5 -1
- package/dist/io/opc/sniff-format.d.ts +3 -3
- package/dist/io/opc/sniff-format.js +2 -2
- package/dist/io/style/xf-style.d.ts +23 -1
- package/dist/io/style/xf-style.js +8 -0
- package/dist/io/xlsb/formula.d.ts +2 -2
- package/dist/io/xlsb/formula.js +49 -34
- package/dist/io/xlsb/primitives.js +8 -14
- package/dist/io/xlsb/ptg-functions.d.ts +19 -10
- package/dist/io/xlsb/ptg-functions.js +385 -596
- package/dist/io/xlsb/read-styles.js +45 -81
- package/dist/io/xlsb/read-worksheet.d.ts +20 -1
- package/dist/io/xlsb/read-worksheet.js +73 -89
- package/dist/io/xlsb/read.d.ts +6 -3
- package/dist/io/xlsb/read.js +44 -23
- package/dist/io/xlsb/record-stream.d.ts +30 -0
- package/dist/io/xlsb/record-stream.js +20 -0
- package/dist/io/xlsb/record-types.d.ts +1 -5
- package/dist/io/xlsb/record-types.js +1 -5
- package/dist/io/xlsx/cell-accumulator.d.ts +8 -1
- package/dist/io/xlsx/cell-accumulator.js +32 -9
- package/dist/io/xlsx/cell-style-resolution.d.ts +25 -0
- package/dist/io/xlsx/cell-style-resolution.js +29 -0
- package/dist/io/xlsx/cell-value.d.ts +5 -3
- package/dist/io/xlsx/cell-value.js +13 -15
- package/dist/io/xlsx/color-xml.js +3 -2
- package/dist/io/xlsx/column-budget.d.ts +26 -0
- package/dist/io/xlsx/column-budget.js +22 -0
- package/dist/io/xlsx/comments.d.ts +6 -2
- package/dist/io/xlsx/comments.js +36 -32
- package/dist/io/xlsx/conditional-formatting.d.ts +6 -3
- package/dist/io/xlsx/conditional-formatting.js +30 -26
- package/dist/io/xlsx/data-validation.js +29 -27
- package/dist/io/xlsx/edit-vba.d.ts +7 -2
- package/dist/io/xlsx/edit-vba.js +14 -21
- package/dist/io/xlsx/font-xml.d.ts +7 -0
- package/dist/io/xlsx/font-xml.js +104 -0
- package/dist/io/xlsx/hyperlinks.d.ts +37 -5
- package/dist/io/xlsx/hyperlinks.js +22 -13
- package/dist/io/xlsx/images.js +11 -13
- package/dist/io/xlsx/namespaces.d.ts +16 -0
- package/dist/io/xlsx/namespaces.js +7 -0
- package/dist/io/xlsx/package-plan.d.ts +14 -2
- package/dist/io/xlsx/package-plan.js +39 -11
- package/dist/io/xlsx/pivot.js +8 -7
- package/dist/io/xlsx/read-parts.d.ts +59 -0
- package/dist/io/xlsx/read-parts.js +252 -0
- package/dist/io/xlsx/read-pivot.js +2 -1
- package/dist/io/xlsx/read-repair.d.ts +26 -0
- package/dist/io/xlsx/read-repair.js +39 -0
- package/dist/io/xlsx/{rich-runs.js → read-rich-runs.js} +6 -3
- package/dist/io/xlsx/read-rows.d.ts +18 -5
- package/dist/io/xlsx/read-rows.js +45 -31
- package/dist/io/xlsx/read-shared-strings.js +3 -2
- package/dist/io/xlsx/read-styles.d.ts +1 -6
- package/dist/io/xlsx/read-styles.js +6 -71
- package/dist/io/xlsx/read-workbook-xml.d.ts +36 -0
- package/dist/io/xlsx/read-workbook-xml.js +170 -0
- package/dist/io/xlsx/read-worksheet.d.ts +2 -1
- package/dist/io/xlsx/read-worksheet.js +35 -164
- package/dist/io/xlsx/read.d.ts +5 -12
- package/dist/io/xlsx/read.js +73 -406
- package/dist/io/xlsx/rich-text.js +1 -1
- package/dist/io/xlsx/row-position.d.ts +18 -0
- package/dist/io/xlsx/row-position.js +11 -0
- package/dist/io/xlsx/row-xml.d.ts +128 -0
- package/dist/io/xlsx/row-xml.js +203 -0
- package/dist/io/xlsx/shared-formulas.js +2 -2
- package/dist/io/xlsx/sheet-properties.d.ts +10 -1
- package/dist/io/xlsx/sheet-properties.js +145 -9
- package/dist/io/xlsx/style-elements.d.ts +43 -0
- package/dist/io/xlsx/style-elements.js +156 -0
- package/dist/io/xlsx/styles.d.ts +12 -3
- package/dist/io/xlsx/styles.js +5 -207
- package/dist/io/xlsx/tables.js +10 -14
- package/dist/io/xlsx/theme-xml.d.ts +26 -4
- package/dist/io/xlsx/theme-xml.js +107 -69
- package/dist/io/xlsx/threaded-comments.d.ts +8 -10
- package/dist/io/xlsx/threaded-comments.js +2 -1
- package/dist/io/xlsx/workbook-xml.d.ts +54 -4
- package/dist/io/xlsx/workbook-xml.js +60 -34
- package/dist/io/xlsx/worksheet-xml.d.ts +23 -70
- package/dist/io/xlsx/worksheet-xml.js +48 -229
- package/dist/io/xlsx/write-stream.d.ts +65 -16
- package/dist/io/xlsx/write-stream.js +50 -20
- package/dist/io/xlsx/write.d.ts +1 -2
- package/dist/io/xlsx/write.js +114 -74
- package/dist/rel-type.d.ts +16 -0
- package/dist/rel-type.js +6 -0
- package/dist/token-set.d.ts +13 -0
- package/dist/token-set.js +4 -1
- package/dist/vba/bytes.d.ts +14 -5
- package/dist/vba/bytes.js +16 -6
- package/dist/vba/cfb-format.d.ts +8 -0
- package/dist/vba/cfb-format.js +1 -0
- package/dist/vba/cfb-writer.d.ts +9 -0
- package/dist/vba/cfb-writer.js +12 -9
- package/dist/vba/cfb.d.ts +13 -1
- package/dist/vba/cfb.js +73 -51
- package/dist/vba/codepage.js +2 -1
- package/dist/vba/errors.d.ts +7 -0
- package/dist/vba/ms-ovba.js +51 -16
- package/dist/vba/project-editor.js +35 -40
- package/dist/vba/project.d.ts +11 -1
- package/dist/vba/project.js +27 -8
- package/dist/vba/vba-encoding.js +4 -5
- package/dist/xml/xml-attrs.d.ts +37 -0
- package/dist/xml/xml-attrs.js +30 -0
- package/dist/xml/xml-chars.d.ts +40 -0
- package/dist/xml/xml-chars.js +12 -0
- package/dist/xml/xml-namespaces.d.ts +31 -0
- package/dist/xml/xml-namespaces.js +50 -0
- package/dist/xml/xml-read.d.ts +72 -10
- package/dist/xml/xml-read.js +94 -18
- package/dist/xml/xml-scan.d.ts +15 -37
- package/dist/xml/xml-scan.js +12 -40
- package/dist/xml/xml.d.ts +28 -27
- package/dist/xml/xml.js +24 -24
- package/package.json +12 -7
- /package/dist/io/xlsx/{rich-runs.d.ts → read-rich-runs.d.ts} +0 -0
package/dist/core/pivot-table.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { AuthoringError, InternalError } from '../errors.js';
|
|
1
|
+
import { AuthoringError, InternalError, quoted } from '../errors.js';
|
|
2
2
|
import { tokenSet } from '../token-set.js';
|
|
3
|
-
import {
|
|
3
|
+
import { encodeRect } from './address.js';
|
|
4
|
+
import { INTERNAL } from './internal.js';
|
|
4
5
|
import { isErrorValue, isFormulaValue, isHyperlinkValue, isRichTextValue, isSharedFormulaValue, richTextToPlain, } from './value.js';
|
|
5
6
|
const PIVOT_METRICS = {
|
|
6
7
|
sum: true,
|
|
@@ -40,7 +41,7 @@ export class PivotTable {
|
|
|
40
41
|
constructor(options) {
|
|
41
42
|
const metric = options.metric ?? 'sum';
|
|
42
43
|
if (!Object.hasOwn(PIVOT_METRICS, metric)) {
|
|
43
|
-
throw new AuthoringError(`unsupported pivot metric
|
|
44
|
+
throw new AuthoringError(`unsupported pivot metric ${quoted(metric)}: expected one of ${Object.keys(PIVOT_METRICS).join(', ')}`);
|
|
44
45
|
}
|
|
45
46
|
this.metric = metric;
|
|
46
47
|
const source = options.source;
|
|
@@ -49,51 +50,36 @@ export class PivotTable {
|
|
|
49
50
|
if (columnCount < 1 || lastRow < 2) {
|
|
50
51
|
throw new AuthoringError('a pivot source needs a header row and at least one data row');
|
|
51
52
|
}
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const resolve = (role, name) => {
|
|
61
|
-
const index = fields.findIndex((field) => field.name === name);
|
|
62
|
-
if (index < 0) {
|
|
63
|
-
throw new AuthoringError(`pivot ${role} field "${name}" is not a column header in the source sheet`);
|
|
64
|
-
}
|
|
65
|
-
return index;
|
|
66
|
-
};
|
|
67
|
-
if (options.rows.length === 0)
|
|
68
|
-
throw new AuthoringError('a pivot table needs at least one row field');
|
|
69
|
-
if (options.columns.length === 0)
|
|
70
|
-
throw new AuthoringError('a pivot table needs at least one column field');
|
|
71
|
-
const [valueName, ...extraValues] = options.values;
|
|
72
|
-
if (valueName === undefined || extraValues.length > 0) {
|
|
73
|
-
throw new AuthoringError('a pivot table needs exactly one value field');
|
|
74
|
-
}
|
|
75
|
-
this.rowFields = options.rows.map((name) => resolve('row', name));
|
|
76
|
-
this.columnFields = options.columns.map((name) => resolve('column', name));
|
|
77
|
-
this.valueField = resolve('value', valueName);
|
|
78
|
-
const axisFields = new Set([...this.rowFields, ...this.columnFields]);
|
|
53
|
+
const internals = source[INTERNAL];
|
|
54
|
+
const valueAt = (row, col) => internals.peekCell(row, col)?.value ?? null;
|
|
55
|
+
const fields = discoverFields(valueAt, columnCount);
|
|
56
|
+
const roles = resolveRoles(options, fields);
|
|
57
|
+
this.rowFields = roles.rowFields;
|
|
58
|
+
this.columnFields = roles.columnFields;
|
|
59
|
+
this.valueField = roles.valueField;
|
|
60
|
+
const axisFields = new Set([...roles.rowFields, ...roles.columnFields]);
|
|
79
61
|
const firstField = fields[0];
|
|
80
|
-
const lastField = fields
|
|
62
|
+
const lastField = fields.at(-1);
|
|
81
63
|
if (firstField === undefined || lastField === undefined) {
|
|
82
|
-
throw new
|
|
64
|
+
throw new InternalError('pivot field list is empty after discoverFields guaranteed it is not');
|
|
83
65
|
}
|
|
84
66
|
this.sourceSheetName = source.name;
|
|
85
|
-
this.sourceRef =
|
|
67
|
+
this.sourceRef = encodeRect({
|
|
68
|
+
top: 1,
|
|
69
|
+
left: firstField.col,
|
|
70
|
+
bottom: lastRow,
|
|
71
|
+
right: lastField.col,
|
|
72
|
+
});
|
|
86
73
|
const dataRowCount = lastRow - 1;
|
|
87
74
|
const columnScalars = fields.map((field) => {
|
|
88
75
|
const scalars = [];
|
|
89
|
-
for (let row = 2; row <= lastRow; row++)
|
|
90
|
-
scalars.push(scalarOf(
|
|
91
|
-
}
|
|
76
|
+
for (let row = 2; row <= lastRow; row++)
|
|
77
|
+
scalars.push(scalarOf(valueAt(row, field.col)));
|
|
92
78
|
return scalars;
|
|
93
79
|
});
|
|
94
80
|
const catalogues = fields.map(() => null);
|
|
95
81
|
this.cacheFields = fields.map((field, fieldIndex) => {
|
|
96
|
-
const scalars =
|
|
82
|
+
const scalars = columnScalars[fieldIndex] ?? missingColumn(fieldIndex);
|
|
97
83
|
const containsBlank = scalars.some((scalar) => scalar.kind === 'blank');
|
|
98
84
|
if (axisFields.has(fieldIndex)) {
|
|
99
85
|
const items = [];
|
|
@@ -110,15 +96,18 @@ export class PivotTable {
|
|
|
110
96
|
}
|
|
111
97
|
return { name: field.name, sharedItems: null, numeric: numericSummary(scalars), containsBlank };
|
|
112
98
|
});
|
|
99
|
+
const byField = fields.map((_field, fieldIndex) => ({
|
|
100
|
+
scalars: columnScalars[fieldIndex] ?? missingColumn(fieldIndex),
|
|
101
|
+
catalogue: catalogues[fieldIndex],
|
|
102
|
+
}));
|
|
113
103
|
const records = [];
|
|
114
104
|
for (let row = 0; row < dataRowCount; row++) {
|
|
115
|
-
records.push(
|
|
116
|
-
const scalar =
|
|
105
|
+
records.push(byField.map(({ scalars, catalogue }, fieldIndex) => {
|
|
106
|
+
const scalar = scalars[row];
|
|
117
107
|
if (scalar === undefined) {
|
|
118
108
|
throw new InternalError(`pivot record row ${row} is out of range for field ${fieldIndex}: every column was ` +
|
|
119
109
|
'scanned for the same dataRowCount above, so this index is always in range');
|
|
120
110
|
}
|
|
121
|
-
const catalogue = catalogues[fieldIndex];
|
|
122
111
|
if (!catalogue)
|
|
123
112
|
return scalar;
|
|
124
113
|
const index = catalogue.get(itemKey(scalar));
|
|
@@ -138,12 +127,41 @@ export class PivotTable {
|
|
|
138
127
|
return field.name;
|
|
139
128
|
}
|
|
140
129
|
}
|
|
141
|
-
function
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
130
|
+
function discoverFields(valueAt, columnCount) {
|
|
131
|
+
const fields = [];
|
|
132
|
+
for (let col = 1; col <= columnCount; col++) {
|
|
133
|
+
const name = textOf(scalarOf(valueAt(1, col)));
|
|
134
|
+
if (name !== '')
|
|
135
|
+
fields.push({ name, col });
|
|
145
136
|
}
|
|
146
|
-
|
|
137
|
+
if (fields.length === 0)
|
|
138
|
+
throw new AuthoringError('the pivot source header row is empty');
|
|
139
|
+
return fields;
|
|
140
|
+
}
|
|
141
|
+
function resolveRoles(options, fields) {
|
|
142
|
+
const resolve = (role, name) => {
|
|
143
|
+
const index = fields.findIndex((field) => field.name === name);
|
|
144
|
+
if (index < 0) {
|
|
145
|
+
throw new AuthoringError(`pivot ${role} field ${quoted(name)} is not a column header in the source sheet`);
|
|
146
|
+
}
|
|
147
|
+
return index;
|
|
148
|
+
};
|
|
149
|
+
if (options.rows.length === 0)
|
|
150
|
+
throw new AuthoringError('a pivot table needs at least one row field');
|
|
151
|
+
if (options.columns.length === 0)
|
|
152
|
+
throw new AuthoringError('a pivot table needs at least one column field');
|
|
153
|
+
const [valueName, ...extraValues] = options.values;
|
|
154
|
+
if (valueName === undefined || extraValues.length > 0) {
|
|
155
|
+
throw new AuthoringError('a pivot table needs exactly one value field');
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
rowFields: options.rows.map((name) => resolve('row', name)),
|
|
159
|
+
columnFields: options.columns.map((name) => resolve('column', name)),
|
|
160
|
+
valueField: resolve('value', valueName),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function missingColumn(fieldIndex) {
|
|
164
|
+
throw new InternalError(`pivot field index ${fieldIndex} is out of range for columnScalars: it was built from the same fields array`);
|
|
147
165
|
}
|
|
148
166
|
function itemKey(item) {
|
|
149
167
|
switch (item.kind) {
|
package/dist/core/protection.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { concat, toBase64 } from '../bytes.js';
|
|
1
|
+
import { concat, toBase64, utf16leBytes } from '../bytes.js';
|
|
2
2
|
import { sha512 } from '../sha512.js';
|
|
3
3
|
export const SHEET_PROTECTION_FLAGS = [
|
|
4
4
|
{ key: 'formatCells', defaultForbidden: true },
|
|
@@ -22,7 +22,7 @@ const DEFAULT_SPIN_COUNT = 100000;
|
|
|
22
22
|
const SALT_BYTES = 16;
|
|
23
23
|
export function deriveCredential(password, spinCount = DEFAULT_SPIN_COUNT) {
|
|
24
24
|
const salt = crypto.getRandomValues(new Uint8Array(SALT_BYTES));
|
|
25
|
-
let hash = sha512(concat([salt,
|
|
25
|
+
let hash = sha512(concat([salt, utf16leBytes(password)]));
|
|
26
26
|
const spun = new Uint8Array(hash.length + 4);
|
|
27
27
|
const counter = new DataView(spun.buffer, hash.length, 4);
|
|
28
28
|
for (let i = 0; i < spinCount; i++) {
|
|
@@ -37,12 +37,3 @@ export function deriveCredential(password, spinCount = DEFAULT_SPIN_COUNT) {
|
|
|
37
37
|
spinCount,
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
|
-
function utf16le(text) {
|
|
41
|
-
const bytes = new Uint8Array(text.length * 2);
|
|
42
|
-
for (let i = 0; i < text.length; i++) {
|
|
43
|
-
const unit = text.charCodeAt(i);
|
|
44
|
-
bytes[i * 2] = unit & 0xff;
|
|
45
|
-
bytes[i * 2 + 1] = unit >>> 8;
|
|
46
|
-
}
|
|
47
|
-
return bytes;
|
|
48
|
-
}
|
package/dist/core/range.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { quoted } from '../errors.js';
|
|
2
|
+
import { assertAxisInBounds, decodeRange, encodeAddress, encodeRect, MAX_COLUMN, MAX_ROW, } from './address.js';
|
|
2
3
|
import { applyCellStyle } from './cell.js';
|
|
4
|
+
import { INTERNAL } from './internal.js';
|
|
3
5
|
import { CELL_STYLE_FACETS, } from './style.js';
|
|
4
6
|
export class Range {
|
|
5
7
|
#sheet;
|
|
@@ -8,10 +10,10 @@ export class Range {
|
|
|
8
10
|
bottom;
|
|
9
11
|
right;
|
|
10
12
|
constructor(sheet, top, left, bottom, right) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
assertAxisInBounds('row', top);
|
|
14
|
+
assertAxisInBounds('row', bottom);
|
|
15
|
+
assertAxisInBounds('column', left);
|
|
16
|
+
assertAxisInBounds('column', right);
|
|
15
17
|
this.#sheet = sheet;
|
|
16
18
|
this.top = Math.min(top, bottom);
|
|
17
19
|
this.bottom = Math.max(top, bottom);
|
|
@@ -22,7 +24,7 @@ export class Range {
|
|
|
22
24
|
return this.#sheet;
|
|
23
25
|
}
|
|
24
26
|
get address() {
|
|
25
|
-
return
|
|
27
|
+
return encodeRect(this);
|
|
26
28
|
}
|
|
27
29
|
get rowCount() {
|
|
28
30
|
return this.bottom - this.top + 1;
|
|
@@ -45,12 +47,8 @@ export class Range {
|
|
|
45
47
|
}
|
|
46
48
|
get cells() {
|
|
47
49
|
const cells = [];
|
|
48
|
-
for (
|
|
49
|
-
|
|
50
|
-
if (this.#sheet.hasCell(row, col))
|
|
51
|
-
cells.push(this.#sheet.getCell(encodeAddress(col, row)));
|
|
52
|
-
}
|
|
53
|
-
}
|
|
50
|
+
for (const cell of this.#storedCells())
|
|
51
|
+
cells.push(cell);
|
|
54
52
|
return cells;
|
|
55
53
|
}
|
|
56
54
|
get style() {
|
|
@@ -64,7 +62,7 @@ export class Range {
|
|
|
64
62
|
applyCellStyle(cell, style);
|
|
65
63
|
}
|
|
66
64
|
clearStyle() {
|
|
67
|
-
for (const cell of this
|
|
65
|
+
for (const cell of this.#storedCells()) {
|
|
68
66
|
for (const facet of CELL_STYLE_FACETS)
|
|
69
67
|
setFacet(cell, facet, undefined);
|
|
70
68
|
}
|
|
@@ -105,28 +103,42 @@ export class Range {
|
|
|
105
103
|
set protection(protection) {
|
|
106
104
|
this.#writeFacet('protection', protection);
|
|
107
105
|
}
|
|
108
|
-
|
|
109
|
-
|
|
106
|
+
*#materialise() {
|
|
107
|
+
const internals = this.#sheet[INTERNAL];
|
|
108
|
+
for (let row = this.top; row <= this.bottom; row++) {
|
|
109
|
+
for (let col = this.left; col <= this.right; col++) {
|
|
110
|
+
yield internals.masterAt(row, col);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
110
113
|
}
|
|
111
114
|
#writeFacet(facet, value) {
|
|
112
|
-
const cells = value === undefined ? this
|
|
115
|
+
const cells = value === undefined ? this.#storedCells() : this.#materialise();
|
|
113
116
|
for (const cell of cells)
|
|
114
117
|
setFacet(cell, facet, value);
|
|
115
118
|
}
|
|
119
|
+
*#storedCells() {
|
|
120
|
+
const internals = this.#sheet[INTERNAL];
|
|
121
|
+
for (let row = this.top; row <= this.bottom; row++) {
|
|
122
|
+
for (let col = this.left; col <= this.right; col++) {
|
|
123
|
+
const cell = internals.peekCell(row, col);
|
|
124
|
+
if (cell !== undefined)
|
|
125
|
+
yield cell;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
116
129
|
#collectShared(target, facet) {
|
|
117
130
|
const shared = this.#sharedFacet(facet);
|
|
118
131
|
if (shared !== undefined)
|
|
119
132
|
target[facet] = shared;
|
|
120
133
|
}
|
|
121
134
|
#sharedFacet(facet) {
|
|
135
|
+
const internals = this.#sheet[INTERNAL];
|
|
122
136
|
let first;
|
|
123
137
|
let firstKey;
|
|
124
138
|
let seen = 0;
|
|
125
139
|
for (let row = this.top; row <= this.bottom; row++) {
|
|
126
140
|
for (let col = this.left; col <= this.right; col++) {
|
|
127
|
-
const value =
|
|
128
|
-
? this.#sheet.getCell(encodeAddress(col, row))[facet]
|
|
129
|
-
: undefined;
|
|
141
|
+
const value = internals.peekCell(row, col)?.[facet];
|
|
130
142
|
const key = facetKey(value);
|
|
131
143
|
if (seen === 0) {
|
|
132
144
|
first = value;
|
|
@@ -152,24 +164,16 @@ function facetKey(value) {
|
|
|
152
164
|
? Object.fromEntries(Object.entries(inner).sort(([a], [b]) => (a < b ? -1 : 1)))
|
|
153
165
|
: inner);
|
|
154
166
|
}
|
|
155
|
-
function checkBound(axis, value, max) {
|
|
156
|
-
if (!Number.isInteger(value) || value < 1) {
|
|
157
|
-
throw new RangeError(`${axis} ${value} is out of bounds: ${axis}s start at 1`);
|
|
158
|
-
}
|
|
159
|
-
if (value > max) {
|
|
160
|
-
throw new RangeError(`${axis} ${value} is out of bounds: the sheet ends at ${max}`);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
167
|
export function rangeFrom(sheet, reference) {
|
|
164
168
|
const { top, left, bottom, right, sheetName, dimensions } = decodeRange(reference);
|
|
165
169
|
if (sheetName !== undefined && sheetName.toLowerCase() !== sheet.name.toLowerCase()) {
|
|
166
|
-
throw new SyntaxError(
|
|
170
|
+
throw new SyntaxError(`${quoted(reference)} names worksheet ${quoted(sheetName)}, not ${quoted(sheet.name)}: a range belongs to the sheet it came from`);
|
|
167
171
|
}
|
|
168
172
|
if (top === undefined || bottom === undefined) {
|
|
169
|
-
throw new SyntaxError(
|
|
173
|
+
throw new SyntaxError(`${quoted(reference)} spans whole columns (${dimensions}): style them through getColumn(n), which says the same thing in one attribute instead of ${MAX_ROW} cells`);
|
|
170
174
|
}
|
|
171
175
|
if (left === undefined || right === undefined) {
|
|
172
|
-
throw new SyntaxError(
|
|
176
|
+
throw new SyntaxError(`${quoted(reference)} spans whole rows (${dimensions}): style them through getRow(n), which says the same thing in one attribute instead of ${MAX_COLUMN} cells`);
|
|
173
177
|
}
|
|
174
178
|
return new Range(sheet, top, left, bottom, right);
|
|
175
179
|
}
|
package/dist/core/row-input.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AuthoringError } from '../errors.js';
|
|
1
|
+
import { AuthoringError, quoted } from '../errors.js';
|
|
2
2
|
import { Cell } from './cell.js';
|
|
3
3
|
export function positionalPlacements(values) {
|
|
4
4
|
const placements = [];
|
|
@@ -27,5 +27,5 @@ function columnIndexByKey(columns, key) {
|
|
|
27
27
|
if (properties.key === key)
|
|
28
28
|
return index;
|
|
29
29
|
}
|
|
30
|
-
throw new AuthoringError(`no column is keyed ${
|
|
30
|
+
throw new AuthoringError(`no column is keyed ${quoted(key)}: set getColumn(n).key first`);
|
|
31
31
|
}
|
package/dist/core/row.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export declare class Row extends AxisHandle<RowProperties> {
|
|
|
19
19
|
get properties(): Readonly<RowProperties> | undefined;
|
|
20
20
|
protected propertiesOf(): RowProperties | undefined;
|
|
21
21
|
protected ensureProperties(): RowProperties;
|
|
22
|
+
protected dropProperties(): void;
|
|
22
23
|
/**
|
|
23
24
|
* Row height in points; `undefined` leaves the sheet default in force.
|
|
24
25
|
*
|
package/dist/core/row.js
CHANGED
|
@@ -19,6 +19,9 @@ export class Row extends AxisHandle {
|
|
|
19
19
|
ensureProperties() {
|
|
20
20
|
return this.#sheet[INTERNAL].ensureRowProperties(this.number);
|
|
21
21
|
}
|
|
22
|
+
dropProperties() {
|
|
23
|
+
this.#sheet[INTERNAL].dropRowProperties(this.number);
|
|
24
|
+
}
|
|
22
25
|
get height() {
|
|
23
26
|
return this.read('height');
|
|
24
27
|
}
|
package/dist/core/style.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ClonePlan } from './clone.ts';
|
|
2
|
+
import { type AssertNever, NAMED_STYLE_ID } from './internal.ts';
|
|
2
3
|
/** Underline can be a plain flag or one of Excel's named underline styles. */
|
|
3
4
|
export type UnderlineStyle = boolean | 'none' | 'single' | 'double' | 'singleAccounting' | 'doubleAccounting';
|
|
4
5
|
/** Narrow a raw `<u val>` token to a named {@link UnderlineStyle} (the non-boolean members). */
|
|
@@ -36,11 +37,35 @@ export interface Color {
|
|
|
36
37
|
*/
|
|
37
38
|
export declare function parseArgb(value: string): string | undefined;
|
|
38
39
|
/**
|
|
39
|
-
* Fill pattern kinds,
|
|
40
|
+
* Fill pattern kinds, in the order OOXML's `ST_PatternType` enumerates them. `none` is the
|
|
40
41
|
* absence of a fill; `solid` paints the whole cell with the foreground colour (the
|
|
41
42
|
* common case). The remaining hatch patterns are carried for fidelity on read.
|
|
43
|
+
*
|
|
44
|
+
* The order is load-bearing rather than cosmetic, which is why it is stated twice over -- here, and
|
|
45
|
+
* in {@link FILL_PATTERNS_IN_SCHEMA_ORDER}, tied together by a proof. BIFF12 stores a pattern as its
|
|
46
|
+
* *index* into this enumeration, so the binary codec needs the sequence as a value; the doc above
|
|
47
|
+
* this type used to claim schema order while the union put `gray125` and `gray0625` at positions 2
|
|
48
|
+
* and 6, where the schema puts them last, and the binary codec carried a third copy that was right.
|
|
49
|
+
*/
|
|
50
|
+
export type FillPatternType = 'none' | 'solid' | 'mediumGray' | 'darkGray' | 'lightGray' | 'darkHorizontal' | 'darkVertical' | 'darkDown' | 'darkUp' | 'darkGrid' | 'darkTrellis' | 'lightHorizontal' | 'lightVertical' | 'lightDown' | 'lightUp' | 'lightGrid' | 'lightTrellis' | 'gray125' | 'gray0625';
|
|
51
|
+
/**
|
|
52
|
+
* Every {@link FillPatternType}, in `ST_PatternType` order, which is also the order BIFF12's `fls`
|
|
53
|
+
* field indexes: `fls` 1 is `solid`, 2 is `mediumGray`, and so on. Index 0 is `none`, which the
|
|
54
|
+
* model spells as no fill at all rather than as a pattern.
|
|
55
|
+
*
|
|
56
|
+
* One list, consulted by the guard below and by `io/xlsb/read-styles.ts`. It replaced three
|
|
57
|
+
* hand-maintained copies of one enumeration -- the union, the guard's own table, and the binary
|
|
58
|
+
* codec's index array -- of which only the first two were checked against each other, so adding a
|
|
59
|
+
* pattern forced the guard to be updated and let the binary codec silently drop it.
|
|
42
60
|
*/
|
|
43
|
-
export
|
|
61
|
+
export declare const FILL_PATTERNS_IN_SCHEMA_ORDER: readonly ["none", "solid", "mediumGray", "darkGray", "lightGray", "darkHorizontal", "darkVertical", "darkDown", "darkUp", "darkGrid", "darkTrellis", "lightHorizontal", "lightVertical", "lightDown", "lightUp", "lightGrid", "lightTrellis", "gray125", "gray0625"];
|
|
62
|
+
/**
|
|
63
|
+
* The two halves of the proof {@link FILL_PATTERNS_IN_SCHEMA_ORDER} owes, since a list -- unlike the
|
|
64
|
+
* `Record` shape every other token guard here is built from -- can name fewer members than its union
|
|
65
|
+
* without the compiler minding. `satisfies` above covers "no invented name"; this covers "no
|
|
66
|
+
* omission".
|
|
67
|
+
*/
|
|
68
|
+
export type EveryFillPatternIsOrdered = AssertNever<Exclude<FillPatternType, (typeof FILL_PATTERNS_IN_SCHEMA_ORDER)[number]>>;
|
|
44
69
|
/** Narrow a raw `<patternFill patternType>` token to a known {@link FillPatternType}. */
|
|
45
70
|
export declare const isFillPatternType: (value: string) => value is FillPatternType;
|
|
46
71
|
/**
|
|
@@ -79,6 +104,18 @@ export interface GradientFill {
|
|
|
79
104
|
}
|
|
80
105
|
/** A cell/row background fill: a flat pattern or a colour gradient. */
|
|
81
106
|
export type Fill = PatternFill | GradientFill;
|
|
107
|
+
declare const GRADIENT_STOP_CLONE: ClonePlan<GradientStop>;
|
|
108
|
+
/** The proof that {@link GRADIENT_STOP_CLONE} names every field of a gradient stop. */
|
|
109
|
+
export type EveryGradientStopFieldIsCloned = AssertNever<Exclude<keyof Required<GradientStop>, keyof typeof GRADIENT_STOP_CLONE>>;
|
|
110
|
+
declare const PATTERN_FILL_CLONE: ClonePlan<PatternFill>;
|
|
111
|
+
/** The proof that {@link PATTERN_FILL_CLONE} names every field of a pattern fill. */
|
|
112
|
+
export type EveryPatternFillFieldIsCloned = AssertNever<Exclude<keyof Required<PatternFill>, keyof typeof PATTERN_FILL_CLONE>>;
|
|
113
|
+
declare const GRADIENT_FILL_CLONE: ClonePlan<GradientFill>;
|
|
114
|
+
/** The proof that {@link GRADIENT_FILL_CLONE} names every field of a gradient fill. */
|
|
115
|
+
export type EveryGradientFillFieldIsCloned = AssertNever<Exclude<keyof Required<GradientFill>, keyof typeof GRADIENT_FILL_CLONE>>;
|
|
116
|
+
/** A defensive deep copy of a fill, whichever of the two shapes it is. The union is dispatched on
|
|
117
|
+
* `type` because the two halves share no field beyond it, so one plan could not describe both. */
|
|
118
|
+
export declare function cloneFill(fill: Fill): Fill;
|
|
82
119
|
/**
|
|
83
120
|
* Line styles a cell border edge can take, as OOXML's `ST_BorderStyle` enumerates them.
|
|
84
121
|
* `none` is the absence of an edge and is expressed by omitting the edge, not by this value.
|
|
@@ -106,6 +143,14 @@ export interface Border {
|
|
|
106
143
|
readonly diagonalUp?: boolean;
|
|
107
144
|
readonly diagonalDown?: boolean;
|
|
108
145
|
}
|
|
146
|
+
declare const BORDER_EDGE_CLONE: ClonePlan<BorderEdge>;
|
|
147
|
+
/** The proof that {@link BORDER_EDGE_CLONE} names every field of a border edge. */
|
|
148
|
+
export type EveryBorderEdgeFieldIsCloned = AssertNever<Exclude<keyof Required<BorderEdge>, keyof typeof BORDER_EDGE_CLONE>>;
|
|
149
|
+
declare const BORDER_CLONE: ClonePlan<Border>;
|
|
150
|
+
/** The proof that {@link BORDER_CLONE} names every side of a border. */
|
|
151
|
+
export type EveryBorderFieldIsCloned = AssertNever<Exclude<keyof Required<Border>, keyof typeof BORDER_CLONE>>;
|
|
152
|
+
/** A defensive deep copy of a border, each present edge and its colour included. */
|
|
153
|
+
export declare function cloneBorder(border: Border): Border;
|
|
109
154
|
/** Vertical alignment of a font relative to the baseline (super/subscript). */
|
|
110
155
|
export type FontVerticalAlignment = 'superscript' | 'subscript';
|
|
111
156
|
/** Narrow a raw `<vertAlign val>` token to a known {@link FontVerticalAlignment}. */
|
|
@@ -133,6 +178,11 @@ export interface Font {
|
|
|
133
178
|
readonly outline?: boolean;
|
|
134
179
|
readonly vertAlign?: FontVerticalAlignment;
|
|
135
180
|
}
|
|
181
|
+
declare const FONT_CLONE: ClonePlan<Font>;
|
|
182
|
+
/** The proof that {@link FONT_CLONE} names every facet of a font. */
|
|
183
|
+
export type EveryFontFieldIsCloned = AssertNever<Exclude<keyof Required<Font>, keyof typeof FONT_CLONE>>;
|
|
184
|
+
/** A defensive deep copy of a font, its nested colour included. */
|
|
185
|
+
export declare function cloneFont(font: Font): Font;
|
|
136
186
|
/** How a cell's content sits horizontally within its bounds, as OOXML's `ST_HorizontalAlignment`
|
|
137
187
|
* enumerates it. `general` is the type-dependent default (text left, numbers right) and reads
|
|
138
188
|
* back as no explicit horizontal alignment. */
|
|
@@ -166,7 +216,11 @@ export interface Alignment {
|
|
|
166
216
|
* Format-blind on purpose. `Alignment` is a core type and the layering gate forbids core importing a
|
|
167
217
|
* serialisation, so the table states what a facet *is* and each codec supplies the reading and the
|
|
168
218
|
* writing off the `kind`. That is where {@link SHEET_PROTECTION_FLAGS} sits and how it is consumed,
|
|
169
|
-
* and it is the shape the BIFF12 codec
|
|
219
|
+
* and it is the shape the BIFF12 codec drives off too: `io/xlsb/read-styles.ts` walks this list and
|
|
220
|
+
* looks each facet up in a `Record` keyed by {@link Alignment}, so the bit layout stays a BIFF12 fact
|
|
221
|
+
* in the BIFF12 codec while the *set* of facets is decided here, once, for both. (That sentence used
|
|
222
|
+
* to read "if alignment ever reaches it". Alignment had reached it; the comment had not noticed, and
|
|
223
|
+
* the binary reader was restating all seven facets and their default-omission rules by hand.)
|
|
170
224
|
*
|
|
171
225
|
* The OOXML attribute name is the model key for all seven facets, so it is not restated here: a
|
|
172
226
|
* second list that is always identical is a second list to keep in step. A future facet whose
|
|
@@ -234,6 +288,32 @@ export interface CellStyle {
|
|
|
234
288
|
}
|
|
235
289
|
/** The names of the {@link CellStyle} facets, for helpers that copy the tuple facet-by-facet. */
|
|
236
290
|
export declare const CELL_STYLE_FACETS: (keyof CellStyle)[];
|
|
291
|
+
/**
|
|
292
|
+
* Everything a cell's *formatting* is, which is the six {@link CellStyle} facets plus two that only a
|
|
293
|
+
* cell can carry: the quote-prefix flag and the link to a named cell style.
|
|
294
|
+
*
|
|
295
|
+
* The two extras are on the cell's `xf` record exactly as the six are, and are written and read back
|
|
296
|
+
* exactly as the six are, but they sat outside the tuple, so every copy path driven by the tuple
|
|
297
|
+
* dropped them: a splice, a `duplicateRow`, or a `dst.model = src.model` turned a leading-apostrophe
|
|
298
|
+
* text cell back into an unprefixed one. That is the merge-loss the tuple exists to make impossible,
|
|
299
|
+
* so they join it. Callers that mean "the six shared facets" (a column default, a named style, a
|
|
300
|
+
* `<dxf>`) still say {@link CellStyle}; callers copying a *cell* say this.
|
|
301
|
+
*/
|
|
302
|
+
export type CellContent = CellStyle & {
|
|
303
|
+
quotePrefix?: boolean | undefined;
|
|
304
|
+
[NAMED_STYLE_ID]?: number | undefined;
|
|
305
|
+
};
|
|
306
|
+
/**
|
|
307
|
+
* The names of every {@link CellContent} facet, the six shared ones first. Helpers that copy a cell's
|
|
308
|
+
* whole formatting drive off this, so a facet added to either half reaches all of them at once.
|
|
309
|
+
*/
|
|
310
|
+
export declare const CELL_CONTENT_FACETS: (keyof CellContent)[];
|
|
311
|
+
/**
|
|
312
|
+
* Copy every present facet of a cell's formatting from `source` onto `target`, leaving facets
|
|
313
|
+
* `source` omits untouched: {@link assignStyleFacets} widened to the two cell-only facets. This is
|
|
314
|
+
* what a copy of a *cell* uses, so no structural edit can drop one.
|
|
315
|
+
*/
|
|
316
|
+
export declare function assignContentFacets(target: CellContent, source: Readonly<CellContent>): void;
|
|
237
317
|
/**
|
|
238
318
|
* Copy each present facet of `source` onto `target`, leaving facets `source` omits untouched: the
|
|
239
319
|
* plain-record counterpart to a cell's `applyCellStyle`, for the {@link CellStyle}-shaped targets a
|
|
@@ -249,69 +329,4 @@ export declare function assignStyleFacets(target: CellStyle, source: Readonly<Ce
|
|
|
249
329
|
* the tuple reaches a `<col>` style without anyone remembering to widen a literal.
|
|
250
330
|
*/
|
|
251
331
|
export declare function pickStyleFacets(source: Readonly<CellStyle>): CellStyle;
|
|
252
|
-
|
|
253
|
-
* A named cell style: the OOXML `cellStyleXfs`/`cellStyles` layer. A spreadsheet applies a built-in
|
|
254
|
-
* or custom style (e.g. "Normal", "Accent1") whose visual facets live in this shared, named layer
|
|
255
|
-
* rather than on each cell's direct format; a cell links to it and inherits any facet the direct
|
|
256
|
-
* format leaves unset. The facets are a cell's own (see {@link CellStyle}); `name` is the style's
|
|
257
|
-
* display name and `builtinId` its Excel gallery index when it is a built-in style.
|
|
258
|
-
*/
|
|
259
|
-
export type NamedCellStyle = Readonly<CellStyle> & {
|
|
260
|
-
readonly name?: string;
|
|
261
|
-
readonly builtinId?: number;
|
|
262
|
-
};
|
|
263
|
-
/**
|
|
264
|
-
* A differential style (OOXML CT_Dxf): formatting laid *over* whatever a cell already carries. Only
|
|
265
|
-
* the facets present override; the rest of the cell's own style shows through. It carries the subset
|
|
266
|
-
* of the cell-style facets (see {@link CellStyle}) a `<dxf>` can express: font, number format, fill,
|
|
267
|
-
* and border.
|
|
268
|
-
*
|
|
269
|
-
* Differential styles live in one workbook-level table (`<dxfs>`) that several features index into:
|
|
270
|
-
* a conditional-formatting rule's highlight format, and a table style's per-element formatting
|
|
271
|
-
* (`<tableStyleElement dxfId="…">`). They are interned and shared, so two features asking for the
|
|
272
|
-
* same formatting land on one entry.
|
|
273
|
-
*
|
|
274
|
-
* Not every facet reaches every consumer. As a **table style element**, Excel applies only the font,
|
|
275
|
-
* fill, and border: its own object model exposes `Font`, `Interior`, and `Borders` on a table style
|
|
276
|
-
* element and nothing for a number format, so a `numFmt` set here is carried faithfully through a
|
|
277
|
-
* round-trip but has no visible effect. The type is left whole rather than split, because the same
|
|
278
|
-
* value is legitimately reused across both consumers and narrowing it would only move the surprise.
|
|
279
|
-
*/
|
|
280
|
-
export type DifferentialStyle = Pick<CellStyle, 'font' | 'numFmt' | 'fill' | 'border'>;
|
|
281
|
-
/**
|
|
282
|
-
* The `<tableStyles>` block of a styles part: the custom table/pivot style definitions a file
|
|
283
|
-
* declares, and the two gallery names it nominates as the default for a new table and a new pivot.
|
|
284
|
-
*
|
|
285
|
-
* Each entry of {@link styles} is one `<tableStyle>…</tableStyle>` fragment kept verbatim, for the
|
|
286
|
-
* same reason a `<dxf>` is: a `tableStyleElement`'s `dxfId` indexes the differential-style table,
|
|
287
|
-
* which the writer re-emits **at its original indices**, so the references stay valid without
|
|
288
|
-
* reparsing anything. That index-stability is load-bearing: renumbering the dxf table would
|
|
289
|
-
* silently re-point every preserved table style at a different format.
|
|
290
|
-
*
|
|
291
|
-
* The two default names are ordinary strings, not fragments: they are re-escaped on write, so they
|
|
292
|
-
* are held decoded.
|
|
293
|
-
*/
|
|
294
|
-
export interface TableStyleTable {
|
|
295
|
-
readonly styles: readonly string[];
|
|
296
|
-
readonly defaultTableStyle?: string | undefined;
|
|
297
|
-
readonly defaultPivotStyle?: string | undefined;
|
|
298
|
-
/**
|
|
299
|
-
* The namespace prefixes the verbatim {@link styles} fragments use, mapped to their URI and to
|
|
300
|
-
* whether the source marked the prefix ignorable (`mc:Ignorable`).
|
|
301
|
-
*
|
|
302
|
-
* Carrying a fragment verbatim carries its *prefixes* too. Excel stamps a revision id
|
|
303
|
-
* (`xr9:uid="{…}"`) on every `<tableStyle>` it writes, so a fragment re-emitted under a
|
|
304
|
-
* `<styleSheet>` that declares only the default namespace is not namespace-well-formed, and no
|
|
305
|
-
* consumer can parse the part at all, which is a far louder failure than the dropped table style
|
|
306
|
-
* this preservation exists to prevent. The writer re-declares each prefix on `<styleSheet>` and
|
|
307
|
-
* re-states the ignorable ones, exactly as the source did.
|
|
308
|
-
*/
|
|
309
|
-
readonly namespaces?: readonly TableStyleNamespace[];
|
|
310
|
-
}
|
|
311
|
-
/** One namespace declaration a preserved `<tableStyle>` fragment depends on. */
|
|
312
|
-
export interface TableStyleNamespace {
|
|
313
|
-
readonly prefix: string;
|
|
314
|
-
readonly uri: string;
|
|
315
|
-
/** Whether the source listed this prefix in the stylesheet's `mc:Ignorable`. */
|
|
316
|
-
readonly ignorable: boolean;
|
|
317
|
-
}
|
|
332
|
+
export {};
|