@shbernal/ts-xlsx 1.3.1 → 2.0.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/dist/core/address.d.ts +49 -2
- package/dist/core/address.js +31 -3
- package/dist/core/autofilter.d.ts +2 -2
- package/dist/core/cell.d.ts +17 -16
- package/dist/core/cell.js +3 -7
- package/dist/core/color-resolution.d.ts +7 -7
- package/dist/core/column.d.ts +8 -9
- package/dist/core/column.js +2 -4
- package/dist/core/comment-thread.d.ts +32 -23
- package/dist/core/comment-thread.js +4 -4
- package/dist/core/conditional-formatting-overlay.d.ts +1 -1
- package/dist/core/conditional-formatting.d.ts +3 -3
- package/dist/core/data-validation-overlay.d.ts +1 -1
- package/dist/core/data-validation.d.ts +3 -3
- package/dist/core/date.d.ts +3 -3
- package/dist/core/formula.d.ts +6 -6
- package/dist/core/grid-edits.js +3 -3
- package/dist/core/image.d.ts +37 -2
- package/dist/core/image.js +6 -0
- package/dist/core/internal.d.ts +9 -1
- package/dist/core/limits.d.ts +4 -4
- package/dist/core/merge.d.ts +6 -12
- package/dist/core/merge.js +0 -3
- package/dist/core/page-setup.d.ts +4 -4
- package/dist/core/pivot-table.d.ts +2 -4
- package/dist/core/pivot-table.js +5 -5
- package/dist/core/preserved.d.ts +3 -3
- package/dist/core/protection.d.ts +4 -4
- package/dist/core/range.d.ts +16 -14
- package/dist/core/range.js +5 -5
- package/dist/core/row-input.d.ts +2 -8
- package/dist/core/row-input.js +2 -2
- package/dist/core/row.d.ts +7 -8
- package/dist/core/row.js +2 -4
- package/dist/core/style.d.ts +14 -14
- package/dist/core/table-style.d.ts +9 -9
- package/dist/core/table-style.js +1 -1
- package/dist/core/table.d.ts +30 -42
- package/dist/core/table.js +16 -10
- package/dist/core/theme.d.ts +13 -43
- package/dist/core/theme.js +2 -148
- package/dist/core/value.d.ts +7 -7
- package/dist/core/workbook-protection.d.ts +2 -2
- package/dist/core/workbook-styles.d.ts +26 -0
- package/dist/core/workbook-styles.js +48 -0
- package/dist/core/workbook-theme.d.ts +25 -0
- package/dist/core/workbook-theme.js +49 -0
- package/dist/core/workbook-vba.d.ts +17 -0
- package/dist/core/workbook-vba.js +79 -0
- package/dist/core/workbook.d.ts +131 -85
- package/dist/core/workbook.js +74 -133
- package/dist/core/worksheet-comments.d.ts +9 -0
- package/dist/core/worksheet-comments.js +52 -0
- package/dist/core/worksheet-model.d.ts +4 -4
- package/dist/core/worksheet-model.js +1 -0
- package/dist/core/worksheet-pictures.d.ts +29 -0
- package/dist/core/worksheet-pictures.js +42 -0
- package/dist/core/worksheet.d.ts +85 -77
- package/dist/core/worksheet.js +36 -95
- package/dist/customui/errors.d.ts +1 -1
- package/dist/customui/ribbon.d.ts +3 -3
- package/dist/entries/core.d.ts +4 -4
- package/dist/entries/core.js +1 -1
- package/dist/entries/vba.d.ts +1 -1
- package/dist/entries/vba.js +1 -1
- package/dist/entries/xlsx.d.ts +1 -0
- package/dist/entries/xlsx.js +1 -0
- package/dist/errors.d.ts +12 -12
- package/dist/io/csv/read.js +1 -2
- package/dist/io/csv/write.d.ts +8 -3
- package/dist/io/csv/write.js +17 -2
- package/dist/io/opc/errors.d.ts +6 -6
- package/dist/io/opc/inflate.d.ts +1 -1
- package/dist/io/opc/namespaces.d.ts +1 -1
- package/dist/io/opc/read-opc.d.ts +19 -3
- package/dist/io/opc/read-opc.js +14 -8
- package/dist/io/opc/read-options.d.ts +2 -2
- package/dist/io/opc/sniff-format.d.ts +2 -2
- package/dist/io/style/xf-style.d.ts +38 -6
- package/dist/io/style/xf-style.js +22 -0
- package/dist/io/xlsb/errors.d.ts +1 -1
- package/dist/io/xlsb/formula.d.ts +4 -4
- package/dist/io/xlsb/primitives.d.ts +8 -8
- package/dist/io/xlsb/ptg-functions.d.ts +1 -1
- package/dist/io/xlsb/read-styles.js +2 -20
- package/dist/io/xlsb/read.d.ts +2 -2
- package/dist/io/xlsx/cell-accumulator.d.ts +25 -6
- package/dist/io/xlsx/cell-accumulator.js +111 -30
- package/dist/io/xlsx/cell-value.d.ts +2 -2
- package/dist/io/xlsx/cell-value.js +3 -3
- package/dist/io/xlsx/color-xml.js +11 -17
- package/dist/io/xlsx/comments.d.ts +5 -5
- package/dist/io/xlsx/comments.js +13 -6
- package/dist/io/xlsx/conditional-formatting.d.ts +3 -3
- package/dist/io/xlsx/conditional-formatting.js +7 -16
- package/dist/io/xlsx/data-validation.d.ts +2 -2
- package/dist/io/xlsx/data-validation.js +1 -1
- package/dist/io/xlsx/errors.d.ts +3 -3
- package/dist/io/xlsx/hyperlinks.d.ts +4 -2
- package/dist/io/xlsx/hyperlinks.js +5 -5
- package/dist/io/xlsx/images.d.ts +1 -1
- package/dist/io/xlsx/images.js +8 -8
- package/dist/io/xlsx/namespaces.d.ts +2 -2
- package/dist/io/xlsx/package-plan.js +5 -2
- package/dist/io/xlsx/read-pivot.js +2 -5
- package/dist/io/xlsx/read-rows.d.ts +13 -13
- package/dist/io/xlsx/read-rows.js +19 -55
- package/dist/io/xlsx/read-shared-strings.js +7 -5
- package/dist/io/xlsx/read-styles.d.ts +3 -3
- package/dist/io/xlsx/read-styles.js +40 -65
- package/dist/io/xlsx/read-worksheet.js +61 -115
- package/dist/io/xlsx/read.d.ts +3 -5
- package/dist/io/xlsx/read.js +61 -69
- package/dist/io/xlsx/rich-runs.d.ts +1 -1
- package/dist/io/xlsx/rich-runs.js +1 -1
- package/dist/io/xlsx/rich-text.d.ts +1 -1
- package/dist/io/xlsx/shared-strings.d.ts +2 -2
- package/dist/io/xlsx/sheet-properties.js +2 -2
- package/dist/io/xlsx/styles.d.ts +8 -9
- package/dist/io/xlsx/styles.js +4 -3
- package/dist/io/xlsx/tables.d.ts +2 -2
- package/dist/io/xlsx/tables.js +8 -13
- package/dist/io/xlsx/theme-xml.d.ts +37 -0
- package/dist/io/xlsx/theme-xml.js +142 -0
- package/dist/io/xlsx/threaded-comments.d.ts +18 -27
- package/dist/io/xlsx/threaded-comments.js +9 -21
- package/dist/io/xlsx/worksheet-xml.d.ts +2 -2
- package/dist/io/xlsx/worksheet-xml.js +7 -12
- package/dist/io/xlsx/write-stream.d.ts +15 -15
- package/dist/io/xlsx/write-stream.js +3 -3
- package/dist/io/xlsx/write.d.ts +8 -7
- package/dist/io/xlsx/write.js +6 -3
- package/dist/io/xlsx/x14-ext.d.ts +1 -1
- package/dist/vba/bytes.d.ts +12 -0
- package/dist/vba/bytes.js +40 -0
- package/dist/vba/cfb-writer.d.ts +1 -1
- package/dist/vba/cfb.d.ts +1 -1
- package/dist/vba/cfb.js +15 -51
- package/dist/vba/codepage.d.ts +2 -2
- package/dist/vba/errors.d.ts +2 -2
- package/dist/vba/index.d.ts +2 -2
- package/dist/vba/index.js +2 -2
- package/dist/vba/ms-ovba.d.ts +1 -1
- package/dist/vba/ms-ovba.js +1 -3
- package/dist/vba/project-editor.d.ts +9 -9
- package/dist/vba/project-editor.js +2 -11
- package/dist/vba/project.d.ts +5 -5
- package/dist/vba/project.js +1 -10
- package/dist/vba/vba-encoding.d.ts +1 -1
- package/dist/xml/errors.d.ts +1 -1
- package/dist/xml/xml-read.d.ts +38 -9
- package/dist/xml/xml-read.js +23 -0
- package/dist/xml/xml.d.ts +31 -9
- package/dist/xml/xml.js +23 -3
- package/package.json +41 -35
package/dist/io/xlsx/read.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { decodeRange } from '../../core/address.js';
|
|
2
2
|
import { unmangleFunctions } from '../../core/formula.js';
|
|
3
3
|
import { INTERNAL } from '../../core/internal.js';
|
|
4
|
-
import { Workbook } from '../../core/workbook.js';
|
|
5
4
|
import { WORKBOOK_PROTECTION_CREDENTIAL_ATTRS, } from '../../core/workbook-protection.js';
|
|
6
|
-
import {
|
|
5
|
+
import { Workbook } from '../../core/workbook.js';
|
|
6
|
+
import { boolStrict, localName, numInteger, openElements, parseXml } from '../../xml/xml-read.js';
|
|
7
7
|
import { UnsupportedFormatError } from '../opc/errors.js';
|
|
8
|
-
import { extensionOf
|
|
9
|
-
import { capturePartClosure, contentTypeResolver, packageAccessors, parseRelationshipRecords, parseRelationships,
|
|
8
|
+
import { extensionOf } from '../opc/part-paths.js';
|
|
9
|
+
import { capturePartClosure, contentTypeResolver, packageAccessors, parseRelationshipRecords, parseRelationships, readPartRelationships, relationshipTargetByType, resolveRelativePart, resolveWorkbookPart, } from '../opc/read-opc.js';
|
|
10
10
|
import { DEFAULT_MAX_UNCOMPRESSED } from '../opc/read-options.js';
|
|
11
11
|
import { inflateSpreadsheetPackage } from '../opc/sniff-format.js';
|
|
12
12
|
import { readXlsbPackage, XLSB_WORKBOOK_PART } from '../xlsb/read.js';
|
|
@@ -20,6 +20,7 @@ import { parseSharedStrings } from './read-shared-strings.js';
|
|
|
20
20
|
import { parseIndexedColors, parseMruColors, parseStyleTable, parseTableStyles, } from './read-styles.js';
|
|
21
21
|
import { parseWorksheet } from './read-worksheet.js';
|
|
22
22
|
import { parseTable } from './tables.js';
|
|
23
|
+
import { parseThemeColorScheme, parseThemeFontScheme } from './theme-xml.js';
|
|
23
24
|
import { buildCommentThreads, parsePersons, parseThreadedComments } from './threaded-comments.js';
|
|
24
25
|
export { parseRelationships, resolveWorkbookPart } from '../opc/read-opc.js';
|
|
25
26
|
export { DEFAULT_MAX_UNCOMPRESSED } from '../opc/read-options.js';
|
|
@@ -70,9 +71,9 @@ export function readXlsx(data, options = {}) {
|
|
|
70
71
|
if (sheetXml !== undefined)
|
|
71
72
|
parseWorksheet(sheetXml, sheet, sharedStrings, xfStyles);
|
|
72
73
|
if (path !== undefined) {
|
|
74
|
+
const sheetRels = readPartRelationships(path, partText);
|
|
73
75
|
if (sheetXml !== undefined) {
|
|
74
|
-
|
|
75
|
-
applyHyperlinks(sheet, parseSheetHyperlinks(sheetXml), sheetRels);
|
|
76
|
+
applyHyperlinks(sheet, parseSheetHyperlinks(sheetXml), (id) => sheetRels.byId(id)?.target);
|
|
76
77
|
applyDataValidations(sheet, [
|
|
77
78
|
...parseDataValidations(sheetXml),
|
|
78
79
|
...parseExtendedDataValidations(sheetXml),
|
|
@@ -80,20 +81,20 @@ export function readXlsx(data, options = {}) {
|
|
|
80
81
|
for (const cf of parseConditionalFormattings(sheetXml))
|
|
81
82
|
sheet.addConditionalFormatting(cf);
|
|
82
83
|
}
|
|
83
|
-
const threads = readSheetCommentThreads(
|
|
84
|
+
const threads = readSheetCommentThreads(sheetRels, pkg, workbook);
|
|
84
85
|
if (threads.length > 0)
|
|
85
86
|
sheet[INTERNAL].restoreCommentThreads(threads);
|
|
86
|
-
const comments = readSheetComments(
|
|
87
|
+
const comments = readSheetComments(sheetRels, pkg);
|
|
87
88
|
if (comments !== undefined)
|
|
88
89
|
applyNotes(sheet, comments);
|
|
89
|
-
readSheetImages(
|
|
90
|
-
readSheetBackground(
|
|
90
|
+
readSheetImages(sheetRels, pkg, workbook, sheet, imageIdByMediaPath);
|
|
91
|
+
readSheetBackground(sheetRels, pkg, workbook, sheet, imageIdByMediaPath);
|
|
91
92
|
if (sheetXml !== undefined) {
|
|
92
|
-
readSheetPreservedReferences(
|
|
93
|
+
readSheetPreservedReferences(sheetRels, sheetXml, pkg, contentTypeOf, sheet);
|
|
93
94
|
}
|
|
94
|
-
readSheetTables(
|
|
95
|
-
readSheetPivotTables(
|
|
96
|
-
const printerSettings = readSheetPrinterSettings(
|
|
95
|
+
readSheetTables(sheetRels, pkg, sheet);
|
|
96
|
+
readSheetPivotTables(sheetRels, pkg, sheet);
|
|
97
|
+
const printerSettings = readSheetPrinterSettings(sheetRels, pkg);
|
|
97
98
|
if (printerSettings !== undefined)
|
|
98
99
|
sheet.pageSetup.printerSettings = printerSettings;
|
|
99
100
|
}
|
|
@@ -105,8 +106,8 @@ export function readXlsx(data, options = {}) {
|
|
|
105
106
|
}
|
|
106
107
|
return workbook;
|
|
107
108
|
}
|
|
108
|
-
function readSheetComments(
|
|
109
|
-
const commentsPath =
|
|
109
|
+
function readSheetComments(sheetRels, pkg) {
|
|
110
|
+
const commentsPath = sheetRels.targetPath('comments');
|
|
110
111
|
if (commentsPath === undefined)
|
|
111
112
|
return undefined;
|
|
112
113
|
const commentsXml = pkg.partText(commentsPath);
|
|
@@ -126,23 +127,25 @@ function readWorkbookTheme(workbookRelsXml, pkg, contentTypeOf, workbook) {
|
|
|
126
127
|
return;
|
|
127
128
|
const entryPath = resolveWorkbookPart(target);
|
|
128
129
|
const parts = capturePartClosure(entryPath, pkg.partText, pkg.partBytes, contentTypeOf);
|
|
129
|
-
if (parts
|
|
130
|
-
|
|
130
|
+
if (parts === undefined)
|
|
131
|
+
return;
|
|
132
|
+
const xml = pkg.partText(entryPath) ?? '';
|
|
133
|
+
workbook[INTERNAL].restoreThemePart({ entryPath, parts }, { colors: parseThemeColorScheme(xml), fonts: parseThemeFontScheme(xml) });
|
|
131
134
|
}
|
|
132
|
-
function readSheetCommentThreads(
|
|
133
|
-
const path =
|
|
135
|
+
function readSheetCommentThreads(sheetRels, pkg, workbook) {
|
|
136
|
+
const path = sheetRels.targetPath('threadedComment');
|
|
134
137
|
const xml = path === undefined ? undefined : pkg.partText(path);
|
|
135
138
|
if (xml === undefined)
|
|
136
139
|
return [];
|
|
137
140
|
return buildCommentThreads(parseThreadedComments(xml), (id) => workbook.getPerson(id));
|
|
138
141
|
}
|
|
139
|
-
function readSheetPrinterSettings(
|
|
140
|
-
const path =
|
|
142
|
+
function readSheetPrinterSettings(sheetRels, pkg) {
|
|
143
|
+
const path = sheetRels.targetPath('printerSettings');
|
|
141
144
|
return path === undefined ? undefined : pkg.partBytes(path);
|
|
142
145
|
}
|
|
143
|
-
function readSheetImages(
|
|
146
|
+
function readSheetImages(sheetRels, pkg, workbook, sheet, imageIdByMediaPath) {
|
|
144
147
|
const { partText, partBytes } = pkg;
|
|
145
|
-
const drawingPath =
|
|
148
|
+
const drawingPath = sheetRels.targetPath('drawing');
|
|
146
149
|
if (drawingPath === undefined)
|
|
147
150
|
return;
|
|
148
151
|
const drawingXml = partText(drawingPath);
|
|
@@ -150,12 +153,12 @@ function readSheetImages(sheetPath, pkg, workbook, sheet, imageIdByMediaPath) {
|
|
|
150
153
|
return;
|
|
151
154
|
if (drawingHasUnmodeledContent(drawingXml))
|
|
152
155
|
return;
|
|
153
|
-
const drawingRels =
|
|
156
|
+
const drawingRels = readPartRelationships(drawingPath, partText);
|
|
154
157
|
for (const anchor of parseDrawing(drawingXml)) {
|
|
155
|
-
const
|
|
156
|
-
if (
|
|
158
|
+
const embedded = drawingRels.byId(anchor.embed);
|
|
159
|
+
if (embedded === undefined)
|
|
157
160
|
continue;
|
|
158
|
-
const mediaPath =
|
|
161
|
+
const mediaPath = drawingRels.pathOf(embedded.target);
|
|
159
162
|
let id = imageIdByMediaPath.get(mediaPath);
|
|
160
163
|
if (id === undefined) {
|
|
161
164
|
const bytes = partBytes(mediaPath);
|
|
@@ -174,8 +177,8 @@ function readSheetImages(sheetPath, pkg, workbook, sheet, imageIdByMediaPath) {
|
|
|
174
177
|
}
|
|
175
178
|
}
|
|
176
179
|
}
|
|
177
|
-
function readSheetBackground(
|
|
178
|
-
const mediaPath =
|
|
180
|
+
function readSheetBackground(sheetRels, pkg, workbook, sheet, imageIdByMediaPath) {
|
|
181
|
+
const mediaPath = sheetRels.targetPath('image');
|
|
179
182
|
if (mediaPath === undefined)
|
|
180
183
|
return;
|
|
181
184
|
let id = imageIdByMediaPath.get(mediaPath);
|
|
@@ -188,15 +191,10 @@ function readSheetBackground(sheetPath, pkg, workbook, sheet, imageIdByMediaPath
|
|
|
188
191
|
}
|
|
189
192
|
sheet.addBackgroundImage(id);
|
|
190
193
|
}
|
|
191
|
-
function readSheetPreservedReferences(
|
|
194
|
+
function readSheetPreservedReferences(sheetRels, sheetXml, pkg, contentTypeOf, sheet) {
|
|
192
195
|
const { partText, partBytes } = pkg;
|
|
193
|
-
const relsXml = partText(relsPathFor(sheetPath));
|
|
194
|
-
if (relsXml === undefined)
|
|
195
|
-
return;
|
|
196
|
-
const records = parseRelationshipRecords(relsXml);
|
|
197
|
-
const recordById = new Map(records.map((record) => [record.id, record]));
|
|
198
196
|
const capture = (element, relType, target) => {
|
|
199
|
-
const entryPath =
|
|
197
|
+
const entryPath = sheetRels.pathOf(target);
|
|
200
198
|
const parts = capturePartClosure(entryPath, partText, partBytes, contentTypeOf);
|
|
201
199
|
if (parts !== undefined)
|
|
202
200
|
sheet[INTERNAL].addPreservedReference({ element, relType, entryPath, parts });
|
|
@@ -204,11 +202,11 @@ function readSheetPreservedReferences(sheetPath, sheetXml, pkg, contentTypeOf, s
|
|
|
204
202
|
const referenceElements = sheet.images.length === 0 ? ['drawing', 'legacyDrawingHF'] : ['legacyDrawingHF'];
|
|
205
203
|
for (const element of referenceElements) {
|
|
206
204
|
const relId = worksheetReferenceRelId(sheetXml, element);
|
|
207
|
-
const record = relId === undefined ? undefined :
|
|
205
|
+
const record = relId === undefined ? undefined : sheetRels.byId(relId);
|
|
208
206
|
if (record !== undefined && !record.external)
|
|
209
207
|
capture(element, record.type, record.target);
|
|
210
208
|
}
|
|
211
|
-
for (const record of records) {
|
|
209
|
+
for (const record of sheetRels.records) {
|
|
212
210
|
if (record.external)
|
|
213
211
|
continue;
|
|
214
212
|
if (isPreservedSheetRelType(record.type))
|
|
@@ -294,12 +292,9 @@ function worksheetReferenceRelId(sheetXml, element) {
|
|
|
294
292
|
}
|
|
295
293
|
return undefined;
|
|
296
294
|
}
|
|
297
|
-
function readSheetTables(
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
return;
|
|
301
|
-
for (const target of relationshipTargetsByType(relsXml, 'table')) {
|
|
302
|
-
const tableXml = pkg.partText(resolveRelativePart(sheetPath, target));
|
|
295
|
+
function readSheetTables(sheetRels, pkg, sheet) {
|
|
296
|
+
for (const tablePath of sheetRels.targetPaths('table')) {
|
|
297
|
+
const tableXml = pkg.partText(tablePath);
|
|
303
298
|
if (tableXml === undefined)
|
|
304
299
|
continue;
|
|
305
300
|
const options = parseTable(tableXml);
|
|
@@ -308,20 +303,14 @@ function readSheetTables(sheetPath, pkg, sheet) {
|
|
|
308
303
|
}
|
|
309
304
|
dropMergesInsideTables(sheet);
|
|
310
305
|
}
|
|
311
|
-
function readSheetPivotTables(
|
|
306
|
+
function readSheetPivotTables(sheetRels, pkg, sheet) {
|
|
312
307
|
const { partText } = pkg;
|
|
313
|
-
const
|
|
314
|
-
if (relsXml === undefined)
|
|
315
|
-
return;
|
|
316
|
-
for (const target of relationshipTargetsByType(relsXml, 'pivotTable')) {
|
|
317
|
-
const tablePath = resolveRelativePart(sheetPath, target);
|
|
308
|
+
for (const tablePath of sheetRels.targetPaths('pivotTable')) {
|
|
318
309
|
const tableXml = partText(tablePath);
|
|
319
310
|
if (tableXml === undefined)
|
|
320
311
|
continue;
|
|
321
|
-
const
|
|
322
|
-
const cacheXml =
|
|
323
|
-
? ''
|
|
324
|
-
: (partText(resolveRelativePart(tablePath, cacheTarget)) ?? '');
|
|
312
|
+
const cachePath = readPartRelationships(tablePath, partText).targetPath('pivotCacheDefinition');
|
|
313
|
+
const cacheXml = cachePath === undefined ? '' : (partText(cachePath) ?? '');
|
|
325
314
|
sheet[INTERNAL].addLoadedPivotTable(parsePivotTable(tableXml, cacheXml));
|
|
326
315
|
}
|
|
327
316
|
}
|
|
@@ -354,7 +343,7 @@ export function parseWorkbookSheets(xml) {
|
|
|
354
343
|
}
|
|
355
344
|
return sheets;
|
|
356
345
|
}
|
|
357
|
-
|
|
346
|
+
function parseWorkbookProtection(xml) {
|
|
358
347
|
let result;
|
|
359
348
|
parseXml(xml, {
|
|
360
349
|
onOpen(name, attrs) {
|
|
@@ -382,11 +371,21 @@ export function parseWorkbookProtection(xml) {
|
|
|
382
371
|
}
|
|
383
372
|
export function applyWorkbookView(view, xml) {
|
|
384
373
|
for (const { attrs } of openElements(xml, 'workbookView')) {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
374
|
+
const x = numInteger(attrs.xWindow);
|
|
375
|
+
if (x !== undefined)
|
|
376
|
+
view.x = x;
|
|
377
|
+
const y = numInteger(attrs.yWindow);
|
|
378
|
+
if (y !== undefined)
|
|
379
|
+
view.y = y;
|
|
380
|
+
const width = numInteger(attrs.windowWidth, 0);
|
|
381
|
+
if (width !== undefined)
|
|
382
|
+
view.width = width;
|
|
383
|
+
const height = numInteger(attrs.windowHeight, 0);
|
|
384
|
+
if (height !== undefined)
|
|
385
|
+
view.height = height;
|
|
386
|
+
const activeTab = numInteger(attrs.activeTab, 0);
|
|
387
|
+
if (activeTab !== undefined)
|
|
388
|
+
view.activeTab = activeTab;
|
|
390
389
|
if (attrs.visibility === 'hidden' || attrs.visibility === 'veryHidden') {
|
|
391
390
|
view.visibility = attrs.visibility;
|
|
392
391
|
}
|
|
@@ -395,13 +394,6 @@ export function applyWorkbookView(view, xml) {
|
|
|
395
394
|
return;
|
|
396
395
|
}
|
|
397
396
|
}
|
|
398
|
-
function applyViewNumber(raw, assign) {
|
|
399
|
-
if (raw === undefined)
|
|
400
|
-
return;
|
|
401
|
-
const value = Number(raw);
|
|
402
|
-
if (Number.isFinite(value))
|
|
403
|
-
assign(Math.trunc(value));
|
|
404
|
-
}
|
|
405
397
|
function parseWorkbookDefinedNames(xml, sheetOrder) {
|
|
406
398
|
const names = [];
|
|
407
399
|
let capture = false;
|
|
@@ -415,7 +407,7 @@ function parseWorkbookDefinedNames(xml, sheetOrder) {
|
|
|
415
407
|
return;
|
|
416
408
|
capture = true;
|
|
417
409
|
refersTo = '';
|
|
418
|
-
const scopeIndex = attrs.localSheetId
|
|
410
|
+
const scopeIndex = numInteger(attrs.localSheetId, 0) ?? -1;
|
|
419
411
|
const scope = sheetOrder[scopeIndex];
|
|
420
412
|
pending = { name: attrs.name };
|
|
421
413
|
if (scope !== undefined)
|
|
@@ -2,7 +2,7 @@ import type { RichTextRun } from '../../core/value.ts';
|
|
|
2
2
|
import type { XmlAttributes } from '../../xml/xml-read.ts';
|
|
3
3
|
export declare class RunAccumulator {
|
|
4
4
|
#private;
|
|
5
|
-
|
|
5
|
+
beginContainer(): void;
|
|
6
6
|
/** The runs gathered so far. */
|
|
7
7
|
get runs(): RichTextRun[];
|
|
8
8
|
beginRun(): void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { RichTextRun } from '../../core/value.ts';
|
|
2
2
|
/**
|
|
3
3
|
* Serialise a rich-text value's runs as the inner content of an `<is>` element. A zero-length run
|
|
4
|
-
* is dropped: an empty `<t/>` is schema-invalid
|
|
4
|
+
* is dropped: an empty `<t/>` is schema-invalid (Excel flags the file as corrupt) and an empty
|
|
5
5
|
* run contributes nothing to the rendered text, so omitting it is loss-free.
|
|
6
6
|
*/
|
|
7
7
|
export declare function richTextRunsXml(runs: readonly RichTextRun[]): string;
|
|
@@ -3,14 +3,14 @@ import type { RichTextValue } from '../../core/value.ts';
|
|
|
3
3
|
* Interns cell string values into the shared-strings pool. {@link intern} returns the index a
|
|
4
4
|
* `t="s"` cell writes as its `<v>`; identical entries collapse to one, so `count` (total references)
|
|
5
5
|
* and `uniqueCount` (distinct entries) diverge exactly as Excel records them. Each entry is stored as
|
|
6
|
-
* its rendered `<si>` inner XML, which is also its dedup key
|
|
6
|
+
* its rendered `<si>` inner XML, which is also its dedup key: a plain string (`<t>…`) and rich runs
|
|
7
7
|
* (`<r>…`) render to distinct markup, so the two kinds never collide in the pool.
|
|
8
8
|
*/
|
|
9
9
|
export declare class SharedStringTable {
|
|
10
10
|
#private;
|
|
11
11
|
/** Intern a plain or rich string and return its `<si>` index, reusing the entry when it repeats. */
|
|
12
12
|
intern(value: string | RichTextValue): number;
|
|
13
|
-
/** Whether no string has been interned
|
|
13
|
+
/** Whether no string has been interned; the writer omits the part entirely when so. */
|
|
14
14
|
get isEmpty(): boolean;
|
|
15
15
|
/** Serialise the pool as the `xl/sharedStrings.xml` part. */
|
|
16
16
|
toXml(): string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { encodeAddress } from '../../core/address.js';
|
|
2
2
|
import { SHEET_PROTECTION_FLAGS } from '../../core/protection.js';
|
|
3
|
-
import { attr, boolAttr, escapeAttr,
|
|
3
|
+
import { attr, boolAttr, escapeAttr, escapeSpreadsheetText, numberText } from '../../xml/xml.js';
|
|
4
4
|
import { colorAttrs } from './color-xml.js';
|
|
5
5
|
export function sheetViewsXml(view, active) {
|
|
6
6
|
const selected = active ? ' tabSelected="1"' : '';
|
|
@@ -99,7 +99,7 @@ export function headerFooterXml(hf) {
|
|
|
99
99
|
if (differentFirst)
|
|
100
100
|
attrs += ' differentFirst="1"';
|
|
101
101
|
const body = children
|
|
102
|
-
.map(({ tag, key }) => `<${tag}>${
|
|
102
|
+
.map(({ tag, key }) => `<${tag}>${escapeSpreadsheetText(hf[key])}</${tag}>`)
|
|
103
103
|
.join('');
|
|
104
104
|
return `<headerFooter${attrs}>${body}</headerFooter>`;
|
|
105
105
|
}
|
package/dist/io/xlsx/styles.d.ts
CHANGED
|
@@ -8,15 +8,15 @@ export interface CellStyle {
|
|
|
8
8
|
readonly border?: Border | undefined;
|
|
9
9
|
readonly alignment?: Alignment | undefined;
|
|
10
10
|
readonly protection?: Protection | undefined;
|
|
11
|
-
/** The quote-prefix flag
|
|
11
|
+
/** The quote-prefix flag: an attribute on the xf, not a shared sub-table entry. */
|
|
12
12
|
readonly quotePrefix?: boolean | undefined;
|
|
13
|
-
/** The `xfId` link into `cellStyleXfs
|
|
13
|
+
/** The `xfId` link into `cellStyleXfs`: the named cell style this format inherits from (0 = Normal). */
|
|
14
14
|
readonly xfId?: number | undefined;
|
|
15
15
|
}
|
|
16
16
|
/** What a {@link StyleRegistry} needs from its workbook before any style is interned. */
|
|
17
17
|
export interface StyleRegistryOptions {
|
|
18
18
|
/**
|
|
19
|
-
* The font every cell naming none of its own renders in
|
|
19
|
+
* The font every cell naming none of its own renders in, emitted as id 0. Take it from
|
|
20
20
|
* {@link Workbook.defaultFont}, which resolves the authored/declared/theme chain and guarantees a
|
|
21
21
|
* complete entry. Omitted, the registry falls back to the Office default.
|
|
22
22
|
*/
|
|
@@ -28,7 +28,7 @@ export interface StyleRegistryOptions {
|
|
|
28
28
|
*
|
|
29
29
|
* The reader flattens font 0 onto every xf that names it, so a cell that merely inherited the
|
|
30
30
|
* file's default arrives carrying it as a concrete face. That face is an artefact of reading, not
|
|
31
|
-
* an authored intent
|
|
31
|
+
* an authored intent (in the source file the cell said nothing about its font) so it must
|
|
32
32
|
* collapse back to id 0 and follow the new default rather than pin itself to the old one through a
|
|
33
33
|
* custom entry.
|
|
34
34
|
*/
|
|
@@ -59,7 +59,7 @@ export declare class StyleRegistry {
|
|
|
59
59
|
* rule's `dxfId`, and every `<tableStyleElement dxfId="…">` inside a preserved `<tableStyle>` (see
|
|
60
60
|
* {@link seedTableStyles}). Those constructs are carried as opaque XML precisely *because* the
|
|
61
61
|
* indices they name do not move. Renumbering, reordering, or de-duplicating the seeded entries
|
|
62
|
-
* would silently re-point every one of them at a different format
|
|
62
|
+
* would silently re-point every one of them at a different format: a change no schema check and no
|
|
63
63
|
* round-trip of our own can catch, because the file stays perfectly valid and merely renders wrong.
|
|
64
64
|
*/
|
|
65
65
|
seedDifferentialStyles(fragments: readonly string[]): void;
|
|
@@ -88,13 +88,13 @@ export declare class StyleRegistry {
|
|
|
88
88
|
* {@link seedTableStyles}, whose preserved definitions these append after.
|
|
89
89
|
*
|
|
90
90
|
* A definition here **replaces** a preserved one of the same name. Two `<tableStyle>` elements
|
|
91
|
-
* sharing a name is ambiguous
|
|
92
|
-
* happened to index first
|
|
91
|
+
* sharing a name is ambiguous, since a table's `tableStyleInfo/@name` would reach whichever a
|
|
92
|
+
* consumer happened to index first, so authoring a name the source already used is read as overriding it,
|
|
93
93
|
* which is what asking for it means.
|
|
94
94
|
*/
|
|
95
95
|
addTableStyle(style: TableStyle): void;
|
|
96
96
|
/**
|
|
97
|
-
* Intern an authored differential style, returning the `<dxfs>` index that references it
|
|
97
|
+
* Intern an authored differential style, returning the `<dxfs>` index that references it: a
|
|
98
98
|
* conditional-formatting rule's `dxfId`, or a table style element's. Identical styles collapse to
|
|
99
99
|
* one entry, whichever feature asked for them, so a highlight rule and a table style's header row
|
|
100
100
|
* painted the same way share a single `<dxf>`.
|
|
@@ -107,4 +107,3 @@ export declare class StyleRegistry {
|
|
|
107
107
|
toXml(): string;
|
|
108
108
|
}
|
|
109
109
|
export declare function fontXml(font: Font, nameTag?: 'name' | 'rFont'): string;
|
|
110
|
-
export declare function dxfXml(style: DifferentialStyle): string;
|
package/dist/io/xlsx/styles.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { isBorderStyle, isFillPatternType, isFontScheme, isFontVerticalAlignment, isHorizontalAlignment, isNamedUnderlineStyle, isVerticalAlignment, } from '../../core/style.js';
|
|
2
2
|
import { TABLE_STYLE_ELEMENT_TYPES } from '../../core/table-style.js';
|
|
3
3
|
import { AuthoringError } from '../../errors.js';
|
|
4
|
-
import { escapeAttr, XML_DECLARATION } from '../../xml/xml.js';
|
|
5
4
|
import { decodeEntities } from '../../xml/xml-read.js';
|
|
5
|
+
import { assertRepresentable, escapeAttr, XML_DECLARATION } from '../../xml/xml.js';
|
|
6
6
|
import { colorAttrs } from './color-xml.js';
|
|
7
7
|
import { MARKUP_COMPATIBILITY_NS, SPREADSHEETML_NS } from './namespaces.js';
|
|
8
8
|
const RESERVED_FILL_COUNT = 2;
|
|
@@ -188,7 +188,7 @@ export class StyleRegistry {
|
|
|
188
188
|
const cellStyleXfs = this.#cellStyleXfs.map((format) => xfXml(format, null)).join('');
|
|
189
189
|
const cellStyles = this.#cellStyleNames.map(cellStyleTag).join('');
|
|
190
190
|
const fontCount = RESERVED_FONT_COUNT + this.#fontXml.length;
|
|
191
|
-
const fonts = `<font>${this.#defaultFontBody}</font
|
|
191
|
+
const fonts = `<font>${this.#defaultFontBody}</font>${this.#fontXml.join('')}`;
|
|
192
192
|
const borderCount = RESERVED_BORDER_COUNT + this.#borderXml.length;
|
|
193
193
|
const borders = DEFAULT_BORDER + this.#borderXml.join('');
|
|
194
194
|
return (XML_DECLARATION +
|
|
@@ -362,7 +362,7 @@ export function fontXml(font, nameTag = 'name') {
|
|
|
362
362
|
parts.push(`<scheme val="${checkedToken(font.scheme, isFontScheme, 'font scheme')}"/>`);
|
|
363
363
|
return parts.join('');
|
|
364
364
|
}
|
|
365
|
-
|
|
365
|
+
function dxfXml(style) {
|
|
366
366
|
const parts = [];
|
|
367
367
|
if (style.font !== undefined) {
|
|
368
368
|
const font = fontXml(style.font);
|
|
@@ -425,6 +425,7 @@ function edgeXml(tag, edge) {
|
|
|
425
425
|
return `<${tag} style="${style}"><color ${colorAttrs(edge.color)}/></${tag}>`;
|
|
426
426
|
}
|
|
427
427
|
function escapeFormatCode(code) {
|
|
428
|
+
assertRepresentable(code);
|
|
428
429
|
return code
|
|
429
430
|
.replace(/&/g, '&')
|
|
430
431
|
.replace(/</g, '<')
|
package/dist/io/xlsx/tables.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { type Table, type TableOptions } from '../../core/table.ts';
|
|
|
2
2
|
export declare function tableXml(table: Table, id: number): string;
|
|
3
3
|
/**
|
|
4
4
|
* Parse a `<table>` part into the options that reconstruct it, or `undefined` when the XML is not a
|
|
5
|
-
* usable table (no name, no ref, or no columns
|
|
6
|
-
* rather than fabricate a degenerate table). Duplicate column names are not resolved here
|
|
5
|
+
* usable table (no name, no ref, or no columns: Excel treats such a part as corrupt, so we drop it
|
|
6
|
+
* rather than fabricate a degenerate table). Duplicate column names are not resolved here, since the
|
|
7
7
|
* {@link Table} constructor disambiguates them, so authoring and loading share one implementation.
|
|
8
8
|
*/
|
|
9
9
|
export declare function parseTable(xml: string): TableOptions | undefined;
|
package/dist/io/xlsx/tables.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { decodeRange, encodeAddress } from '../../core/address.js';
|
|
2
2
|
import { isTotalsRowFunction, } from '../../core/table.js';
|
|
3
|
+
import { boolPresent, localName, numInteger, parseXml } from '../../xml/xml-read.js';
|
|
3
4
|
import { boolAttr, escapeAttr, escapeText, XML_DECLARATION } from '../../xml/xml.js';
|
|
4
|
-
import { localName, parseXml } from '../../xml/xml-read.js';
|
|
5
5
|
import { NS } from './relationships.js';
|
|
6
6
|
export function tableXml(table, id) {
|
|
7
7
|
const name = escapeAttr(table.name);
|
|
@@ -55,9 +55,6 @@ function tableColumnXml(column, id) {
|
|
|
55
55
|
}
|
|
56
56
|
return `<tableColumn ${attrs}/>`;
|
|
57
57
|
}
|
|
58
|
-
function parseOoxmlBool(value) {
|
|
59
|
-
return value !== '0' && value !== 'false';
|
|
60
|
-
}
|
|
61
58
|
export function parseTable(xml) {
|
|
62
59
|
let name;
|
|
63
60
|
let displayName;
|
|
@@ -77,12 +74,10 @@ export function parseTable(xml) {
|
|
|
77
74
|
name = attrs.name ?? attrs.displayName;
|
|
78
75
|
displayName = attrs.displayName ?? attrs.name;
|
|
79
76
|
ref = attrs.ref;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (attrs.totalsRowCount !== undefined)
|
|
83
|
-
totalsRowCount = Number(attrs.totalsRowCount);
|
|
77
|
+
headerRowCount = numInteger(attrs.headerRowCount, 0) ?? headerRowCount;
|
|
78
|
+
totalsRowCount = numInteger(attrs.totalsRowCount, 0) ?? totalsRowCount;
|
|
84
79
|
if (attrs.totalsRowShown !== undefined)
|
|
85
|
-
totalsRowShown =
|
|
80
|
+
totalsRowShown = boolPresent(attrs.totalsRowShown);
|
|
86
81
|
break;
|
|
87
82
|
case 'autoFilter':
|
|
88
83
|
hasAutoFilter = true;
|
|
@@ -92,13 +87,13 @@ export function parseTable(xml) {
|
|
|
92
87
|
if (attrs.name !== undefined)
|
|
93
88
|
captured.name = attrs.name;
|
|
94
89
|
if (attrs.showFirstColumn !== undefined)
|
|
95
|
-
captured.showFirstColumn =
|
|
90
|
+
captured.showFirstColumn = boolPresent(attrs.showFirstColumn);
|
|
96
91
|
if (attrs.showLastColumn !== undefined)
|
|
97
|
-
captured.showLastColumn =
|
|
92
|
+
captured.showLastColumn = boolPresent(attrs.showLastColumn);
|
|
98
93
|
if (attrs.showRowStripes !== undefined)
|
|
99
|
-
captured.showRowStripes =
|
|
94
|
+
captured.showRowStripes = boolPresent(attrs.showRowStripes);
|
|
100
95
|
if (attrs.showColumnStripes !== undefined) {
|
|
101
|
-
captured.showColumnStripes =
|
|
96
|
+
captured.showColumnStripes = boolPresent(attrs.showColumnStripes);
|
|
102
97
|
}
|
|
103
98
|
style = captured;
|
|
104
99
|
break;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type ThemeColorScheme, type ThemeFontScheme, type ThemeOverrides } from '../../core/theme.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Extract the colour scheme from a theme part. Returns only the slots the part actually declares in a
|
|
4
|
+
* colour model this reader understands; an unrecognised one is dropped rather than guessed at, so a
|
|
5
|
+
* caller can tell "the theme says nothing here" from "the theme says black".
|
|
6
|
+
*
|
|
7
|
+
* Reads the `<a:clrScheme>` block alone. A theme carries a font scheme and a format scheme too, but
|
|
8
|
+
* neither participates in resolving a colour, and scanning the whole part would let a `<a:srgbClr>`
|
|
9
|
+
* buried in a gradient stop masquerade as a scheme slot.
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseThemeColorScheme(themeXml: string): ThemeColorScheme;
|
|
12
|
+
/** Extract the major/minor latin typefaces from a theme part's `<a:fontScheme>`. */
|
|
13
|
+
export declare function parseThemeFontScheme(themeXml: string): ThemeFontScheme;
|
|
14
|
+
/**
|
|
15
|
+
* Apply authored colour/font overrides to a theme part, returning the new part text.
|
|
16
|
+
*
|
|
17
|
+
* Surgical by design: the base part rides through untouched except for the `<a:clrScheme>` and
|
|
18
|
+
* `<a:fontScheme>` blocks, and within those, only what the caller actually named. The format scheme,
|
|
19
|
+
* the gradients, line styles and effect styles that make a theme look like a theme, is left exactly
|
|
20
|
+
* as it was, because nobody hand-authors `fillStyleLst` gradient stops from a spreadsheet API and
|
|
21
|
+
* regenerating it would replace a designer's work with the Office default.
|
|
22
|
+
*
|
|
23
|
+
* A slot the caller did not override keeps its **verbatim source element**, not a re-serialisation of
|
|
24
|
+
* its value. That matters for `dk1`/`lt1`, which Excel writes as `<a:sysClr val="windowText"
|
|
25
|
+
* lastClr="000000"/>`: rewriting those as `<a:srgbClr>` would pin them to one machine's resolved
|
|
26
|
+
* window colours and break dark-mode following.
|
|
27
|
+
*/
|
|
28
|
+
export declare function applyThemeOverrides(baseXml: string, overrides: ThemeOverrides): string;
|
|
29
|
+
/**
|
|
30
|
+
* The theme part a workbook with no theme of its own ships: the standard Office theme.
|
|
31
|
+
*
|
|
32
|
+
* A spreadsheet must carry one even when nobody configured it: the stylesheet's own default font
|
|
33
|
+
* references `theme="1"`, which a consumer can only resolve against this part, so the two travel
|
|
34
|
+
* together. It is also the base {@link applyThemeOverrides} authors on top of when a workbook was
|
|
35
|
+
* built from scratch rather than read from a file.
|
|
36
|
+
*/
|
|
37
|
+
export declare const DEFAULT_THEME_XML: string;
|