@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
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { AuthoringError } from '../../errors.js';
|
|
1
|
+
import { AuthoringError, InternalError, quoted } from '../../errors.js';
|
|
2
2
|
import { extensionOf, relativePartPath, relsPathFor, THEME_PART_PATH } from '../opc/part-paths.js';
|
|
3
3
|
import { relsPartXml } from '../opc/rels.js';
|
|
4
|
-
import { drawingPart, mediaPart, vmlDrawingPart } from './part-names.js';
|
|
4
|
+
import { drawingPart, mediaPart, pivotCacheDefinitionPart, pivotCacheRecordsPart, pivotTablePart, vmlDrawingPart, } from './part-names.js';
|
|
5
5
|
import { applyThemeOverrides } from './theme-xml.js';
|
|
6
|
-
export class
|
|
6
|
+
export class RelIdAllocator {
|
|
7
7
|
#next = 1;
|
|
8
8
|
next() {
|
|
9
9
|
return `rId${this.#next++}`;
|
|
@@ -32,7 +32,7 @@ export function planMedia(workbook, sheets) {
|
|
|
32
32
|
const image = workbook.getImage(id);
|
|
33
33
|
if (image === undefined) {
|
|
34
34
|
const reference = role === 'anchor' ? `anchors image id ${id}` : `sets background image id ${id}`;
|
|
35
|
-
throw new AuthoringError(`sheet
|
|
35
|
+
throw new AuthoringError(`sheet ${quoted(sheetName)} ${reference}, which is not registered on the workbook`);
|
|
36
36
|
}
|
|
37
37
|
const number = i + 1;
|
|
38
38
|
parts.push({ number, extension: image.extension, data: image.data });
|
|
@@ -51,12 +51,15 @@ export function planMedia(workbook, sheets) {
|
|
|
51
51
|
},
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
|
-
export function planPreservedParts(workbook, generatedDrawingCount, generatedMediaCount) {
|
|
54
|
+
export function planPreservedParts(workbook, generatedDrawingCount, generatedMediaCount, generatedPivotCount) {
|
|
55
55
|
const sheets = workbook.worksheets;
|
|
56
56
|
const numbering = {
|
|
57
57
|
drawing: generatedDrawingCount,
|
|
58
58
|
vml: sheets.length,
|
|
59
59
|
media: generatedMediaCount,
|
|
60
|
+
pivotTable: generatedPivotCount,
|
|
61
|
+
pivotCacheDefinition: generatedPivotCount,
|
|
62
|
+
pivotCacheRecords: generatedPivotCount,
|
|
60
63
|
};
|
|
61
64
|
const remap = new Map();
|
|
62
65
|
const theme = workbook.themePart;
|
|
@@ -77,7 +80,7 @@ export function planPreservedParts(workbook, generatedDrawingCount, generatedMed
|
|
|
77
80
|
const emitted = new Map();
|
|
78
81
|
for (const reference of allReferences) {
|
|
79
82
|
for (const part of reference.parts) {
|
|
80
|
-
const newPath = remap
|
|
83
|
+
const newPath = resolveRemapped(remap, part.path);
|
|
81
84
|
if (emitted.has(newPath))
|
|
82
85
|
continue;
|
|
83
86
|
const rels = part.rels.flatMap((rel) => {
|
|
@@ -104,17 +107,17 @@ export function planPreservedParts(workbook, generatedDrawingCount, generatedMed
|
|
|
104
107
|
const perSheet = sheets.map((sheet) => sheet.preservedReferences.map((reference) => ({
|
|
105
108
|
element: reference.element,
|
|
106
109
|
relType: reference.relType,
|
|
107
|
-
entryPath: remap
|
|
110
|
+
entryPath: resolveRemapped(remap, reference.entryPath),
|
|
108
111
|
})));
|
|
109
112
|
const workbookRefs = workbook.preservedReferences.map((reference) => ({
|
|
110
113
|
relType: reference.relType,
|
|
111
|
-
entryPath: remap
|
|
114
|
+
entryPath: resolveRemapped(remap, reference.entryPath),
|
|
112
115
|
pivotCacheId: reference.pivotCacheId,
|
|
113
116
|
externalReferenceIndex: reference.externalReferenceIndex,
|
|
114
117
|
}));
|
|
115
118
|
const rootRefs = workbook.preservedRootReferences.map((reference) => ({
|
|
116
119
|
relType: reference.relType,
|
|
117
|
-
entryPath: remap
|
|
120
|
+
entryPath: resolveRemapped(remap, reference.entryPath),
|
|
118
121
|
}));
|
|
119
122
|
return {
|
|
120
123
|
perSheet,
|
|
@@ -124,14 +127,39 @@ export function planPreservedParts(workbook, generatedDrawingCount, generatedMed
|
|
|
124
127
|
themeEmitted: theme !== undefined,
|
|
125
128
|
};
|
|
126
129
|
}
|
|
130
|
+
function resolveRemapped(remap, path) {
|
|
131
|
+
const resolved = remap.get(path);
|
|
132
|
+
if (resolved === undefined) {
|
|
133
|
+
throw new InternalError(`preserved part ${quoted(path)} was never assigned a new path`);
|
|
134
|
+
}
|
|
135
|
+
return resolved;
|
|
136
|
+
}
|
|
127
137
|
function preservedPartPath(originalPath, numbering) {
|
|
128
138
|
const ext = extensionOf(originalPath);
|
|
129
|
-
if (ext
|
|
139
|
+
if (ext === 'vml')
|
|
130
140
|
return vmlDrawingPart(++numbering.vml);
|
|
131
141
|
if (originalPath.startsWith('xl/media/'))
|
|
132
142
|
return mediaPart(++numbering.media, ext);
|
|
133
|
-
if (originalPath.startsWith('xl/drawings/') && ext
|
|
143
|
+
if (originalPath.startsWith('xl/drawings/') && ext === 'xml') {
|
|
134
144
|
return drawingPart(++numbering.drawing);
|
|
135
145
|
}
|
|
146
|
+
if (isNumberedPart(originalPath, PIVOT_TABLE_PREFIX)) {
|
|
147
|
+
return pivotTablePart(++numbering.pivotTable);
|
|
148
|
+
}
|
|
149
|
+
if (isNumberedPart(originalPath, PIVOT_CACHE_DEFINITION_PREFIX)) {
|
|
150
|
+
return pivotCacheDefinitionPart(++numbering.pivotCacheDefinition);
|
|
151
|
+
}
|
|
152
|
+
if (isNumberedPart(originalPath, PIVOT_CACHE_RECORDS_PREFIX)) {
|
|
153
|
+
return pivotCacheRecordsPart(++numbering.pivotCacheRecords);
|
|
154
|
+
}
|
|
136
155
|
return originalPath;
|
|
137
156
|
}
|
|
157
|
+
const PIVOT_TABLE_PREFIX = numberedPartPrefix(pivotTablePart);
|
|
158
|
+
const PIVOT_CACHE_DEFINITION_PREFIX = numberedPartPrefix(pivotCacheDefinitionPart);
|
|
159
|
+
const PIVOT_CACHE_RECORDS_PREFIX = numberedPartPrefix(pivotCacheRecordsPart);
|
|
160
|
+
function numberedPartPrefix(part) {
|
|
161
|
+
return part(1).slice(0, -'1.xml'.length);
|
|
162
|
+
}
|
|
163
|
+
function isNumberedPart(path, prefix) {
|
|
164
|
+
return path.startsWith(prefix) && /^\d+\.xml$/.test(path.slice(prefix.length));
|
|
165
|
+
}
|
package/dist/io/xlsx/pivot.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { encodeAddress } from '../../core/address.js';
|
|
2
|
-
import { escapeAttr, XML_DECLARATION } from '../../xml/xml.js';
|
|
2
|
+
import { boolAttr, escapeAttr, numberText, XML_DECLARATION } from '../../xml/xml.js';
|
|
3
3
|
import { RELATIONSHIPS_NS } from '../opc/namespaces.js';
|
|
4
4
|
import { SPREADSHEETML_NS } from './namespaces.js';
|
|
5
5
|
const METRIC_CAPTIONS = {
|
|
@@ -30,9 +30,10 @@ export function pivotCacheDefinitionXml(table) {
|
|
|
30
30
|
const numeric = field.numeric;
|
|
31
31
|
const descriptor = numeric === null
|
|
32
32
|
? `<sharedItems${blank}/>`
|
|
33
|
-
: `<sharedItems containsSemiMixedTypes="0" containsString="0" containsNumber="1"
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
: `<sharedItems containsSemiMixedTypes="0" containsString="0" containsNumber="1"` +
|
|
34
|
+
boolAttr('containsInteger', numeric.allInteger) +
|
|
35
|
+
blank +
|
|
36
|
+
` minValue="${numberText(numeric.min)}" maxValue="${numberText(numeric.max)}"/>`;
|
|
36
37
|
return `<cacheField name="${escapeAttr(field.name)}" numFmtId="0">${descriptor}</cacheField>`;
|
|
37
38
|
})
|
|
38
39
|
.join('');
|
|
@@ -56,8 +57,8 @@ export function pivotCacheRecordsXml(table) {
|
|
|
56
57
|
`</pivotCacheRecords>`);
|
|
57
58
|
}
|
|
58
59
|
export function pivotTableXml(table, name, cacheId) {
|
|
59
|
-
const rowField = table.rowFields[0];
|
|
60
|
-
const columnField = table.columnFields[0];
|
|
60
|
+
const rowField = table.rowFields[0] ?? 0;
|
|
61
|
+
const columnField = table.columnFields[0] ?? 0;
|
|
61
62
|
const rowGroups = table.cacheFields[rowField]?.sharedItems?.length ?? 1;
|
|
62
63
|
const columnGroups = table.cacheFields[columnField]?.sharedItems?.length ?? 1;
|
|
63
64
|
const location = `A1:${encodeAddress(2 + columnGroups, 3 + rowGroups)}`;
|
|
@@ -107,7 +108,7 @@ function sharedItemXml(item) {
|
|
|
107
108
|
case 'string':
|
|
108
109
|
return `<s v="${escapeAttr(item.value)}"/>`;
|
|
109
110
|
case 'number':
|
|
110
|
-
return `<n v="${item.value}"/>`;
|
|
111
|
+
return `<n v="${numberText(item.value)}"/>`;
|
|
111
112
|
case 'blank':
|
|
112
113
|
return '<m/>';
|
|
113
114
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { CommentThread } from '../../core/comment-thread.ts';
|
|
2
|
+
import { Workbook } from '../../core/workbook.ts';
|
|
3
|
+
import type { Worksheet } from '../../core/worksheet.ts';
|
|
4
|
+
import type { CollectingPass } from '../../xml/xml-read.ts';
|
|
5
|
+
import { type PackageAccessors, type PartRelationships } from '../opc/read-opc.ts';
|
|
6
|
+
import { type ParsedComment } from './comments.ts';
|
|
7
|
+
/**
|
|
8
|
+
* What every part reader in one package read shares: the inflated package, the model being built, the
|
|
9
|
+
* content-type resolver a preserved part's closure is captured through, and the interning map that
|
|
10
|
+
* makes one workbook image per media part however many places point at it.
|
|
11
|
+
*
|
|
12
|
+
* None of the four varies within a read, and threading them positionally is what let `internImage`
|
|
13
|
+
* end up taking the same three in a different order from both of its callers. What genuinely varies
|
|
14
|
+
* -- a part's relationships, the sheet being filled -- stays a positional argument, and the sheet's
|
|
15
|
+
* rels in particular are deliberately *not* in here: they are per sheet, and a stale copy of them
|
|
16
|
+
* would send every sheet's parts to the first sheet's.
|
|
17
|
+
*/
|
|
18
|
+
export interface PackageReadContext {
|
|
19
|
+
readonly pkg: PackageAccessors;
|
|
20
|
+
readonly workbook: Workbook;
|
|
21
|
+
readonly contentTypeOf: (path: string) => string;
|
|
22
|
+
readonly imageIdByMediaPath: Map<string, number>;
|
|
23
|
+
}
|
|
24
|
+
export declare function readSheetComments(sheetRels: PartRelationships): Map<string, ParsedComment> | undefined;
|
|
25
|
+
export declare function readWorkbookPersons({ workbook }: PackageReadContext, workbookRels: PartRelationships): void;
|
|
26
|
+
export declare function readWorkbookTheme(context: PackageReadContext, workbookRels: PartRelationships): void;
|
|
27
|
+
export declare function readSheetCommentThreads({ workbook }: PackageReadContext, sheetRels: PartRelationships): CommentThread[];
|
|
28
|
+
export declare function readSheetPrinterSettings(sheetRels: PartRelationships): Uint8Array | undefined;
|
|
29
|
+
export declare function readSheetImages(context: PackageReadContext, sheetRels: PartRelationships, sheet: Worksheet): void;
|
|
30
|
+
export declare function readSheetBackground(context: PackageReadContext, sheetRels: PartRelationships, sheet: Worksheet): void;
|
|
31
|
+
export declare function readSheetPreservedReferences(context: PackageReadContext, sheetRels: PartRelationships, referenceRelIds: WorksheetReferenceRelIds, sheet: Worksheet): void;
|
|
32
|
+
export declare function readWorkbookPreservedReferences(context: PackageReadContext, workbookRels: PartRelationships, registrations: WorkbookRegistrations): void;
|
|
33
|
+
export declare function readRootPreservedReferences(context: PackageReadContext): void;
|
|
34
|
+
/** The two `<pivotCaches>`/`<externalReferences>` registries a preserved reference is wired by,
|
|
35
|
+
* gathered from the workbook part's own scan rather than from two more of it. */
|
|
36
|
+
export interface WorkbookRegistrations {
|
|
37
|
+
readonly cacheIdByRelId: ReadonlyMap<string, string>;
|
|
38
|
+
readonly externalIndexByRelId: ReadonlyMap<string, number>;
|
|
39
|
+
}
|
|
40
|
+
export declare function pivotCacheRegistrationsPass(): CollectingPass<ReadonlyMap<string, string>>;
|
|
41
|
+
export declare function externalReferenceRegistrationsPass(): CollectingPass<ReadonlyMap<string, number>>;
|
|
42
|
+
/** The `r:id` each of the two element-wired references carries, or `undefined` where absent. */
|
|
43
|
+
export type WorksheetReferenceRelIds = Readonly<Partial<Record<'drawing' | 'legacyDrawingHF', string>>>;
|
|
44
|
+
/**
|
|
45
|
+
* A pass gathering the `r:id` of the first `<drawing>` and `<legacyDrawingHF>` in a worksheet.
|
|
46
|
+
*
|
|
47
|
+
* These two references live in the worksheet body rather than being distinguishable by relationship
|
|
48
|
+
* Type, since a header/footer VML and a comment VML share the `vmlDrawing` type, so the specific
|
|
49
|
+
* relationship is found by reading the element's own `r:id`.
|
|
50
|
+
*
|
|
51
|
+
* A pass rather than its own scan, because the sheet part is the largest in a package by a wide
|
|
52
|
+
* margin and this ran a full extra scan of it, once or twice per sheet, for two attributes.
|
|
53
|
+
* `readSheet` already builds a multi-pass single parse of it whose own comment records that five
|
|
54
|
+
* separate scans "spent 45% of a large file's read on four scans that matched no element"; this was
|
|
55
|
+
* the sixth scan, added later, that the same argument covers.
|
|
56
|
+
*/
|
|
57
|
+
export declare function worksheetReferencePass(): CollectingPass<WorksheetReferenceRelIds>;
|
|
58
|
+
export declare function readSheetTables({ pkg }: PackageReadContext, sheetRels: PartRelationships, sheet: Worksheet): void;
|
|
59
|
+
export declare function readSheetPivotTables({ pkg }: PackageReadContext, sheetRels: PartRelationships, sheet: Worksheet): void;
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { decodeRange } from '../../core/address.js';
|
|
2
|
+
import { INTERNAL } from '../../core/internal.js';
|
|
3
|
+
import { Workbook } from '../../core/workbook.js';
|
|
4
|
+
import { isAnyRelType } from '../../rel-type.js';
|
|
5
|
+
import { localName } from '../../xml/xml-scan.js';
|
|
6
|
+
import { relAttr } from '../opc/namespaces.js';
|
|
7
|
+
import { extensionOf, resolveRelativePart } from '../opc/part-paths.js';
|
|
8
|
+
import { capturePartClosure, parseRelationshipRecords, readPartRelationships, } from '../opc/read-opc.js';
|
|
9
|
+
import { parseComments } from './comments.js';
|
|
10
|
+
import { drawingHasUnmodeledContent, parseDrawing } from './images.js';
|
|
11
|
+
import { parsePivotTable } from './read-pivot.js';
|
|
12
|
+
import { admitting } from './read-repair.js';
|
|
13
|
+
import { parseTable } from './tables.js';
|
|
14
|
+
import { parseThemeColorScheme, parseThemeFontScheme } from './theme-xml.js';
|
|
15
|
+
import { buildCommentThreads, parsePersons, parseThreadedComments } from './threaded-comments.js';
|
|
16
|
+
export function readSheetComments(sheetRels) {
|
|
17
|
+
const commentsXml = sheetRels.relatedText('comments');
|
|
18
|
+
return commentsXml === undefined ? undefined : parseComments(commentsXml);
|
|
19
|
+
}
|
|
20
|
+
export function readWorkbookPersons({ workbook }, workbookRels) {
|
|
21
|
+
const xml = workbookRels.relatedText('person');
|
|
22
|
+
if (xml !== undefined)
|
|
23
|
+
workbook[INTERNAL].restorePersons(parsePersons(xml));
|
|
24
|
+
}
|
|
25
|
+
export function readWorkbookTheme(context, workbookRels) {
|
|
26
|
+
const { pkg, contentTypeOf, workbook } = context;
|
|
27
|
+
const entryPath = workbookRels.targetPath('theme');
|
|
28
|
+
if (entryPath === undefined)
|
|
29
|
+
return;
|
|
30
|
+
const parts = capturePartClosure(entryPath, pkg.partText, pkg.partBytes, contentTypeOf);
|
|
31
|
+
if (parts === undefined)
|
|
32
|
+
return;
|
|
33
|
+
const xml = pkg.partText(entryPath) ?? '';
|
|
34
|
+
workbook[INTERNAL].restoreThemePart({ entryPath, parts }, { colors: parseThemeColorScheme(xml), fonts: parseThemeFontScheme(xml) });
|
|
35
|
+
}
|
|
36
|
+
export function readSheetCommentThreads({ workbook }, sheetRels) {
|
|
37
|
+
const xml = sheetRels.relatedText('threadedComment');
|
|
38
|
+
if (xml === undefined)
|
|
39
|
+
return [];
|
|
40
|
+
return buildCommentThreads(parseThreadedComments(xml), (id) => workbook.getPerson(id));
|
|
41
|
+
}
|
|
42
|
+
export function readSheetPrinterSettings(sheetRels) {
|
|
43
|
+
return sheetRels.relatedBytes('printerSettings');
|
|
44
|
+
}
|
|
45
|
+
function internImage(context, mediaPath) {
|
|
46
|
+
const { workbook, pkg, imageIdByMediaPath } = context;
|
|
47
|
+
const known = imageIdByMediaPath.get(mediaPath);
|
|
48
|
+
if (known !== undefined)
|
|
49
|
+
return known;
|
|
50
|
+
const bytes = pkg.partBytes(mediaPath);
|
|
51
|
+
if (bytes === undefined)
|
|
52
|
+
return undefined;
|
|
53
|
+
const id = workbook.addImage({ buffer: bytes, extension: extensionOf(mediaPath) });
|
|
54
|
+
imageIdByMediaPath.set(mediaPath, id);
|
|
55
|
+
return id;
|
|
56
|
+
}
|
|
57
|
+
export function readSheetImages(context, sheetRels, sheet) {
|
|
58
|
+
const { partText } = context.pkg;
|
|
59
|
+
const drawingPath = sheetRels.targetPath('drawing');
|
|
60
|
+
if (drawingPath === undefined)
|
|
61
|
+
return;
|
|
62
|
+
const drawingXml = partText(drawingPath);
|
|
63
|
+
if (drawingXml === undefined)
|
|
64
|
+
return;
|
|
65
|
+
if (drawingHasUnmodeledContent(drawingXml))
|
|
66
|
+
return;
|
|
67
|
+
const drawingRels = readPartRelationships(drawingPath, partText);
|
|
68
|
+
for (const anchor of parseDrawing(drawingXml)) {
|
|
69
|
+
const embedded = drawingRels.byId(anchor.embed);
|
|
70
|
+
if (embedded === undefined)
|
|
71
|
+
continue;
|
|
72
|
+
const mediaPath = drawingRels.pathOf(embedded.target);
|
|
73
|
+
const id = internImage(context, mediaPath);
|
|
74
|
+
if (id === undefined)
|
|
75
|
+
continue;
|
|
76
|
+
const rot = anchor.rotation !== undefined ? { rotation: anchor.rotation } : {};
|
|
77
|
+
if (anchor.to !== undefined) {
|
|
78
|
+
const mode = anchor.editAs !== undefined ? { editAs: anchor.editAs } : {};
|
|
79
|
+
sheet.addImageAnchor(id, { from: anchor.from, to: anchor.to, ...mode, ...rot });
|
|
80
|
+
}
|
|
81
|
+
else if (anchor.ext !== undefined) {
|
|
82
|
+
sheet.addImageAnchor(id, { from: anchor.from, ext: anchor.ext, ...rot });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export function readSheetBackground(context, sheetRels, sheet) {
|
|
87
|
+
const mediaPath = sheetRels.targetPath('image');
|
|
88
|
+
if (mediaPath === undefined)
|
|
89
|
+
return;
|
|
90
|
+
const id = internImage(context, mediaPath);
|
|
91
|
+
if (id !== undefined)
|
|
92
|
+
sheet.addBackgroundImage(id);
|
|
93
|
+
}
|
|
94
|
+
export function readSheetPreservedReferences(context, sheetRels, referenceRelIds, sheet) {
|
|
95
|
+
const { contentTypeOf } = context;
|
|
96
|
+
const { partText, partBytes } = context.pkg;
|
|
97
|
+
const capture = (element, relType, target) => {
|
|
98
|
+
const entryPath = sheetRels.pathOf(target);
|
|
99
|
+
const parts = capturePartClosure(entryPath, partText, partBytes, contentTypeOf);
|
|
100
|
+
if (parts !== undefined)
|
|
101
|
+
sheet[INTERNAL].addPreservedReference({ element, relType, entryPath, parts });
|
|
102
|
+
};
|
|
103
|
+
const referenceElements = sheet.images.length === 0 ? ['drawing', 'legacyDrawingHF'] : ['legacyDrawingHF'];
|
|
104
|
+
for (const element of referenceElements) {
|
|
105
|
+
const relId = referenceRelIds[element];
|
|
106
|
+
const record = relId === undefined ? undefined : sheetRels.byId(relId);
|
|
107
|
+
if (record !== undefined && !record.external)
|
|
108
|
+
capture(element, record.type, record.target);
|
|
109
|
+
}
|
|
110
|
+
for (const record of sheetRels.records) {
|
|
111
|
+
if (record.external)
|
|
112
|
+
continue;
|
|
113
|
+
if (isPreservedSheetRelType(record.type))
|
|
114
|
+
capture(undefined, record.type, record.target);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function isPreservedSheetRelType(type) {
|
|
118
|
+
return isAnyRelType(type, 'pivotTable', 'slicer');
|
|
119
|
+
}
|
|
120
|
+
export function readWorkbookPreservedReferences(context, workbookRels, registrations) {
|
|
121
|
+
const { contentTypeOf, workbook } = context;
|
|
122
|
+
const { partText, partBytes } = context.pkg;
|
|
123
|
+
const { cacheIdByRelId, externalIndexByRelId } = registrations;
|
|
124
|
+
for (const record of workbookRels.records) {
|
|
125
|
+
if (record.external || !isPreservedWorkbookRelType(record.type))
|
|
126
|
+
continue;
|
|
127
|
+
const entryPath = workbookRels.pathOf(record.target);
|
|
128
|
+
const parts = capturePartClosure(entryPath, partText, partBytes, contentTypeOf);
|
|
129
|
+
if (parts === undefined)
|
|
130
|
+
continue;
|
|
131
|
+
const cacheId = cacheIdByRelId.get(record.id);
|
|
132
|
+
const externalReferenceIndex = externalIndexByRelId.get(record.id);
|
|
133
|
+
workbook[INTERNAL].addPreservedReference({
|
|
134
|
+
relType: record.type,
|
|
135
|
+
entryPath,
|
|
136
|
+
parts,
|
|
137
|
+
...(cacheId !== undefined ? { pivotCacheId: cacheId } : {}),
|
|
138
|
+
...(externalReferenceIndex !== undefined ? { externalReferenceIndex } : {}),
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
export function readRootPreservedReferences(context) {
|
|
143
|
+
const { contentTypeOf, workbook } = context;
|
|
144
|
+
const { partText, partBytes } = context.pkg;
|
|
145
|
+
const relsXml = partText('_rels/.rels');
|
|
146
|
+
if (relsXml === undefined)
|
|
147
|
+
return;
|
|
148
|
+
for (const record of parseRelationshipRecords(relsXml)) {
|
|
149
|
+
if (record.external || isRegeneratedRootRelType(record.type))
|
|
150
|
+
continue;
|
|
151
|
+
const entryPath = resolveRelativePart('', record.target);
|
|
152
|
+
const parts = capturePartClosure(entryPath, partText, partBytes, contentTypeOf);
|
|
153
|
+
if (parts === undefined)
|
|
154
|
+
continue;
|
|
155
|
+
workbook[INTERNAL].addPreservedRootReference({ relType: record.type, entryPath, parts });
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function isRegeneratedRootRelType(type) {
|
|
159
|
+
return isAnyRelType(type, 'officeDocument', 'core-properties', 'extended-properties');
|
|
160
|
+
}
|
|
161
|
+
function isPreservedWorkbookRelType(type) {
|
|
162
|
+
return isAnyRelType(type, 'pivotCacheDefinition', 'slicerCache', 'vbaProject', 'externalLink');
|
|
163
|
+
}
|
|
164
|
+
export function pivotCacheRegistrationsPass() {
|
|
165
|
+
const byRelId = new Map();
|
|
166
|
+
return {
|
|
167
|
+
handlers: {
|
|
168
|
+
onOpen(name, attrs, _selfClosing, scope) {
|
|
169
|
+
if (localName(name) !== 'pivotCache')
|
|
170
|
+
return;
|
|
171
|
+
const relId = relAttr(scope, attrs, 'id');
|
|
172
|
+
if (relId !== undefined && attrs.cacheId !== undefined)
|
|
173
|
+
byRelId.set(relId, attrs.cacheId);
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
result: () => byRelId,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
export function externalReferenceRegistrationsPass() {
|
|
180
|
+
const byRelId = new Map();
|
|
181
|
+
let index = 0;
|
|
182
|
+
return {
|
|
183
|
+
handlers: {
|
|
184
|
+
onOpen(name, attrs, _selfClosing, scope) {
|
|
185
|
+
if (localName(name) !== 'externalReference')
|
|
186
|
+
return;
|
|
187
|
+
const relId = relAttr(scope, attrs, 'id');
|
|
188
|
+
if (relId !== undefined)
|
|
189
|
+
byRelId.set(relId, index++);
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
result: () => byRelId,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
export function worksheetReferencePass() {
|
|
196
|
+
const relIds = {};
|
|
197
|
+
return {
|
|
198
|
+
handlers: {
|
|
199
|
+
onOpen(name, attrs, _selfClosing, scope) {
|
|
200
|
+
const local = localName(name);
|
|
201
|
+
if (local !== 'drawing' && local !== 'legacyDrawingHF')
|
|
202
|
+
return;
|
|
203
|
+
if (relIds[local] !== undefined)
|
|
204
|
+
return;
|
|
205
|
+
const relId = relAttr(scope, attrs, 'id');
|
|
206
|
+
if (relId !== undefined)
|
|
207
|
+
relIds[local] = relId;
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
result: () => relIds,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
export function readSheetTables({ pkg }, sheetRels, sheet) {
|
|
214
|
+
for (const tablePath of sheetRels.targetPaths('table')) {
|
|
215
|
+
const tableXml = pkg.partText(tablePath);
|
|
216
|
+
if (tableXml === undefined)
|
|
217
|
+
continue;
|
|
218
|
+
const options = parseTable(tableXml);
|
|
219
|
+
if (options !== undefined) {
|
|
220
|
+
admitting(() => {
|
|
221
|
+
sheet.addTable(options);
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
dropMergesInsideTables(sheet);
|
|
226
|
+
}
|
|
227
|
+
export function readSheetPivotTables({ pkg }, sheetRels, sheet) {
|
|
228
|
+
const { partText } = pkg;
|
|
229
|
+
for (const tablePath of sheetRels.targetPaths('pivotTable')) {
|
|
230
|
+
const tableXml = partText(tablePath);
|
|
231
|
+
if (tableXml === undefined)
|
|
232
|
+
continue;
|
|
233
|
+
const cacheXml = readPartRelationships(tablePath, partText).relatedText('pivotCacheDefinition') ?? '';
|
|
234
|
+
sheet[INTERNAL].addLoadedPivotTable(parsePivotTable(tableXml, cacheXml));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
function dropMergesInsideTables(sheet) {
|
|
238
|
+
const regions = sheet.tables.map((table) => table.region);
|
|
239
|
+
if (regions.length === 0)
|
|
240
|
+
return;
|
|
241
|
+
for (const range of [...sheet.merges]) {
|
|
242
|
+
const { top, left, bottom, right } = decodeRange(range);
|
|
243
|
+
if (top === undefined || left === undefined || bottom === undefined || right === undefined)
|
|
244
|
+
continue;
|
|
245
|
+
const overlaps = regions.some((region) => left <= region.right &&
|
|
246
|
+
right >= region.left &&
|
|
247
|
+
top <= region.bottom &&
|
|
248
|
+
bottom >= region.top);
|
|
249
|
+
if (overlaps)
|
|
250
|
+
sheet.unmergeCells(range);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isDeclarablePivotSourceKind, pivotMetricFromSubtotal, } from '../../core/pivot-table.js';
|
|
2
|
+
import { numInteger } from '../../xml/xml-attrs.js';
|
|
2
3
|
import { parseXml } from '../../xml/xml-read.js';
|
|
3
|
-
import { localName
|
|
4
|
+
import { localName } from '../../xml/xml-scan.js';
|
|
4
5
|
export function parsePivotTable(tableXml, cacheXml) {
|
|
5
6
|
const { fields, source } = parsePivotCacheDefinition(cacheXml);
|
|
6
7
|
const def = parsePivotTableDefinition(tableXml);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A sheet name from a file, rewritten into one the model will accept.
|
|
3
|
+
*
|
|
4
|
+
* Excel's own repair, in the order the constraints interact: forbidden characters go first (they
|
|
5
|
+
* can be anywhere), then the length ceiling, then the apostrophe rule *again*, because truncating
|
|
6
|
+
* can expose an interior apostrophe at the new edge. An empty result becomes `Sheet{n}`, and a
|
|
7
|
+
* collision takes a ` (2)` suffix that is itself made to fit inside the 31-character limit.
|
|
8
|
+
*
|
|
9
|
+
* @param taken the lower-cased names already in the workbook; sheet names collide
|
|
10
|
+
* case-insensitively, which is the comparison `Workbook.getWorksheet` makes.
|
|
11
|
+
*/
|
|
12
|
+
export declare function repairSheetName(name: string, taken: ReadonlySet<string>): string;
|
|
13
|
+
/**
|
|
14
|
+
* Run a model call that is being handed foreign input, and answer `undefined` where the model
|
|
15
|
+
* refuses it.
|
|
16
|
+
*
|
|
17
|
+
* The three caught types are the three a model method raises *about its argument*: an
|
|
18
|
+
* `AuthoringError` for a composite that cannot exist, and the native `RangeError` / `SyntaxError`
|
|
19
|
+
* the taxonomy assigns to a single scalar that is out of range or does not parse. Every one of them
|
|
20
|
+
* is a statement about the caller, and on this path the caller is a file.
|
|
21
|
+
*
|
|
22
|
+
* Nothing else is caught. An `XlsxError` raised by a layer below is a real failure of the read and
|
|
23
|
+
* keeps its identity; an `InternalError` is a bug of ours and must not be swallowed by a reader
|
|
24
|
+
* being tolerant about somebody else's file.
|
|
25
|
+
*/
|
|
26
|
+
export declare function admitting<T>(build: () => T): T | undefined;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { INVALID_SHEET_NAME_CHARS, MAX_SHEET_NAME_LENGTH } from '../../core/limits.js';
|
|
2
|
+
import { AuthoringError } from '../../errors.js';
|
|
3
|
+
const INVALID_SHEET_NAME_CHARS_GLOBAL = new RegExp(INVALID_SHEET_NAME_CHARS.source, 'g');
|
|
4
|
+
export function repairSheetName(name, taken) {
|
|
5
|
+
const stripped = trimApostrophes(name.replace(INVALID_SHEET_NAME_CHARS_GLOBAL, '')).slice(0, MAX_SHEET_NAME_LENGTH);
|
|
6
|
+
const base = trimApostrophes(stripped);
|
|
7
|
+
if (base.length === 0)
|
|
8
|
+
return firstFree((n) => `Sheet${n}`, taken);
|
|
9
|
+
if (!taken.has(base.toLowerCase()))
|
|
10
|
+
return base;
|
|
11
|
+
return firstFree((n) => withSuffix(base, ` (${n})`), taken, 2);
|
|
12
|
+
}
|
|
13
|
+
function trimApostrophes(name) {
|
|
14
|
+
return name.replace(/^'+/, '').replace(/'+$/, '');
|
|
15
|
+
}
|
|
16
|
+
function firstFree(candidate, taken, from = 1) {
|
|
17
|
+
for (let n = from;; n++) {
|
|
18
|
+
const name = candidate(n);
|
|
19
|
+
if (!taken.has(name.toLowerCase()))
|
|
20
|
+
return name;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function withSuffix(base, suffix) {
|
|
24
|
+
const room = MAX_SHEET_NAME_LENGTH - suffix.length;
|
|
25
|
+
return trimApostrophes(base.slice(0, room)) + suffix;
|
|
26
|
+
}
|
|
27
|
+
export function admitting(build) {
|
|
28
|
+
try {
|
|
29
|
+
return build();
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
if (error instanceof AuthoringError ||
|
|
33
|
+
error instanceof RangeError ||
|
|
34
|
+
error instanceof SyntaxError) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { decodeSpreadsheetText } from '../../xml/xml-attrs.js';
|
|
1
2
|
import { TextCapture } from '../../xml/xml-read.js';
|
|
2
|
-
import {
|
|
3
|
-
import { applyFontChild } from './
|
|
3
|
+
import {} from '../../xml/xml-scan.js';
|
|
4
|
+
import { applyFontChild } from './font-xml.js';
|
|
4
5
|
export class RunAccumulator {
|
|
5
6
|
#container;
|
|
6
7
|
#readRuns;
|
|
@@ -34,12 +35,14 @@ export class RunAccumulator {
|
|
|
34
35
|
this.#plain = '';
|
|
35
36
|
this.#inRun = false;
|
|
36
37
|
this.#isRich = false;
|
|
38
|
+
this.#inContainer = false;
|
|
39
|
+
this.#capture.reset();
|
|
37
40
|
}
|
|
38
41
|
open(local, attrs, selfClosing) {
|
|
39
42
|
switch (local) {
|
|
40
43
|
case this.#container:
|
|
41
|
-
this.#inContainer = true;
|
|
42
44
|
this.beginContainer();
|
|
45
|
+
this.#inContainer = !selfClosing;
|
|
43
46
|
return true;
|
|
44
47
|
case 'r':
|
|
45
48
|
if (!this.#readRuns || !this.#inContainer)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CellValue } from '../../core/value.ts';
|
|
2
|
-
import { type
|
|
3
|
-
export interface ReadSheetRowsOptions extends
|
|
2
|
+
import { type ReadPackageOptions, type XfStyle } from './read.ts';
|
|
3
|
+
export interface ReadSheetRowsOptions extends ReadPackageOptions {
|
|
4
4
|
/**
|
|
5
5
|
* Which worksheet to stream: its name, or its 1-based position in the workbook. Defaults to the
|
|
6
6
|
* first sheet.
|
|
@@ -11,9 +11,18 @@ export interface ReadSheetRowsOptions extends ReadXlsxOptions {
|
|
|
11
11
|
* The resolved style facets of a streamed cell: its own `<c s>` cell format, flattened exactly as
|
|
12
12
|
* the buffered reader resolves it. Present only when the cell carries a format; a consumer can copy
|
|
13
13
|
* these straight onto a writer cell to preserve its look through a streaming read→write.
|
|
14
|
+
*
|
|
15
|
+
* @unpublished A named commitment this surface is not ready to make. `entries/xlsx.ts` records the
|
|
16
|
+
* decision: the streaming reader's granular output shapes stay inferred structural types while the
|
|
17
|
+
* surface settles, so a consumer destructures them and never has to spell them.
|
|
14
18
|
*/
|
|
15
19
|
export type StreamedCellStyle = XfStyle;
|
|
16
|
-
/** One non-empty cell in a {@link StreamedRow}.
|
|
20
|
+
/** One non-empty cell in a {@link StreamedRow}.
|
|
21
|
+
*
|
|
22
|
+
* @unpublished A named commitment this surface is not ready to make. `entries/xlsx.ts` records the
|
|
23
|
+
* decision: the streaming reader's granular output shapes stay inferred structural types while the
|
|
24
|
+
* surface settles, so a consumer destructures them and never has to spell them.
|
|
25
|
+
*/
|
|
17
26
|
export interface StreamedCell {
|
|
18
27
|
/** 1-based column index. */
|
|
19
28
|
readonly col: number;
|
|
@@ -41,6 +50,10 @@ export interface StreamedRow {
|
|
|
41
50
|
* its rows have not already been consumed, so their order relative to `rows()` never matters. (When
|
|
42
51
|
* rows *are* consumed first, the streaming idiom, the accessors reuse that pass and re-scan
|
|
43
52
|
* nothing.)
|
|
53
|
+
*
|
|
54
|
+
* @unpublished A named commitment this surface is not ready to make. `entries/xlsx.ts` records the
|
|
55
|
+
* decision: the streaming reader's granular output shapes stay inferred structural types while the
|
|
56
|
+
* surface settles, so a consumer destructures them and never has to spell them.
|
|
44
57
|
*/
|
|
45
58
|
export interface StreamedSheet {
|
|
46
59
|
/** The worksheet's declared name, joined from the workbook part. Never a positional placeholder. */
|
|
@@ -76,10 +89,10 @@ export declare function readSheetRows(data: Uint8Array, options?: ReadSheetRowsO
|
|
|
76
89
|
* of walking `readXlsx(data).worksheets`.
|
|
77
90
|
*
|
|
78
91
|
* @param data The raw `.xlsx` bytes.
|
|
79
|
-
* @param options The inflate bound (see {@link
|
|
92
|
+
* @param options The inflate bound (see {@link ReadPackageOptions}).
|
|
80
93
|
* @throws {UnsupportedFormatError} if the input is not a readable `.xlsx` package (a legacy `.xls`, a
|
|
81
94
|
* binary `.xlsb`, or an unrecognised/non-ZIP blob; branch on `.format`).
|
|
82
95
|
* @throws {PackageReadError} if the input is a ZIP that cannot be unpacked: a corrupt or
|
|
83
96
|
* truncated archive, or one exceeding the inflate bound (a probable zip bomb).
|
|
84
97
|
*/
|
|
85
|
-
export declare function readWorkbookStream(data: Uint8Array, options?:
|
|
98
|
+
export declare function readWorkbookStream(data: Uint8Array, options?: ReadPackageOptions): Generator<StreamedSheet, void, undefined>;
|