@shbernal/ts-xlsx 3.0.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 +34 -24
- package/dist/bytes.d.ts +10 -2
- package/dist/bytes.js +22 -0
- package/dist/core/address.d.ts +96 -2
- package/dist/core/address.js +87 -33
- package/dist/core/array-formula-ranges.d.ts +33 -0
- package/dist/core/array-formula-ranges.js +62 -0
- 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 +4 -6
- package/dist/core/column.d.ts +1 -0
- package/dist/core/column.js +6 -2
- package/dist/core/comment-thread.d.ts +7 -3
- package/dist/core/comment-thread.js +2 -1
- package/dist/core/conditional-formatting-overlay.d.ts +11 -1
- package/dist/core/conditional-formatting-overlay.js +30 -3
- package/dist/core/conditional-formatting.d.ts +107 -11
- package/dist/core/conditional-formatting.js +76 -19
- package/dist/core/containers.d.ts +12 -0
- package/dist/core/containers.js +5 -0
- package/dist/core/data-validation-overlay.d.ts +7 -1
- package/dist/core/data-validation-overlay.js +19 -4
- package/dist/core/data-validation.d.ts +22 -0
- package/dist/core/data-validation.js +30 -4
- package/dist/core/date-format.d.ts +20 -0
- package/dist/core/date-format.js +170 -0
- package/dist/core/date.d.ts +43 -8
- package/dist/core/date.js +19 -3
- 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 +76 -17
- package/dist/core/formula.js +87 -80
- 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 +30 -3
- package/dist/core/grid-edits.js +248 -81
- package/dist/core/grid-shift.d.ts +58 -9
- package/dist/core/grid-shift.js +26 -4
- package/dist/core/hyperlink.d.ts +39 -0
- package/dist/core/hyperlink.js +88 -0
- package/dist/core/image.d.ts +49 -14
- package/dist/core/image.js +16 -5
- package/dist/core/internal.d.ts +10 -2
- package/dist/core/limits.d.ts +25 -0
- package/dist/core/limits.js +4 -0
- package/dist/core/merge.d.ts +18 -4
- package/dist/core/merge.js +33 -20
- package/dist/core/page-setup.d.ts +26 -11
- package/dist/core/pivot-table.d.ts +49 -10
- package/dist/core/pivot-table.js +112 -60
- package/dist/core/protection.d.ts +66 -4
- package/dist/core/protection.js +6 -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 +6 -2
- package/dist/core/structured-reference.d.ts +7 -0
- package/dist/core/structured-reference.js +7 -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 +64 -16
- package/dist/core/table.js +87 -40
- package/dist/core/theme.d.ts +2 -0
- package/dist/core/theme.js +9 -5
- package/dist/core/value.d.ts +60 -28
- package/dist/core/value.js +48 -43
- package/dist/core/workbook-media.d.ts +34 -0
- package/dist/core/workbook-media.js +44 -0
- package/dist/core/workbook-styles.d.ts +83 -1
- package/dist/core/workbook-styles.js +4 -0
- package/dist/core/workbook-theme.js +5 -3
- package/dist/core/workbook-vba.js +3 -2
- package/dist/core/workbook.d.ts +41 -3
- package/dist/core/workbook.js +46 -41
- package/dist/core/worksheet-comments.d.ts +2 -1
- package/dist/core/worksheet-comments.js +20 -13
- package/dist/core/worksheet-merges.d.ts +49 -0
- package/dist/core/worksheet-merges.js +65 -0
- package/dist/core/worksheet-model.d.ts +10 -2
- package/dist/core/worksheet-model.js +28 -9
- package/dist/core/worksheet-pictures.d.ts +3 -3
- package/dist/core/worksheet-pictures.js +7 -6
- package/dist/core/worksheet.d.ts +165 -27
- package/dist/core/worksheet.js +206 -89
- package/dist/customui/ribbon.js +2 -1
- package/dist/entries/core.d.ts +21 -14
- package/dist/entries/core.js +14 -7
- package/dist/entries/errors.d.ts +1 -0
- package/dist/entries/errors.js +1 -0
- 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/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 +21 -0
- package/dist/io/csv/delimiter.js +18 -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 +51 -22
- package/dist/io/csv/write.d.ts +19 -5
- package/dist/io/csv/write.js +24 -44
- 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 +5 -5
- package/dist/io/opc/read-opc.d.ts +58 -14
- package/dist/io/opc/read-opc.js +49 -21
- 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/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/read-policy/column-budget.js +18 -0
- 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/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 +52 -35
- 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 +495 -596
- package/dist/io/xlsb/read-metadata.d.ts +7 -0
- package/dist/io/xlsb/read-metadata.js +69 -0
- package/dist/io/xlsb/read-styles.js +45 -81
- package/dist/io/xlsb/read-worksheet.d.ts +26 -1
- package/dist/io/xlsb/read-worksheet.js +148 -106
- package/dist/io/xlsb/read.d.ts +6 -3
- package/dist/io/xlsb/read.js +70 -31
- 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 +14 -5
- package/dist/io/xlsb/record-types.js +14 -5
- 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 +24 -9
- package/dist/io/xlsx/cell-accumulator.js +74 -21
- 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 +19 -5
- package/dist/io/xlsx/cell-value.js +45 -30
- package/dist/io/xlsx/color-xml.js +3 -2
- 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 +9 -30
- package/dist/io/xlsx/comments.js +25 -83
- package/dist/io/xlsx/conditional-formatting.d.ts +43 -23
- package/dist/io/xlsx/conditional-formatting.js +437 -138
- package/dist/io/xlsx/data-validation.d.ts +12 -7
- package/dist/io/xlsx/data-validation.js +67 -53
- package/dist/io/xlsx/edit-vba.d.ts +7 -2
- package/dist/io/xlsx/edit-vba.js +52 -52
- 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 +19 -21
- package/dist/io/xlsx/hyperlinks.js +12 -32
- package/dist/io/xlsx/images.d.ts +49 -16
- package/dist/io/xlsx/images.js +149 -50
- package/dist/io/xlsx/namespaces.d.ts +24 -0
- package/dist/io/xlsx/namespaces.js +11 -0
- package/dist/io/xlsx/package-plan.d.ts +60 -15
- package/dist/io/xlsx/package-plan.js +83 -18
- 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 +26 -24
- 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 +59 -0
- package/dist/io/xlsx/read-parts.js +259 -0
- package/dist/io/xlsx/read-pivot.js +11 -4
- package/dist/io/xlsx/{rich-runs.d.ts → read-rich-runs.d.ts} +8 -5
- package/dist/io/xlsx/{rich-runs.js → read-rich-runs.js} +24 -4
- package/dist/io/xlsx/read-rows.d.ts +35 -11
- package/dist/io/xlsx/read-rows.js +73 -49
- package/dist/io/xlsx/read-shared-strings.js +3 -2
- package/dist/io/xlsx/read-styles.d.ts +0 -30
- package/dist/io/xlsx/read-styles.js +45 -105
- package/dist/io/xlsx/read-workbook-xml.d.ts +42 -0
- package/dist/io/xlsx/read-workbook-xml.js +175 -0
- package/dist/io/xlsx/read-worksheet.d.ts +9 -3
- package/dist/io/xlsx/read-worksheet.js +70 -177
- package/dist/io/xlsx/read.d.ts +3 -14
- package/dist/io/xlsx/read.js +74 -411
- package/dist/io/xlsx/relationships.d.ts +3 -0
- package/dist/io/xlsx/relationships.js +4 -0
- package/dist/io/xlsx/rich-text.js +1 -1
- package/dist/io/xlsx/row-position.d.ts +20 -0
- package/dist/io/xlsx/row-position.js +11 -0
- package/dist/io/xlsx/row-xml.d.ts +139 -0
- package/dist/io/xlsx/row-xml.js +222 -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 +182 -20
- 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 +41 -0
- package/dist/io/xlsx/style-elements.js +136 -0
- package/dist/io/xlsx/styles.d.ts +17 -3
- package/dist/io/xlsx/styles.js +13 -209
- package/dist/io/xlsx/tables.d.ts +10 -2
- package/dist/io/xlsx/tables.js +55 -52
- package/dist/io/xlsx/theme-xml.d.ts +32 -4
- package/dist/io/xlsx/theme-xml.js +106 -71
- package/dist/io/xlsx/threaded-comments.d.ts +14 -11
- package/dist/io/xlsx/threaded-comments.js +16 -8
- package/dist/io/xlsx/workbook-xml.d.ts +45 -6
- package/dist/io/xlsx/workbook-xml.js +62 -54
- package/dist/io/xlsx/worksheet-xml.d.ts +26 -70
- package/dist/io/xlsx/worksheet-xml.js +69 -282
- package/dist/io/xlsx/write-stream.d.ts +90 -19
- package/dist/io/xlsx/write-stream.js +80 -25
- package/dist/io/xlsx/write.d.ts +12 -6
- package/dist/io/xlsx/write.js +226 -123
- package/dist/rel-type.d.ts +25 -0
- package/dist/rel-type.js +9 -0
- package/dist/token-set.d.ts +13 -0
- package/dist/token-set.js +4 -1
- package/dist/vba/bytes.d.ts +16 -5
- package/dist/vba/bytes.js +27 -6
- package/dist/vba/cfb-format.d.ts +55 -0
- package/dist/vba/cfb-format.js +35 -0
- package/dist/vba/cfb-writer.d.ts +8 -0
- package/dist/vba/cfb-writer.js +40 -40
- package/dist/vba/cfb.d.ts +21 -4
- package/dist/vba/cfb.js +124 -90
- package/dist/vba/codepage.js +2 -1
- package/dist/vba/dir-records.d.ts +6 -0
- package/dist/vba/dir-records.js +10 -2
- package/dist/vba/errors.d.ts +11 -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 +66 -22
- package/dist/vba/project-editor.js +129 -119
- package/dist/vba/project.d.ts +15 -1
- package/dist/vba/project.js +38 -13
- package/dist/vba/vba-encoding.d.ts +4 -10
- package/dist/vba/vba-encoding.js +3 -17
- 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 +101 -11
- package/dist/xml/xml-read.js +150 -18
- package/dist/xml/xml-scan.d.ts +25 -34
- package/dist/xml/xml-scan.js +69 -46
- package/dist/xml/xml.d.ts +59 -26
- package/dist/xml/xml.js +45 -23
- package/package.json +15 -9
- package/skills/ts-xlsx-upstream/SKILL.md +21 -13
- package/dist/core/modern-functions.d.ts +0 -1
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { INTERNAL } from '../../core/internal.js';
|
|
2
|
+
import { mergesOverlappingTables } from '../../core/merge.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 { admitting } from '../read-policy/read-repair.js';
|
|
10
|
+
import { parseDrawing } from './images.js';
|
|
11
|
+
import { parseComments } from './read-comments.js';
|
|
12
|
+
import { parsePivotTable } from './read-pivot.js';
|
|
13
|
+
import { transitionalPart } from './strict-parts.js';
|
|
14
|
+
import { parseTable } from './tables.js';
|
|
15
|
+
import { parseThemeSchemes } from './theme-xml.js';
|
|
16
|
+
import { buildCommentThreads, parsePersons, parseThreadedComments } from './threaded-comments.js';
|
|
17
|
+
function capturePreservedClosure({ pkg, contentTypeOf }, entryPath) {
|
|
18
|
+
return capturePartClosure(entryPath, pkg.partText, pkg.partBytes, contentTypeOf)?.map((part) => {
|
|
19
|
+
const bytes = transitionalPart(part.bytes, part.contentType);
|
|
20
|
+
return bytes === part.bytes ? part : { ...part, bytes };
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
export function readSheetComments(sheetRels) {
|
|
24
|
+
const commentsXml = sheetRels.relatedText('comments');
|
|
25
|
+
return commentsXml === undefined ? undefined : parseComments(commentsXml);
|
|
26
|
+
}
|
|
27
|
+
export function readWorkbookPersons({ workbook }, workbookRels) {
|
|
28
|
+
const xml = workbookRels.relatedText('person');
|
|
29
|
+
if (xml !== undefined)
|
|
30
|
+
workbook[INTERNAL].restorePersons(parsePersons(xml));
|
|
31
|
+
}
|
|
32
|
+
export function readWorkbookTheme(context, workbookRels) {
|
|
33
|
+
const { pkg, workbook } = context;
|
|
34
|
+
const entryPath = workbookRels.targetPath('theme');
|
|
35
|
+
if (entryPath === undefined)
|
|
36
|
+
return;
|
|
37
|
+
const parts = capturePreservedClosure(context, entryPath);
|
|
38
|
+
if (parts === undefined)
|
|
39
|
+
return;
|
|
40
|
+
const xml = pkg.partText(entryPath) ?? '';
|
|
41
|
+
workbook[INTERNAL].restoreThemePart({ entryPath, parts }, parseThemeSchemes(xml));
|
|
42
|
+
}
|
|
43
|
+
export function readSheetCommentThreads({ workbook }, sheetRels) {
|
|
44
|
+
const xml = sheetRels.relatedText('threadedComment');
|
|
45
|
+
if (xml === undefined)
|
|
46
|
+
return [];
|
|
47
|
+
return buildCommentThreads(parseThreadedComments(xml), (id) => workbook.getPerson(id));
|
|
48
|
+
}
|
|
49
|
+
export function readSheetPrinterSettings(sheetRels) {
|
|
50
|
+
return sheetRels.relatedBytes('printerSettings');
|
|
51
|
+
}
|
|
52
|
+
function internImage(context, mediaPath) {
|
|
53
|
+
const { workbook, pkg, imageIdByMediaPath } = context;
|
|
54
|
+
const known = imageIdByMediaPath.get(mediaPath);
|
|
55
|
+
if (known !== undefined)
|
|
56
|
+
return known;
|
|
57
|
+
const bytes = pkg.partBytes(mediaPath);
|
|
58
|
+
if (bytes === undefined)
|
|
59
|
+
return undefined;
|
|
60
|
+
const id = workbook.addImage({ buffer: bytes, extension: extensionOf(mediaPath) });
|
|
61
|
+
imageIdByMediaPath.set(mediaPath, id);
|
|
62
|
+
return id;
|
|
63
|
+
}
|
|
64
|
+
export function readSheetImages(context, sheetRels, sheet) {
|
|
65
|
+
const { partText } = context.pkg;
|
|
66
|
+
const drawingPath = sheetRels.targetPath('drawing');
|
|
67
|
+
if (drawingPath === undefined)
|
|
68
|
+
return;
|
|
69
|
+
const drawingXml = partText(drawingPath);
|
|
70
|
+
if (drawingXml === undefined)
|
|
71
|
+
return;
|
|
72
|
+
const { anchors, fullyModeled } = parseDrawing(drawingXml);
|
|
73
|
+
if (!fullyModeled)
|
|
74
|
+
return;
|
|
75
|
+
const drawingRels = readPartRelationships(drawingPath, partText);
|
|
76
|
+
for (const anchor of anchors) {
|
|
77
|
+
const embedded = drawingRels.byId(anchor.embed);
|
|
78
|
+
if (embedded === undefined)
|
|
79
|
+
continue;
|
|
80
|
+
const mediaPath = drawingRels.pathOf(embedded.target);
|
|
81
|
+
const id = internImage(context, mediaPath);
|
|
82
|
+
if (id === undefined)
|
|
83
|
+
continue;
|
|
84
|
+
const rot = anchor.rotation !== undefined ? { rotation: anchor.rotation } : {};
|
|
85
|
+
const properties = pictureOf(anchor, drawingRels);
|
|
86
|
+
if (anchor.to !== undefined) {
|
|
87
|
+
const mode = anchor.editAs !== undefined ? { editAs: anchor.editAs } : {};
|
|
88
|
+
sheet.addImageAnchor(id, { from: anchor.from, to: anchor.to, ...mode, ...rot }, properties);
|
|
89
|
+
}
|
|
90
|
+
else if (anchor.ext !== undefined) {
|
|
91
|
+
sheet.addImageAnchor(id, { from: anchor.from, ext: anchor.ext, ...rot }, properties);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function pictureOf(anchor, drawingRels) {
|
|
96
|
+
const { description, title, crop, hyperlinkId, tooltip } = anchor;
|
|
97
|
+
const link = hyperlinkId === undefined ? undefined : drawingRels.byId(hyperlinkId);
|
|
98
|
+
const target = link === undefined || link.target === '' ? undefined : link.target;
|
|
99
|
+
return {
|
|
100
|
+
...(description === undefined ? {} : { description }),
|
|
101
|
+
...(title === undefined ? {} : { title }),
|
|
102
|
+
...(crop === undefined ? {} : { crop }),
|
|
103
|
+
...(target === undefined
|
|
104
|
+
? {}
|
|
105
|
+
: { hyperlink: tooltip === undefined ? { target } : { target, tooltip } }),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
export function readSheetBackground(context, sheetRels, sheet) {
|
|
109
|
+
const mediaPath = sheetRels.targetPath('image');
|
|
110
|
+
if (mediaPath === undefined)
|
|
111
|
+
return;
|
|
112
|
+
const id = internImage(context, mediaPath);
|
|
113
|
+
if (id !== undefined)
|
|
114
|
+
sheet.addBackgroundImage(id);
|
|
115
|
+
}
|
|
116
|
+
export function readSheetPreservedReferences(context, sheetRels, referenceRelIds, sheet) {
|
|
117
|
+
const capture = (element, relType, target) => {
|
|
118
|
+
const entryPath = sheetRels.pathOf(target);
|
|
119
|
+
const parts = capturePreservedClosure(context, entryPath);
|
|
120
|
+
if (parts !== undefined)
|
|
121
|
+
sheet[INTERNAL].addPreservedReference({ element, relType, entryPath, parts });
|
|
122
|
+
};
|
|
123
|
+
const referenceElements = sheet.images.length === 0 ? ['drawing', 'legacyDrawingHF'] : ['legacyDrawingHF'];
|
|
124
|
+
for (const element of referenceElements) {
|
|
125
|
+
const relId = referenceRelIds[element];
|
|
126
|
+
const record = relId === undefined ? undefined : sheetRels.byId(relId);
|
|
127
|
+
if (record !== undefined && !record.external)
|
|
128
|
+
capture(element, record.type, record.target);
|
|
129
|
+
}
|
|
130
|
+
for (const record of sheetRels.records) {
|
|
131
|
+
if (record.external)
|
|
132
|
+
continue;
|
|
133
|
+
if (isPreservedSheetRelType(record.type))
|
|
134
|
+
capture(undefined, record.type, record.target);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function isPreservedSheetRelType(type) {
|
|
138
|
+
return isAnyRelType(type, 'pivotTable', 'slicer');
|
|
139
|
+
}
|
|
140
|
+
export function readWorkbookPreservedReferences(context, workbookRels, registrations) {
|
|
141
|
+
const { workbook } = context;
|
|
142
|
+
const { cacheIdByRelId, externalIndexByRelId } = registrations;
|
|
143
|
+
for (const record of workbookRels.records) {
|
|
144
|
+
if (record.external || !isPreservedWorkbookRelType(record.type))
|
|
145
|
+
continue;
|
|
146
|
+
const entryPath = workbookRels.pathOf(record.target);
|
|
147
|
+
const parts = capturePreservedClosure(context, entryPath);
|
|
148
|
+
if (parts === undefined)
|
|
149
|
+
continue;
|
|
150
|
+
const cacheId = cacheIdByRelId.get(record.id);
|
|
151
|
+
const externalReferenceIndex = externalIndexByRelId.get(record.id);
|
|
152
|
+
workbook[INTERNAL].addPreservedReference({
|
|
153
|
+
relType: record.type,
|
|
154
|
+
entryPath,
|
|
155
|
+
parts,
|
|
156
|
+
...(cacheId !== undefined ? { pivotCacheId: cacheId } : {}),
|
|
157
|
+
...(externalReferenceIndex !== undefined ? { externalReferenceIndex } : {}),
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
export function readRootPreservedReferences(context) {
|
|
162
|
+
const { workbook } = context;
|
|
163
|
+
const relsXml = context.pkg.partText('_rels/.rels');
|
|
164
|
+
if (relsXml === undefined)
|
|
165
|
+
return;
|
|
166
|
+
for (const record of parseRelationshipRecords(relsXml)) {
|
|
167
|
+
if (record.external || isRegeneratedRootRelType(record.type))
|
|
168
|
+
continue;
|
|
169
|
+
const entryPath = resolveRelativePart('', record.target);
|
|
170
|
+
const parts = capturePreservedClosure(context, entryPath);
|
|
171
|
+
if (parts === undefined)
|
|
172
|
+
continue;
|
|
173
|
+
workbook[INTERNAL].addPreservedRootReference({ relType: record.type, entryPath, parts });
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function isRegeneratedRootRelType(type) {
|
|
177
|
+
return isAnyRelType(type, 'officeDocument', 'core-properties', 'extended-properties');
|
|
178
|
+
}
|
|
179
|
+
function isPreservedWorkbookRelType(type) {
|
|
180
|
+
return isAnyRelType(type, 'pivotCacheDefinition', 'slicerCache', 'vbaProject', 'externalLink');
|
|
181
|
+
}
|
|
182
|
+
export function pivotCacheRegistrationsPass() {
|
|
183
|
+
const byRelId = new Map();
|
|
184
|
+
return {
|
|
185
|
+
handlers: {
|
|
186
|
+
onOpen(name, attrs, _selfClosing, scope) {
|
|
187
|
+
if (localName(name) !== 'pivotCache')
|
|
188
|
+
return;
|
|
189
|
+
const relId = relAttr(scope, attrs, 'id');
|
|
190
|
+
if (relId !== undefined && attrs.cacheId !== undefined)
|
|
191
|
+
byRelId.set(relId, attrs.cacheId);
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
result: () => byRelId,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
export function externalReferenceRegistrationsPass() {
|
|
198
|
+
const byRelId = new Map();
|
|
199
|
+
let index = 0;
|
|
200
|
+
return {
|
|
201
|
+
handlers: {
|
|
202
|
+
onOpen(name, attrs, _selfClosing, scope) {
|
|
203
|
+
if (localName(name) !== 'externalReference')
|
|
204
|
+
return;
|
|
205
|
+
const relId = relAttr(scope, attrs, 'id');
|
|
206
|
+
if (relId !== undefined)
|
|
207
|
+
byRelId.set(relId, index++);
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
result: () => byRelId,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
export function worksheetReferencePass() {
|
|
214
|
+
const relIds = {};
|
|
215
|
+
return {
|
|
216
|
+
handlers: {
|
|
217
|
+
onOpen(name, attrs, _selfClosing, scope) {
|
|
218
|
+
const local = localName(name);
|
|
219
|
+
if (local !== 'drawing' && local !== 'legacyDrawingHF')
|
|
220
|
+
return;
|
|
221
|
+
if (relIds[local] !== undefined)
|
|
222
|
+
return;
|
|
223
|
+
const relId = relAttr(scope, attrs, 'id');
|
|
224
|
+
if (relId !== undefined)
|
|
225
|
+
relIds[local] = relId;
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
result: () => relIds,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
export function readSheetTables({ pkg }, sheetRels, sheet, definedNames) {
|
|
232
|
+
for (const tablePath of sheetRels.targetPaths('table')) {
|
|
233
|
+
const tableXml = pkg.partText(tablePath);
|
|
234
|
+
if (tableXml === undefined)
|
|
235
|
+
continue;
|
|
236
|
+
const options = parseTable(tableXml, definedNames);
|
|
237
|
+
if (options !== undefined) {
|
|
238
|
+
admitting(() => {
|
|
239
|
+
sheet.addTable(options);
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
dropMergesInsideTables(sheet);
|
|
244
|
+
}
|
|
245
|
+
export function readSheetPivotTables({ pkg }, sheetRels, sheet) {
|
|
246
|
+
const { partText } = pkg;
|
|
247
|
+
for (const tablePath of sheetRels.targetPaths('pivotTable')) {
|
|
248
|
+
const tableXml = partText(tablePath);
|
|
249
|
+
if (tableXml === undefined)
|
|
250
|
+
continue;
|
|
251
|
+
const cacheXml = readPartRelationships(tablePath, partText).relatedText('pivotCacheDefinition') ?? '';
|
|
252
|
+
sheet[INTERNAL].addLoadedPivotTable(parsePivotTable(tableXml, cacheXml));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function dropMergesInsideTables(sheet) {
|
|
256
|
+
for (const { merge } of mergesOverlappingTables(sheet.merges, sheet.tables)) {
|
|
257
|
+
sheet.unmergeCells(merge);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
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';
|
|
5
|
+
import { relAttr } from '../opc/namespaces.js';
|
|
4
6
|
export function parsePivotTable(tableXml, cacheXml) {
|
|
5
7
|
const { fields, source } = parsePivotCacheDefinition(cacheXml);
|
|
6
8
|
const def = parsePivotTableDefinition(tableXml);
|
|
@@ -19,9 +21,9 @@ export function parsePivotTable(tableXml, cacheXml) {
|
|
|
19
21
|
}
|
|
20
22
|
function parsePivotCacheDefinition(cacheXml) {
|
|
21
23
|
const fields = [];
|
|
22
|
-
let source = { kind: 'worksheet', sheet: '', ref: '' };
|
|
24
|
+
let source = { kind: 'worksheet', sheet: '', ref: '', inAnotherWorkbook: false };
|
|
23
25
|
parseXml(cacheXml, {
|
|
24
|
-
onOpen(name, attrs) {
|
|
26
|
+
onOpen(name, attrs, _selfClosing, scope) {
|
|
25
27
|
const local = localName(name);
|
|
26
28
|
if (local === 'cacheField' && attrs.name !== undefined) {
|
|
27
29
|
fields.push({ name: attrs.name });
|
|
@@ -30,7 +32,12 @@ function parsePivotCacheDefinition(cacheXml) {
|
|
|
30
32
|
source = { ...source, kind: sourceKind(attrs.type) };
|
|
31
33
|
}
|
|
32
34
|
else if (local === 'worksheetSource') {
|
|
33
|
-
source = {
|
|
35
|
+
source = {
|
|
36
|
+
...source,
|
|
37
|
+
sheet: attrs.sheet ?? '',
|
|
38
|
+
ref: attrs.ref ?? '',
|
|
39
|
+
inAnotherWorkbook: relAttr(scope, attrs, 'id') !== undefined,
|
|
40
|
+
};
|
|
34
41
|
}
|
|
35
42
|
},
|
|
36
43
|
});
|
|
@@ -13,19 +13,22 @@ export declare class RunAccumulator {
|
|
|
13
13
|
#private;
|
|
14
14
|
/**
|
|
15
15
|
* @param options.container the element that opens one string: `'si'` for the shared-string pool,
|
|
16
|
-
* `'is'` for an inline string in a worksheet body.
|
|
17
|
-
* @param options.readRuns whether `<r>`/`<rPr>` open a rich-text run.
|
|
18
|
-
*
|
|
19
|
-
* {@link plainText}, which is
|
|
16
|
+
* `'is'` for an inline string in a worksheet body, `'text'` for a note's body.
|
|
17
|
+
* @param options.readRuns whether `<r>`/`<rPr>` open a rich-text run. A cell's string reads them in
|
|
18
|
+
* both worksheet readers, pooled or inline; a note's body does not, and with runs off every `<t>`
|
|
19
|
+
* falls through to {@link plainText}, which is the flattening a plain-text note wants.
|
|
20
20
|
*/
|
|
21
21
|
constructor(options: {
|
|
22
|
-
readonly container: 'si' | 'is';
|
|
22
|
+
readonly container: 'si' | 'is' | 'text';
|
|
23
23
|
readonly readRuns: boolean;
|
|
24
24
|
});
|
|
25
25
|
/** The runs gathered so far. */
|
|
26
26
|
get runs(): RichTextRun[];
|
|
27
27
|
/** Whether the container held at least one `<r>`: what decides rich text from a plain string. */
|
|
28
28
|
get isRich(): boolean;
|
|
29
|
+
/** Whether a container element opened at all since the last {@link beginContainer}. An `<is/>` is an
|
|
30
|
+
* empty string and a `<c t="inlineStr">` with no `<is>` is no string, and only this tells them apart. */
|
|
31
|
+
get opened(): boolean;
|
|
29
32
|
/** The container's own text: every `<t>` no run claimed, concatenated and already unescaped. */
|
|
30
33
|
get plainText(): string;
|
|
31
34
|
/**
|
|
@@ -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;
|
|
@@ -12,7 +13,9 @@ export class RunAccumulator {
|
|
|
12
13
|
#plain = '';
|
|
13
14
|
#inRun = false;
|
|
14
15
|
#isRich = false;
|
|
16
|
+
#opened = false;
|
|
15
17
|
#inContainer = false;
|
|
18
|
+
#phoneticDepth = 0;
|
|
16
19
|
constructor(options) {
|
|
17
20
|
this.#container = options.container;
|
|
18
21
|
this.#readRuns = options.readRuns;
|
|
@@ -23,6 +26,9 @@ export class RunAccumulator {
|
|
|
23
26
|
get isRich() {
|
|
24
27
|
return this.#isRich;
|
|
25
28
|
}
|
|
29
|
+
get opened() {
|
|
30
|
+
return this.#opened;
|
|
31
|
+
}
|
|
26
32
|
get plainText() {
|
|
27
33
|
return this.#plain;
|
|
28
34
|
}
|
|
@@ -34,12 +40,17 @@ export class RunAccumulator {
|
|
|
34
40
|
this.#plain = '';
|
|
35
41
|
this.#inRun = false;
|
|
36
42
|
this.#isRich = false;
|
|
43
|
+
this.#opened = false;
|
|
44
|
+
this.#inContainer = false;
|
|
45
|
+
this.#phoneticDepth = 0;
|
|
46
|
+
this.#capture.reset();
|
|
37
47
|
}
|
|
38
48
|
open(local, attrs, selfClosing) {
|
|
39
49
|
switch (local) {
|
|
40
50
|
case this.#container:
|
|
41
|
-
this.#inContainer = true;
|
|
42
51
|
this.beginContainer();
|
|
52
|
+
this.#inContainer = !selfClosing;
|
|
53
|
+
this.#opened = true;
|
|
43
54
|
return true;
|
|
44
55
|
case 'r':
|
|
45
56
|
if (!this.#readRuns || !this.#inContainer)
|
|
@@ -56,8 +67,13 @@ export class RunAccumulator {
|
|
|
56
67
|
this.#font = {};
|
|
57
68
|
this.#inProperties = true;
|
|
58
69
|
return true;
|
|
70
|
+
case 'rPh':
|
|
71
|
+
if (!selfClosing)
|
|
72
|
+
this.#phoneticDepth++;
|
|
73
|
+
return true;
|
|
59
74
|
case 't':
|
|
60
|
-
this.#
|
|
75
|
+
if (this.#phoneticDepth === 0)
|
|
76
|
+
this.#capture.open(local, selfClosing);
|
|
61
77
|
return true;
|
|
62
78
|
default:
|
|
63
79
|
if (!this.#inProperties || this.#font === null)
|
|
@@ -82,6 +98,10 @@ export class RunAccumulator {
|
|
|
82
98
|
}
|
|
83
99
|
return 'claimed';
|
|
84
100
|
}
|
|
101
|
+
case 'rPh':
|
|
102
|
+
if (this.#phoneticDepth > 0)
|
|
103
|
+
this.#phoneticDepth--;
|
|
104
|
+
return 'claimed';
|
|
85
105
|
case 'rPr':
|
|
86
106
|
if (!this.#readRuns || !this.#inProperties)
|
|
87
107
|
return 'other';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { CellValue } from '../../core/value.ts';
|
|
2
|
-
import
|
|
3
|
-
|
|
2
|
+
import type { ReadPackageOptions } from '../opc/read-options.ts';
|
|
3
|
+
import type { XfStyle } from '../style/xf-style.ts';
|
|
4
|
+
export interface ReadSheetRowsOptions extends ReadPackageOptions {
|
|
4
5
|
/**
|
|
5
6
|
* Which worksheet to stream: its name, or its 1-based position in the workbook. Defaults to the
|
|
6
7
|
* first sheet.
|
|
@@ -8,12 +9,22 @@ export interface ReadSheetRowsOptions extends ReadXlsxOptions {
|
|
|
8
9
|
readonly sheet?: string | number;
|
|
9
10
|
}
|
|
10
11
|
/**
|
|
11
|
-
* The resolved style facets of a streamed cell: its own `<c s>`
|
|
12
|
-
* the
|
|
13
|
-
*
|
|
12
|
+
* The resolved style facets of a streamed cell: its own `<c s>` format, failing that its row's (when
|
|
13
|
+
* the row is marked `customFormat`), failing that its column's, flattened exactly as the buffered
|
|
14
|
+
* reader resolves it. Present only when the cell, its row or its column declares a format; a consumer
|
|
15
|
+
* can copy these straight onto a writer cell to preserve its look through a streaming read→write.
|
|
16
|
+
*
|
|
17
|
+
* @unpublished A named commitment this surface is not ready to make. `entries/xlsx.ts` records the
|
|
18
|
+
* decision: the streaming reader's granular output shapes stay inferred structural types while the
|
|
19
|
+
* surface settles, so a consumer destructures them and never has to spell them.
|
|
14
20
|
*/
|
|
15
21
|
export type StreamedCellStyle = XfStyle;
|
|
16
|
-
/** One non-empty cell in a {@link StreamedRow}.
|
|
22
|
+
/** One non-empty cell in a {@link StreamedRow}.
|
|
23
|
+
*
|
|
24
|
+
* @unpublished A named commitment this surface is not ready to make. `entries/xlsx.ts` records the
|
|
25
|
+
* decision: the streaming reader's granular output shapes stay inferred structural types while the
|
|
26
|
+
* surface settles, so a consumer destructures them and never has to spell them.
|
|
27
|
+
*/
|
|
17
28
|
export interface StreamedCell {
|
|
18
29
|
/** 1-based column index. */
|
|
19
30
|
readonly col: number;
|
|
@@ -21,7 +32,8 @@ export interface StreamedCell {
|
|
|
21
32
|
readonly address: string;
|
|
22
33
|
/** The decoded value, identical to what `readXlsx` would produce for the same cell. */
|
|
23
34
|
readonly value: CellValue;
|
|
24
|
-
/** The cell's resolved style facets,
|
|
35
|
+
/** The cell's resolved style facets, including a format it inherits from its row or column; absent
|
|
36
|
+
* when none of the three declares one. */
|
|
25
37
|
readonly style?: StreamedCellStyle;
|
|
26
38
|
}
|
|
27
39
|
/** One worksheet row, as yielded by {@link readSheetRows} / {@link StreamedSheet.rows}. */
|
|
@@ -41,15 +53,27 @@ export interface StreamedRow {
|
|
|
41
53
|
* its rows have not already been consumed, so their order relative to `rows()` never matters. (When
|
|
42
54
|
* rows *are* consumed first, the streaming idiom, the accessors reuse that pass and re-scan
|
|
43
55
|
* nothing.)
|
|
56
|
+
*
|
|
57
|
+
* @unpublished A named commitment this surface is not ready to make. `entries/xlsx.ts` records the
|
|
58
|
+
* decision: the streaming reader's granular output shapes stay inferred structural types while the
|
|
59
|
+
* surface settles, so a consumer destructures them and never has to spell them.
|
|
44
60
|
*/
|
|
45
61
|
export interface StreamedSheet {
|
|
46
|
-
/**
|
|
62
|
+
/**
|
|
63
|
+
* The worksheet's name, joined from the workbook part and repaired exactly as `readXlsx` repairs it
|
|
64
|
+
* (a duplicate becomes `S (2)`, a forbidden character is removed), so the two readers name a sheet
|
|
65
|
+
* the same way. Never a positional placeholder.
|
|
66
|
+
*/
|
|
47
67
|
readonly name: string;
|
|
48
68
|
/** Stream this sheet's rows, one at a time, in sheet order. */
|
|
49
69
|
rows(): Generator<StreamedRow, void, undefined>;
|
|
50
70
|
/** 1-based indices of columns the sheet declares hidden, ascending. */
|
|
51
71
|
readonly hiddenColumns: readonly number[];
|
|
52
|
-
/**
|
|
72
|
+
/**
|
|
73
|
+
* The sheet's merged ranges, as canonical A1 range strings, in declaration order: the ones
|
|
74
|
+
* `readXlsx` admits, so an unreadable range, or one overlapping a range declared before it, is
|
|
75
|
+
* dropped.
|
|
76
|
+
*/
|
|
53
77
|
readonly merges: readonly string[];
|
|
54
78
|
}
|
|
55
79
|
/**
|
|
@@ -76,10 +100,10 @@ export declare function readSheetRows(data: Uint8Array, options?: ReadSheetRowsO
|
|
|
76
100
|
* of walking `readXlsx(data).worksheets`.
|
|
77
101
|
*
|
|
78
102
|
* @param data The raw `.xlsx` bytes.
|
|
79
|
-
* @param options The inflate bound (see {@link
|
|
103
|
+
* @param options The inflate bound (see {@link ReadPackageOptions}).
|
|
80
104
|
* @throws {UnsupportedFormatError} if the input is not a readable `.xlsx` package (a legacy `.xls`, a
|
|
81
105
|
* binary `.xlsb`, or an unrecognised/non-ZIP blob; branch on `.format`).
|
|
82
106
|
* @throws {PackageReadError} if the input is a ZIP that cannot be unpacked: a corrupt or
|
|
83
107
|
* truncated archive, or one exceeding the inflate bound (a probable zip bomb).
|
|
84
108
|
*/
|
|
85
|
-
export declare function readWorkbookStream(data: Uint8Array, options?:
|
|
109
|
+
export declare function readWorkbookStream(data: Uint8Array, options?: ReadPackageOptions): Generator<StreamedSheet, void, undefined>;
|