@shbernal/ts-xlsx 2.1.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 +5 -4
- package/dist/core/autofilter.js +34 -35
- package/dist/core/axis-handle.d.ts +10 -0
- package/dist/core/axis-handle.js +17 -0
- package/dist/core/cell.d.ts +25 -0
- package/dist/core/cell.js +9 -3
- 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 +5 -1
- package/dist/core/column.js +34 -35
- 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 +14 -6
- package/dist/core/conditional-formatting.js +45 -43
- 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 +9 -3
- package/dist/core/data-validation.js +21 -18
- 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 +14 -10
- package/dist/core/image.js +9 -9
- 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-index.d.ts +31 -0
- package/dist/core/merge-index.js +60 -0
- package/dist/core/merge.d.ts +5 -14
- package/dist/core/merge.js +18 -27
- package/dist/core/page-setup.d.ts +72 -2
- package/dist/core/page-setup.js +34 -8
- package/dist/core/pivot-table.d.ts +1 -1
- package/dist/core/pivot-table.js +67 -53
- 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 +5 -1
- package/dist/core/row.js +22 -23
- package/dist/core/style.d.ts +134 -75
- package/dist/core/style.js +112 -53
- package/dist/core/table-style.d.ts +1 -1
- package/dist/core/table-style.js +4 -4
- package/dist/core/table.d.ts +28 -10
- package/dist/core/table.js +54 -39
- package/dist/core/theme.js +6 -5
- package/dist/core/used-extent.d.ts +44 -0
- package/dist/core/used-extent.js +102 -0
- 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 +72 -12
- package/dist/core/worksheet.js +68 -70
- package/dist/customui/ribbon.js +6 -7
- 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 +15 -1
- 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 +10 -0
- package/dist/io/opc/part-paths.js +16 -1
- package/dist/io/opc/read-opc.d.ts +69 -10
- package/dist/io/opc/read-opc.js +49 -55
- package/dist/io/opc/read-options.d.ts +5 -1
- package/dist/io/opc/rels.d.ts +1 -6
- package/dist/io/opc/rels.js +1 -4
- 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 +48 -2
- package/dist/io/style/xf-style.js +14 -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 +50 -83
- 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 +47 -29
- 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 +9 -2
- 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 -31
- package/dist/io/xlsx/conditional-formatting.d.ts +9 -5
- package/dist/io/xlsx/conditional-formatting.js +51 -46
- package/dist/io/xlsx/data-validation.d.ts +9 -7
- package/dist/io/xlsx/data-validation.js +38 -35
- package/dist/io/xlsx/edit-vba.d.ts +7 -2
- package/dist/io/xlsx/edit-vba.js +15 -29
- 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 +41 -7
- package/dist/io/xlsx/hyperlinks.js +40 -28
- package/dist/io/xlsx/images.js +24 -25
- 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 +23 -3
- package/dist/io/xlsx/package-plan.js +66 -25
- package/dist/io/xlsx/part-names.d.ts +41 -0
- package/dist/io/xlsx/part-names.js +46 -0
- 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 +3 -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.d.ts → read-rich-runs.d.ts} +1 -1
- package/dist/io/xlsx/{rich-runs.js → read-rich-runs.js} +7 -3
- package/dist/io/xlsx/read-rows.d.ts +18 -5
- package/dist/io/xlsx/read-rows.js +50 -37
- package/dist/io/xlsx/read-shared-strings.js +5 -3
- package/dist/io/xlsx/read-styles.d.ts +1 -6
- package/dist/io/xlsx/read-styles.js +65 -109
- 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 +11 -1
- package/dist/io/xlsx/read-worksheet.js +51 -193
- package/dist/io/xlsx/read.d.ts +5 -13
- package/dist/io/xlsx/read.js +111 -436
- 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 +166 -37
- 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 -204
- package/dist/io/xlsx/tables.js +11 -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 +3 -1
- package/dist/io/xlsx/workbook-xml.d.ts +54 -4
- package/dist/io/xlsx/workbook-xml.js +84 -57
- package/dist/io/xlsx/worksheet-xml.d.ts +23 -70
- package/dist/io/xlsx/worksheet-xml.js +59 -242
- package/dist/io/xlsx/write-stream.d.ts +71 -16
- package/dist/io/xlsx/write-stream.js +79 -41
- package/dist/io/xlsx/write.d.ts +6 -2
- package/dist/io/xlsx/write.js +217 -153
- package/dist/rel-type.d.ts +16 -0
- package/dist/rel-type.js +6 -0
- package/dist/token-set.d.ts +28 -0
- package/dist/token-set.js +7 -0
- package/dist/vba/bytes.d.ts +14 -5
- package/dist/vba/bytes.js +16 -6
- package/dist/vba/cfb-format.d.ts +32 -0
- package/dist/vba/cfb-format.js +13 -0
- package/dist/vba/cfb-writer.d.ts +9 -0
- package/dist/vba/cfb-writer.js +28 -25
- package/dist/vba/cfb.d.ts +13 -1
- package/dist/vba/cfb.js +73 -57
- package/dist/vba/codepage.js +2 -1
- package/dist/vba/errors.d.ts +7 -0
- package/dist/vba/ms-ovba.js +79 -23
- package/dist/vba/project-editor.js +35 -40
- package/dist/vba/project.d.ts +11 -1
- package/dist/vba/project.js +40 -21
- package/dist/vba/vba-encoding.js +5 -6
- 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 +128 -81
- package/dist/xml/xml-read.js +161 -178
- package/dist/xml/xml-scan.d.ts +78 -0
- package/dist/xml/xml-scan.js +180 -0
- package/dist/xml/xml.d.ts +29 -28
- package/dist/xml/xml.js +24 -24
- package/package.json +13 -9
package/dist/io/xlsx/read.js
CHANGED
|
@@ -1,54 +1,49 @@
|
|
|
1
|
-
import { decodeRange } from '../../core/address.js';
|
|
2
|
-
import { unmangleFunctions } from '../../core/formula.js';
|
|
3
1
|
import { INTERNAL } from '../../core/internal.js';
|
|
4
|
-
import { WORKBOOK_PROTECTION_CREDENTIAL_ATTRS, } from '../../core/workbook-protection.js';
|
|
5
2
|
import { Workbook } from '../../core/workbook.js';
|
|
6
|
-
import {
|
|
7
|
-
import { boolStrict, capturedText, enumToken, localName, numInteger, openElements, parseXml, } from '../../xml/xml-read.js';
|
|
3
|
+
import { parseXmlPasses } from '../../xml/xml-read.js';
|
|
8
4
|
import { UnsupportedFormatError } from '../opc/errors.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import { drawingHasUnmodeledContent, parseDrawing } from './images.js';
|
|
19
|
-
import { parsePivotTable } from './read-pivot.js';
|
|
5
|
+
import { contentTypeResolver, openSpreadsheetPackage, readPartRelationships, } from '../opc/read-opc.js';
|
|
6
|
+
import { readXlsbPackage } from '../xlsb/read.js';
|
|
7
|
+
import { applyNotes } from './comments.js';
|
|
8
|
+
import { conditionalFormattingPass } from './conditional-formatting.js';
|
|
9
|
+
import { applyDataValidations, dataValidationPass, extendedDataValidationPass, } from './data-validation.js';
|
|
10
|
+
import { applyHyperlinks, sheetHyperlinkPass } from './hyperlinks.js';
|
|
11
|
+
import { SHARED_STRINGS_PART, STYLES_PART } from './part-names.js';
|
|
12
|
+
import { readRootPreservedReferences, readSheetBackground, readSheetComments, readSheetCommentThreads, readSheetImages, readSheetPivotTables, readSheetPreservedReferences, readSheetPrinterSettings, readSheetTables, readWorkbookPersons, externalReferenceRegistrationsPass, pivotCacheRegistrationsPass, readWorkbookPreservedReferences, readWorkbookTheme, worksheetReferencePass, } from './read-parts.js';
|
|
13
|
+
import { admitting, repairSheetName } from './read-repair.js';
|
|
20
14
|
import { parseSharedStrings } from './read-shared-strings.js';
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import { parseThemeColorScheme, parseThemeFontScheme } from './theme-xml.js';
|
|
25
|
-
import { buildCommentThreads, parsePersons, parseThreadedComments } from './threaded-comments.js';
|
|
26
|
-
export { parseRelationships, resolveWorkbookPart } from '../opc/read-opc.js';
|
|
27
|
-
export { DEFAULT_MAX_UNCOMPRESSED } from '../opc/read-options.js';
|
|
15
|
+
import { parseStyleTable } from './read-styles.js';
|
|
16
|
+
import { applyAppProperties, applyCoreProperties, definedNamesPass, workbookPropertiesPass, workbookProtectionPass, workbookSheetsPass, workbookViewPass, } from './read-workbook-xml.js';
|
|
17
|
+
import { worksheetPass } from './read-worksheet.js';
|
|
28
18
|
export { parseStyleTable } from './read-styles.js';
|
|
19
|
+
export { workbookPropertiesPass, workbookSheetsPass, workbookViewPass, } from './read-workbook-xml.js';
|
|
29
20
|
export function readXlsx(data, options = {}) {
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
const pkg = packageAccessors(files);
|
|
33
|
-
const { partText } = pkg;
|
|
34
|
-
const workbookXml = partText('xl/workbook.xml');
|
|
21
|
+
const { files, pkg, documentPath, workbookXml } = openSpreadsheetPackage(data, options.maxUncompressedBytes);
|
|
22
|
+
const { partText, partBytes } = pkg;
|
|
35
23
|
if (workbookXml === undefined) {
|
|
36
|
-
if (
|
|
37
|
-
return readXlsbPackage(files);
|
|
24
|
+
if (partBytes(documentPath) !== undefined)
|
|
25
|
+
return readXlsbPackage(files, documentPath);
|
|
38
26
|
throw new UnsupportedFormatError('unknown');
|
|
39
27
|
}
|
|
40
28
|
const contentTypeOf = contentTypeResolver(partText('[Content_Types].xml') ?? '');
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
const { cellXfs: xfStyles, namedStyles, defaultFont } = parseStyleTable(stylesXml);
|
|
29
|
+
const workbookRels = readPartRelationships(documentPath, partText);
|
|
30
|
+
const sharedStrings = parseSharedStrings(workbookRels.relatedTextOrPath('sharedStrings', SHARED_STRINGS_PART));
|
|
31
|
+
const stylesXml = workbookRels.relatedTextOrPath('styles', STYLES_PART);
|
|
32
|
+
const { cellXfs: xfStyles, namedStyles, defaultFont, preserved } = parseStyleTable(stylesXml);
|
|
46
33
|
const workbook = new Workbook();
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
34
|
+
const context = {
|
|
35
|
+
pkg,
|
|
36
|
+
workbook,
|
|
37
|
+
contentTypeOf,
|
|
38
|
+
sharedStrings,
|
|
39
|
+
xfStyles,
|
|
40
|
+
imageIdByMediaPath: new Map(),
|
|
41
|
+
};
|
|
42
|
+
workbook[INTERNAL].restoreDifferentialStyles([...preserved.dxfs]);
|
|
43
|
+
workbook[INTERNAL].restoreIndexedColors([...preserved.indexedColors]);
|
|
44
|
+
workbook[INTERNAL].restoreMruColors([...preserved.mruColors]);
|
|
45
|
+
workbook[INTERNAL].restoreTableStyles(preserved.tableStyles);
|
|
46
|
+
readWorkbookTheme(context, workbookRels);
|
|
52
47
|
if (namedStyles.length > 1)
|
|
53
48
|
workbook[INTERNAL].restoreNamedStyles(namedStyles);
|
|
54
49
|
workbook[INTERNAL].restoreDefaultFont(defaultFont);
|
|
@@ -58,408 +53,88 @@ export function readXlsx(data, options = {}) {
|
|
|
58
53
|
const app = partText('docProps/app.xml');
|
|
59
54
|
if (app !== undefined)
|
|
60
55
|
applyAppProperties(workbook, app);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const
|
|
56
|
+
const protection = workbookProtectionPass();
|
|
57
|
+
const sheets = workbookSheetsPass();
|
|
58
|
+
const definedNames = definedNamesPass();
|
|
59
|
+
const pivotCaches = pivotCacheRegistrationsPass();
|
|
60
|
+
const externalReferences = externalReferenceRegistrationsPass();
|
|
61
|
+
parseXmlPasses(workbookXml, [
|
|
62
|
+
protection,
|
|
63
|
+
workbookPropertiesPass(workbook),
|
|
64
|
+
workbookViewPass(workbook.view),
|
|
65
|
+
sheets,
|
|
66
|
+
definedNames,
|
|
67
|
+
pivotCaches,
|
|
68
|
+
externalReferences,
|
|
69
|
+
]);
|
|
70
|
+
workbook.protection = protection.result();
|
|
71
|
+
readWorkbookPersons(context, workbookRels);
|
|
65
72
|
const sheetOrder = [];
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
for (const cf of parseConditionalFormattings(sheetXml))
|
|
83
|
-
sheet.addConditionalFormatting(cf);
|
|
84
|
-
}
|
|
85
|
-
const threads = readSheetCommentThreads(sheetRels, pkg, workbook);
|
|
86
|
-
if (threads.length > 0)
|
|
87
|
-
sheet[INTERNAL].restoreCommentThreads(threads);
|
|
88
|
-
const comments = readSheetComments(sheetRels, pkg);
|
|
89
|
-
if (comments !== undefined)
|
|
90
|
-
applyNotes(sheet, comments);
|
|
91
|
-
readSheetImages(sheetRels, pkg, workbook, sheet, imageIdByMediaPath);
|
|
92
|
-
readSheetBackground(sheetRels, pkg, workbook, sheet, imageIdByMediaPath);
|
|
93
|
-
if (sheetXml !== undefined) {
|
|
94
|
-
readSheetPreservedReferences(sheetRels, sheetXml, pkg, contentTypeOf, sheet);
|
|
95
|
-
}
|
|
96
|
-
readSheetTables(sheetRels, pkg, sheet);
|
|
97
|
-
readSheetPivotTables(sheetRels, pkg, sheet);
|
|
98
|
-
const printerSettings = readSheetPrinterSettings(sheetRels, pkg);
|
|
99
|
-
if (printerSettings !== undefined)
|
|
100
|
-
sheet.pageSetup.printerSettings = printerSettings;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
readWorkbookPreservedReferences(workbookXml, pkg, contentTypeOf, workbook);
|
|
104
|
-
readRootPreservedReferences(pkg, contentTypeOf, workbook);
|
|
105
|
-
for (const name of parseWorkbookDefinedNames(workbookXml, sheetOrder)) {
|
|
106
|
-
workbook.defineName(name);
|
|
107
|
-
}
|
|
108
|
-
return workbook;
|
|
109
|
-
}
|
|
110
|
-
function readSheetComments(sheetRels, pkg) {
|
|
111
|
-
const commentsPath = sheetRels.targetPath('comments');
|
|
112
|
-
if (commentsPath === undefined)
|
|
113
|
-
return undefined;
|
|
114
|
-
const commentsXml = pkg.partText(commentsPath);
|
|
115
|
-
if (commentsXml === undefined)
|
|
116
|
-
return undefined;
|
|
117
|
-
return parseComments(commentsXml);
|
|
118
|
-
}
|
|
119
|
-
function readWorkbookPersons(workbookRelsXml, pkg, workbook) {
|
|
120
|
-
const target = relationshipTargetByType(workbookRelsXml, 'person');
|
|
121
|
-
const xml = target === undefined ? undefined : pkg.partText(resolveWorkbookPart(target));
|
|
122
|
-
if (xml !== undefined)
|
|
123
|
-
workbook[INTERNAL].restorePersons(parsePersons(xml));
|
|
124
|
-
}
|
|
125
|
-
function readWorkbookTheme(workbookRelsXml, pkg, contentTypeOf, workbook) {
|
|
126
|
-
const target = relationshipTargetByType(workbookRelsXml, 'theme');
|
|
127
|
-
if (target === undefined)
|
|
128
|
-
return;
|
|
129
|
-
const entryPath = resolveWorkbookPart(target);
|
|
130
|
-
const parts = capturePartClosure(entryPath, pkg.partText, pkg.partBytes, contentTypeOf);
|
|
131
|
-
if (parts === undefined)
|
|
132
|
-
return;
|
|
133
|
-
const xml = pkg.partText(entryPath) ?? '';
|
|
134
|
-
workbook[INTERNAL].restoreThemePart({ entryPath, parts }, { colors: parseThemeColorScheme(xml), fonts: parseThemeFontScheme(xml) });
|
|
135
|
-
}
|
|
136
|
-
function readSheetCommentThreads(sheetRels, pkg, workbook) {
|
|
137
|
-
const path = sheetRels.targetPath('threadedComment');
|
|
138
|
-
const xml = path === undefined ? undefined : pkg.partText(path);
|
|
139
|
-
if (xml === undefined)
|
|
140
|
-
return [];
|
|
141
|
-
return buildCommentThreads(parseThreadedComments(xml), (id) => workbook.getPerson(id));
|
|
142
|
-
}
|
|
143
|
-
function readSheetPrinterSettings(sheetRels, pkg) {
|
|
144
|
-
const path = sheetRels.targetPath('printerSettings');
|
|
145
|
-
return path === undefined ? undefined : pkg.partBytes(path);
|
|
146
|
-
}
|
|
147
|
-
function internImage(workbook, pkg, imageIdByMediaPath, mediaPath) {
|
|
148
|
-
const known = imageIdByMediaPath.get(mediaPath);
|
|
149
|
-
if (known !== undefined)
|
|
150
|
-
return known;
|
|
151
|
-
const bytes = pkg.partBytes(mediaPath);
|
|
152
|
-
if (bytes === undefined)
|
|
153
|
-
return undefined;
|
|
154
|
-
const id = workbook.addImage({ buffer: bytes, extension: extensionOf(mediaPath) });
|
|
155
|
-
imageIdByMediaPath.set(mediaPath, id);
|
|
156
|
-
return id;
|
|
157
|
-
}
|
|
158
|
-
function readSheetImages(sheetRels, pkg, workbook, sheet, imageIdByMediaPath) {
|
|
159
|
-
const { partText } = pkg;
|
|
160
|
-
const drawingPath = sheetRels.targetPath('drawing');
|
|
161
|
-
if (drawingPath === undefined)
|
|
162
|
-
return;
|
|
163
|
-
const drawingXml = partText(drawingPath);
|
|
164
|
-
if (drawingXml === undefined)
|
|
165
|
-
return;
|
|
166
|
-
if (drawingHasUnmodeledContent(drawingXml))
|
|
167
|
-
return;
|
|
168
|
-
const drawingRels = readPartRelationships(drawingPath, partText);
|
|
169
|
-
for (const anchor of parseDrawing(drawingXml)) {
|
|
170
|
-
const embedded = drawingRels.byId(anchor.embed);
|
|
171
|
-
if (embedded === undefined)
|
|
172
|
-
continue;
|
|
173
|
-
const mediaPath = drawingRels.pathOf(embedded.target);
|
|
174
|
-
const id = internImage(workbook, pkg, imageIdByMediaPath, mediaPath);
|
|
175
|
-
if (id === undefined)
|
|
176
|
-
continue;
|
|
177
|
-
const rot = anchor.rotation !== undefined ? { rotation: anchor.rotation } : {};
|
|
178
|
-
if (anchor.to !== undefined) {
|
|
179
|
-
const mode = anchor.editAs !== undefined ? { editAs: anchor.editAs } : {};
|
|
180
|
-
sheet.addImageAnchor(id, { from: anchor.from, to: anchor.to, ...mode, ...rot });
|
|
181
|
-
}
|
|
182
|
-
else if (anchor.ext !== undefined) {
|
|
183
|
-
sheet.addImageAnchor(id, { from: anchor.from, ext: anchor.ext, ...rot });
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
function readSheetBackground(sheetRels, pkg, workbook, sheet, imageIdByMediaPath) {
|
|
188
|
-
const mediaPath = sheetRels.targetPath('image');
|
|
189
|
-
if (mediaPath === undefined)
|
|
190
|
-
return;
|
|
191
|
-
const id = internImage(workbook, pkg, imageIdByMediaPath, mediaPath);
|
|
192
|
-
if (id !== undefined)
|
|
193
|
-
sheet.addBackgroundImage(id);
|
|
194
|
-
}
|
|
195
|
-
function readSheetPreservedReferences(sheetRels, sheetXml, pkg, contentTypeOf, sheet) {
|
|
196
|
-
const { partText, partBytes } = pkg;
|
|
197
|
-
const capture = (element, relType, target) => {
|
|
198
|
-
const entryPath = sheetRels.pathOf(target);
|
|
199
|
-
const parts = capturePartClosure(entryPath, partText, partBytes, contentTypeOf);
|
|
200
|
-
if (parts !== undefined)
|
|
201
|
-
sheet[INTERNAL].addPreservedReference({ element, relType, entryPath, parts });
|
|
202
|
-
};
|
|
203
|
-
const referenceElements = sheet.images.length === 0 ? ['drawing', 'legacyDrawingHF'] : ['legacyDrawingHF'];
|
|
204
|
-
for (const element of referenceElements) {
|
|
205
|
-
const relId = worksheetReferenceRelId(sheetXml, element);
|
|
206
|
-
const record = relId === undefined ? undefined : sheetRels.byId(relId);
|
|
207
|
-
if (record !== undefined && !record.external)
|
|
208
|
-
capture(element, record.type, record.target);
|
|
209
|
-
}
|
|
210
|
-
for (const record of sheetRels.records) {
|
|
211
|
-
if (record.external)
|
|
212
|
-
continue;
|
|
213
|
-
if (isPreservedSheetRelType(record.type))
|
|
214
|
-
capture(undefined, record.type, record.target);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
function isPreservedSheetRelType(type) {
|
|
218
|
-
return type.endsWith('/pivotTable') || type.endsWith('/slicer');
|
|
219
|
-
}
|
|
220
|
-
function readWorkbookPreservedReferences(workbookXml, pkg, contentTypeOf, workbook) {
|
|
221
|
-
const { partText, partBytes } = pkg;
|
|
222
|
-
const relsXml = partText('xl/_rels/workbook.xml.rels');
|
|
223
|
-
if (relsXml === undefined)
|
|
224
|
-
return;
|
|
225
|
-
const cacheIdByRelId = parsePivotCacheRegistrations(workbookXml);
|
|
226
|
-
const externalIndexByRelId = parseExternalReferenceRegistrations(workbookXml);
|
|
227
|
-
for (const record of parseRelationshipRecords(relsXml)) {
|
|
228
|
-
if (record.external || !isPreservedWorkbookRelType(record.type))
|
|
229
|
-
continue;
|
|
230
|
-
const entryPath = resolveWorkbookPart(record.target);
|
|
231
|
-
const parts = capturePartClosure(entryPath, partText, partBytes, contentTypeOf);
|
|
232
|
-
if (parts === undefined)
|
|
233
|
-
continue;
|
|
234
|
-
const cacheId = cacheIdByRelId.get(record.id);
|
|
235
|
-
const externalReferenceIndex = externalIndexByRelId.get(record.id);
|
|
236
|
-
workbook[INTERNAL].addPreservedReference({
|
|
237
|
-
relType: record.type,
|
|
238
|
-
entryPath,
|
|
239
|
-
parts,
|
|
240
|
-
...(cacheId !== undefined ? { pivotCacheId: cacheId } : {}),
|
|
241
|
-
...(externalReferenceIndex !== undefined ? { externalReferenceIndex } : {}),
|
|
73
|
+
const takenSheetNames = new Set();
|
|
74
|
+
for (const { name, relId, state } of sheets.result()) {
|
|
75
|
+
const target = workbookRels.byId(relId)?.target;
|
|
76
|
+
const sheet = workbook.addWorksheet(repairSheetName(name, takenSheetNames), state === undefined ? undefined : { state });
|
|
77
|
+
takenSheetNames.add(sheet.name.toLowerCase());
|
|
78
|
+
sheetOrder.push(sheet.name);
|
|
79
|
+
readSheet(sheet, target === undefined ? undefined : workbookRels.pathOf(target), context);
|
|
80
|
+
}
|
|
81
|
+
readWorkbookPreservedReferences(context, workbookRels, {
|
|
82
|
+
cacheIdByRelId: pivotCaches.result(),
|
|
83
|
+
externalIndexByRelId: externalReferences.result(),
|
|
84
|
+
});
|
|
85
|
+
readRootPreservedReferences(context);
|
|
86
|
+
for (const name of definedNames.result(sheetOrder)) {
|
|
87
|
+
admitting(() => {
|
|
88
|
+
workbook.defineName(name);
|
|
242
89
|
});
|
|
243
90
|
}
|
|
91
|
+
return workbook;
|
|
244
92
|
}
|
|
245
|
-
function
|
|
246
|
-
const {
|
|
247
|
-
const relsXml = partText('_rels/.rels');
|
|
248
|
-
if (relsXml === undefined)
|
|
249
|
-
return;
|
|
250
|
-
for (const record of parseRelationshipRecords(relsXml)) {
|
|
251
|
-
if (record.external || isRegeneratedRootRelType(record.type))
|
|
252
|
-
continue;
|
|
253
|
-
const entryPath = resolveRelativePart('', record.target);
|
|
254
|
-
const parts = capturePartClosure(entryPath, partText, partBytes, contentTypeOf);
|
|
255
|
-
if (parts === undefined)
|
|
256
|
-
continue;
|
|
257
|
-
workbook[INTERNAL].addPreservedRootReference({ relType: record.type, entryPath, parts });
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
function isRegeneratedRootRelType(type) {
|
|
261
|
-
return (type.endsWith('/officeDocument') ||
|
|
262
|
-
type.endsWith('/core-properties') ||
|
|
263
|
-
type.endsWith('/extended-properties'));
|
|
264
|
-
}
|
|
265
|
-
function isPreservedWorkbookRelType(type) {
|
|
266
|
-
return (type.endsWith('/pivotCacheDefinition') ||
|
|
267
|
-
type.endsWith('/slicerCache') ||
|
|
268
|
-
type.endsWith('/vbaProject') ||
|
|
269
|
-
type.endsWith('/externalLink'));
|
|
270
|
-
}
|
|
271
|
-
function parsePivotCacheRegistrations(workbookXml) {
|
|
272
|
-
const byRelId = new Map();
|
|
273
|
-
for (const { attrs } of openElements(workbookXml, 'pivotCache')) {
|
|
274
|
-
if (attrs['r:id'] !== undefined && attrs.cacheId !== undefined) {
|
|
275
|
-
byRelId.set(attrs['r:id'], attrs.cacheId);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
return byRelId;
|
|
279
|
-
}
|
|
280
|
-
function parseExternalReferenceRegistrations(workbookXml) {
|
|
281
|
-
const byRelId = new Map();
|
|
282
|
-
let index = 0;
|
|
283
|
-
for (const { attrs } of openElements(workbookXml, 'externalReference')) {
|
|
284
|
-
if (attrs['r:id'] !== undefined)
|
|
285
|
-
byRelId.set(attrs['r:id'], index++);
|
|
286
|
-
}
|
|
287
|
-
return byRelId;
|
|
288
|
-
}
|
|
289
|
-
function worksheetReferenceRelId(sheetXml, element) {
|
|
290
|
-
for (const { attrs } of openElements(sheetXml, element)) {
|
|
291
|
-
if (attrs['r:id'] !== undefined)
|
|
292
|
-
return attrs['r:id'];
|
|
293
|
-
}
|
|
294
|
-
return undefined;
|
|
295
|
-
}
|
|
296
|
-
function readSheetTables(sheetRels, pkg, sheet) {
|
|
297
|
-
for (const tablePath of sheetRels.targetPaths('table')) {
|
|
298
|
-
const tableXml = pkg.partText(tablePath);
|
|
299
|
-
if (tableXml === undefined)
|
|
300
|
-
continue;
|
|
301
|
-
const options = parseTable(tableXml);
|
|
302
|
-
if (options !== undefined)
|
|
303
|
-
sheet.addTable(options);
|
|
304
|
-
}
|
|
305
|
-
dropMergesInsideTables(sheet);
|
|
306
|
-
}
|
|
307
|
-
function readSheetPivotTables(sheetRels, pkg, sheet) {
|
|
93
|
+
function readSheet(sheet, path, context) {
|
|
94
|
+
const { pkg, workbook, sharedStrings, xfStyles } = context;
|
|
308
95
|
const { partText } = pkg;
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
const overlaps = regions.some((region) => left <= region.right &&
|
|
327
|
-
right >= region.left &&
|
|
328
|
-
top <= region.bottom &&
|
|
329
|
-
bottom >= region.top);
|
|
330
|
-
if (overlaps)
|
|
331
|
-
sheet.unmergeCells(range);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
export function parseWorkbookSheets(xml) {
|
|
335
|
-
const sheets = [];
|
|
336
|
-
for (const { attrs } of openElements(xml, 'sheet')) {
|
|
337
|
-
const entry = {
|
|
338
|
-
name: attrs.name ?? '',
|
|
339
|
-
relId: attrs['r:id'] ?? '',
|
|
340
|
-
};
|
|
341
|
-
const state = enumToken(attrs.state, isVisibility);
|
|
342
|
-
if (state !== undefined && state !== 'visible')
|
|
343
|
-
entry.state = state;
|
|
344
|
-
sheets.push(entry);
|
|
345
|
-
}
|
|
346
|
-
return sheets;
|
|
347
|
-
}
|
|
348
|
-
function parseWorkbookProtection(xml) {
|
|
349
|
-
let result;
|
|
350
|
-
parseXml(xml, {
|
|
351
|
-
onOpen(name, attrs) {
|
|
352
|
-
if (localName(name) !== 'workbookProtection')
|
|
353
|
-
return;
|
|
354
|
-
const protection = {};
|
|
355
|
-
if (boolStrict(attrs.lockStructure))
|
|
356
|
-
protection.lockStructure = true;
|
|
357
|
-
if (boolStrict(attrs.lockWindows))
|
|
358
|
-
protection.lockWindows = true;
|
|
359
|
-
if (boolStrict(attrs.lockRevision))
|
|
360
|
-
protection.lockRevision = true;
|
|
361
|
-
const credentials = {};
|
|
362
|
-
for (const key of WORKBOOK_PROTECTION_CREDENTIAL_ATTRS) {
|
|
363
|
-
const value = attrs[key];
|
|
364
|
-
if (value !== undefined)
|
|
365
|
-
credentials[key] = value;
|
|
366
|
-
}
|
|
367
|
-
if (Object.keys(credentials).length > 0)
|
|
368
|
-
protection.credentials = credentials;
|
|
369
|
-
result = protection;
|
|
370
|
-
},
|
|
371
|
-
});
|
|
372
|
-
return result;
|
|
373
|
-
}
|
|
374
|
-
export function applyWorkbookView(view, xml) {
|
|
375
|
-
for (const { attrs } of openElements(xml, 'workbookView')) {
|
|
376
|
-
const x = numInteger(attrs.xWindow);
|
|
377
|
-
if (x !== undefined)
|
|
378
|
-
view.x = x;
|
|
379
|
-
const y = numInteger(attrs.yWindow);
|
|
380
|
-
if (y !== undefined)
|
|
381
|
-
view.y = y;
|
|
382
|
-
const width = numInteger(attrs.windowWidth, 0);
|
|
383
|
-
if (width !== undefined)
|
|
384
|
-
view.width = width;
|
|
385
|
-
const height = numInteger(attrs.windowHeight, 0);
|
|
386
|
-
if (height !== undefined)
|
|
387
|
-
view.height = height;
|
|
388
|
-
const activeTab = numInteger(attrs.activeTab, 0);
|
|
389
|
-
if (activeTab !== undefined)
|
|
390
|
-
view.activeTab = activeTab;
|
|
391
|
-
const visibility = enumToken(attrs.visibility, isVisibility);
|
|
392
|
-
if (visibility !== undefined && visibility !== 'visible')
|
|
393
|
-
view.visibility = visibility;
|
|
394
|
-
if (boolStrict(attrs.minimized))
|
|
395
|
-
view.minimized = true;
|
|
96
|
+
const sheetXml = path === undefined ? undefined : partText(path);
|
|
97
|
+
const hyperlinks = sheetHyperlinkPass();
|
|
98
|
+
const validations = dataValidationPass();
|
|
99
|
+
const extendedValidations = extendedDataValidationPass();
|
|
100
|
+
const formattings = conditionalFormattingPass();
|
|
101
|
+
const references = worksheetReferencePass();
|
|
102
|
+
if (sheetXml !== undefined) {
|
|
103
|
+
parseXmlPasses(sheetXml, [
|
|
104
|
+
worksheetPass(sheet, sharedStrings, xfStyles, workbook.dateEpoch),
|
|
105
|
+
hyperlinks,
|
|
106
|
+
validations,
|
|
107
|
+
extendedValidations,
|
|
108
|
+
formattings,
|
|
109
|
+
references,
|
|
110
|
+
]);
|
|
111
|
+
}
|
|
112
|
+
if (path === undefined)
|
|
396
113
|
return;
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
onOpen(name, attrs) {
|
|
406
|
-
if (localName(name) !== 'definedName' || attrs.name === undefined)
|
|
407
|
-
return;
|
|
408
|
-
if (attrs.name === '_xlnm._FilterDatabase')
|
|
409
|
-
return;
|
|
410
|
-
capture = true;
|
|
411
|
-
refersTo = '';
|
|
412
|
-
const scopeIndex = numInteger(attrs.localSheetId, 0) ?? -1;
|
|
413
|
-
const scope = sheetOrder[scopeIndex];
|
|
414
|
-
pending = { name: attrs.name };
|
|
415
|
-
if (scope !== undefined)
|
|
416
|
-
pending.scope = scope;
|
|
417
|
-
if (attrs.comment !== undefined)
|
|
418
|
-
pending.comment = attrs.comment;
|
|
419
|
-
if (boolStrict(attrs.hidden))
|
|
420
|
-
pending.hidden = true;
|
|
421
|
-
},
|
|
422
|
-
onText(chunk) {
|
|
423
|
-
if (capture)
|
|
424
|
-
refersTo += chunk;
|
|
425
|
-
},
|
|
426
|
-
onClose(name) {
|
|
427
|
-
if (localName(name) !== 'definedName' || pending === undefined)
|
|
428
|
-
return;
|
|
429
|
-
names.push({ ...pending, refersTo: unmangleFunctions(refersTo) });
|
|
430
|
-
capture = false;
|
|
431
|
-
pending = undefined;
|
|
432
|
-
},
|
|
433
|
-
});
|
|
434
|
-
return names;
|
|
435
|
-
}
|
|
436
|
-
const CORE_PROPERTY_LOCAL_NAMES = new Set([
|
|
437
|
-
'title',
|
|
438
|
-
'creator',
|
|
439
|
-
'lastModifiedBy',
|
|
440
|
-
'created',
|
|
441
|
-
'modified',
|
|
442
|
-
]);
|
|
443
|
-
function applyCoreProperties(workbook, xml) {
|
|
444
|
-
for (const { local, text } of capturedText(xml, CORE_PROPERTY_LOCAL_NAMES)) {
|
|
445
|
-
if (local === 'title')
|
|
446
|
-
workbook.properties.title = text;
|
|
447
|
-
else if (local === 'creator')
|
|
448
|
-
workbook.properties.creator = text;
|
|
449
|
-
else if (local === 'lastModifiedBy')
|
|
450
|
-
workbook.properties.lastModifiedBy = text;
|
|
451
|
-
else {
|
|
452
|
-
const date = new Date(text);
|
|
453
|
-
if (!Number.isNaN(date.getTime())) {
|
|
454
|
-
if (local === 'created')
|
|
455
|
-
workbook.properties.created = date;
|
|
456
|
-
else
|
|
457
|
-
workbook.properties.modified = date;
|
|
458
|
-
}
|
|
114
|
+
const sheetRels = readPartRelationships(path, partText, pkg.partBytes);
|
|
115
|
+
if (sheetXml !== undefined) {
|
|
116
|
+
applyHyperlinks(sheet, hyperlinks.result(), (id) => sheetRels.byId(id)?.target);
|
|
117
|
+
applyDataValidations(sheet, [...validations.result(), ...extendedValidations.result()]);
|
|
118
|
+
for (const cf of formattings.result()) {
|
|
119
|
+
admitting(() => {
|
|
120
|
+
sheet.addConditionalFormatting(cf);
|
|
121
|
+
});
|
|
459
122
|
}
|
|
460
123
|
}
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
124
|
+
const threads = readSheetCommentThreads(context, sheetRels);
|
|
125
|
+
if (threads.length > 0)
|
|
126
|
+
sheet[INTERNAL].restoreCommentThreads(threads);
|
|
127
|
+
const comments = readSheetComments(sheetRels);
|
|
128
|
+
if (comments !== undefined)
|
|
129
|
+
applyNotes(sheet, comments);
|
|
130
|
+
readSheetImages(context, sheetRels, sheet);
|
|
131
|
+
readSheetBackground(context, sheetRels, sheet);
|
|
132
|
+
if (sheetXml !== undefined) {
|
|
133
|
+
readSheetPreservedReferences(context, sheetRels, references.result(), sheet);
|
|
134
|
+
}
|
|
135
|
+
readSheetTables(context, sheetRels, sheet);
|
|
136
|
+
readSheetPivotTables(context, sheetRels, sheet);
|
|
137
|
+
const printerSettings = readSheetPrinterSettings(sheetRels);
|
|
138
|
+
if (printerSettings !== undefined)
|
|
139
|
+
sheet.pageSetup.printerSettings = printerSettings;
|
|
465
140
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type XmlAttributes } from '../../xml/xml-scan.ts';
|
|
2
|
+
/** One `<row>`, as the reader that opened it needs to see it. */
|
|
3
|
+
export interface RowPosition {
|
|
4
|
+
/** The row's 1-based number, inferred from position when the element declares no `r`. */
|
|
5
|
+
readonly number: number;
|
|
6
|
+
/**
|
|
7
|
+
* Whether that number names a row the grid has. A row past the ceiling is dropped whole by both
|
|
8
|
+
* readers rather than clamped: an `r` names one row, so there is nothing to fold it onto, and
|
|
9
|
+
* clamping would silently move its formatting to the last row of the sheet.
|
|
10
|
+
*/
|
|
11
|
+
readonly inGrid: boolean;
|
|
12
|
+
}
|
|
13
|
+
/** Tracks where the reader is in `<sheetData>`, so a `<row>` with no `r` still has a number. */
|
|
14
|
+
export declare class RowPositionTracker {
|
|
15
|
+
#private;
|
|
16
|
+
/** Open the next `<row>`. A declared `r` wins and re-anchors the count, exactly as position does. */
|
|
17
|
+
open(attrs: XmlAttributes): RowPosition;
|
|
18
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { MAX_ROW } from '../../core/address.js';
|
|
2
|
+
import { numInteger } from '../../xml/xml-attrs.js';
|
|
3
|
+
import {} from '../../xml/xml-scan.js';
|
|
4
|
+
export class RowPositionTracker {
|
|
5
|
+
#last = 0;
|
|
6
|
+
open(attrs) {
|
|
7
|
+
const number = numInteger(attrs.r, 1) ?? this.#last + 1;
|
|
8
|
+
this.#last = number;
|
|
9
|
+
return { number, inGrid: number <= MAX_ROW };
|
|
10
|
+
}
|
|
11
|
+
}
|