@shbernal/ts-xlsx 1.3.1 → 2.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 +20 -10
- package/dist/bytes.d.ts +24 -0
- package/dist/bytes.js +34 -0
- package/dist/core/address.d.ts +72 -3
- package/dist/core/address.js +50 -10
- package/dist/core/autofilter.d.ts +13 -2
- package/dist/core/autofilter.js +35 -10
- package/dist/core/cell.d.ts +17 -16
- package/dist/core/cell.js +3 -7
- package/dist/core/color-resolution.d.ts +8 -8
- package/dist/core/color-resolution.js +7 -8
- 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 +6 -1
- package/dist/core/conditional-formatting-overlay.js +11 -0
- package/dist/core/conditional-formatting.d.ts +48 -8
- package/dist/core/conditional-formatting.js +88 -0
- package/dist/core/data-validation-overlay.d.ts +12 -1
- package/dist/core/data-validation-overlay.js +21 -2
- package/dist/core/data-validation.d.ts +12 -5
- package/dist/core/data-validation.js +34 -0
- package/dist/core/date.d.ts +3 -3
- package/dist/core/formula.d.ts +6 -6
- package/dist/core/grid-edits.d.ts +16 -0
- package/dist/core/grid-edits.js +29 -11
- package/dist/core/grid-shift.d.ts +19 -0
- package/dist/core/grid-shift.js +8 -0
- package/dist/core/image.d.ts +39 -2
- package/dist/core/image.js +10 -0
- package/dist/core/internal.d.ts +9 -1
- package/dist/core/limits.d.ts +4 -4
- package/dist/core/merge.d.ts +17 -12
- package/dist/core/merge.js +36 -5
- package/dist/core/page-setup.d.ts +20 -6
- package/dist/core/page-setup.js +8 -1
- package/dist/core/pivot-table.d.ts +4 -4
- package/dist/core/pivot-table.js +29 -20
- package/dist/core/preserved.d.ts +3 -3
- package/dist/core/protection.d.ts +7 -4
- package/dist/core/protection.js +20 -14
- package/dist/core/range.d.ts +16 -14
- package/dist/core/range.js +5 -5
- package/dist/core/row-input.d.ts +9 -8
- package/dist/core/row-input.js +12 -10
- package/dist/core/row.d.ts +7 -8
- package/dist/core/row.js +2 -4
- package/dist/core/style.d.ts +41 -14
- package/dist/core/style.js +82 -67
- package/dist/core/table-style.d.ts +9 -9
- package/dist/core/table-style.js +1 -1
- package/dist/core/table.d.ts +53 -51
- package/dist/core/table.js +83 -41
- package/dist/core/theme.d.ts +16 -44
- package/dist/core/theme.js +6 -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 +133 -87
- package/dist/core/workbook.js +74 -133
- package/dist/core/worksheet-comments.d.ts +17 -0
- package/dist/core/worksheet-comments.js +70 -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 +100 -79
- package/dist/core/worksheet.js +63 -142
- package/dist/customui/errors.d.ts +1 -1
- package/dist/customui/ribbon.d.ts +3 -3
- package/dist/customui/ribbon.js +24 -23
- package/dist/entries/core.d.ts +7 -7
- package/dist/entries/core.js +1 -1
- package/dist/entries/csv.d.ts +1 -1
- package/dist/entries/node-unavailable.d.ts +15 -0
- package/dist/entries/node-unavailable.js +20 -0
- package/dist/entries/node.d.ts +1 -0
- package/dist/entries/node.js +1 -0
- package/dist/entries/vba.d.ts +1 -1
- package/dist/entries/vba.js +1 -1
- package/dist/entries/xlsx.d.ts +1 -1
- package/dist/entries/xlsx.js +1 -1
- package/dist/errors.d.ts +12 -12
- package/dist/io/csv/read.js +2 -3
- package/dist/io/csv/write.d.ts +19 -4
- package/dist/io/csv/write.js +34 -4
- package/dist/io/opc/errors.d.ts +6 -6
- package/dist/io/opc/inflate.d.ts +1 -1
- package/dist/io/opc/inflate.js +2 -12
- 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/rels.d.ts +11 -0
- package/dist/io/opc/rels.js +3 -2
- package/dist/io/opc/sniff-format.d.ts +2 -2
- package/dist/io/style/xf-style.d.ts +44 -7
- package/dist/io/style/xf-style.js +27 -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 +26 -9
- package/dist/io/xlsx/cell-accumulator.js +89 -46
- package/dist/io/xlsx/cell-value.d.ts +3 -3
- package/dist/io/xlsx/cell-value.js +9 -6
- package/dist/io/xlsx/color-xml.d.ts +1 -1
- package/dist/io/xlsx/color-xml.js +18 -23
- package/dist/io/xlsx/comments.d.ts +5 -5
- package/dist/io/xlsx/comments.js +17 -8
- package/dist/io/xlsx/conditional-formatting.d.ts +4 -4
- package/dist/io/xlsx/conditional-formatting.js +64 -58
- package/dist/io/xlsx/data-validation.d.ts +3 -3
- package/dist/io/xlsx/data-validation.js +35 -33
- package/dist/io/xlsx/errors.d.ts +3 -3
- package/dist/io/xlsx/hyperlinks.d.ts +4 -2
- package/dist/io/xlsx/hyperlinks.js +10 -18
- package/dist/io/xlsx/images.d.ts +1 -1
- package/dist/io/xlsx/images.js +25 -28
- 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 +4 -13
- 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 -44
- package/dist/io/xlsx/read-styles.d.ts +3 -3
- package/dist/io/xlsx/read-styles.js +42 -66
- package/dist/io/xlsx/read-worksheet.js +73 -129
- package/dist/io/xlsx/read.d.ts +4 -6
- package/dist/io/xlsx/read.js +104 -142
- package/dist/io/xlsx/rich-runs.d.ts +41 -7
- package/dist/io/xlsx/rich-runs.js +94 -30
- 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.d.ts +1 -1
- package/dist/io/xlsx/sheet-properties.js +14 -10
- package/dist/io/xlsx/styles.d.ts +9 -22
- package/dist/io/xlsx/styles.js +65 -89
- package/dist/io/xlsx/tables.d.ts +2 -2
- package/dist/io/xlsx/tables.js +20 -25
- package/dist/io/xlsx/theme-xml.d.ts +37 -0
- package/dist/io/xlsx/theme-xml.js +145 -0
- package/dist/io/xlsx/threaded-comments.d.ts +18 -27
- package/dist/io/xlsx/threaded-comments.js +26 -38
- package/dist/io/xlsx/workbook-xml.js +14 -8
- package/dist/io/xlsx/worksheet-xml.d.ts +2 -2
- package/dist/io/xlsx/worksheet-xml.js +40 -48
- package/dist/io/xlsx/write-stream.d.ts +23 -16
- package/dist/io/xlsx/write-stream.js +13 -14
- 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/sha512.d.ts +2 -0
- package/dist/sha512.js +146 -0
- package/dist/vba/bytes.d.ts +11 -0
- package/dist/vba/bytes.js +29 -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/dir-records.d.ts +53 -0
- package/dist/vba/dir-records.js +28 -0
- 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 +6 -44
- package/dist/vba/project.d.ts +5 -5
- package/dist/vba/project.js +3 -28
- package/dist/vba/vba-encoding.d.ts +1 -1
- package/dist/xml/errors.d.ts +1 -1
- package/dist/xml/xml-read.d.ts +98 -9
- package/dist/xml/xml-read.js +70 -0
- package/dist/xml/xml.d.ts +74 -10
- package/dist/xml/xml.js +39 -7
- package/package.json +59 -36
package/dist/core/worksheet.js
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
import { AuthoringError } from '../errors.js';
|
|
2
|
-
import {
|
|
2
|
+
import { decodeCellRef, decodeRange, encodeAddress, rectsOverlap, tryDecodeCellRef, } from './address.js';
|
|
3
3
|
import { canonicalizeAutoFilter } from './autofilter.js';
|
|
4
4
|
import { applyCellStyle, Cell, copyCellContent } from './cell.js';
|
|
5
5
|
import { Column } from './column.js';
|
|
6
|
-
import { commentThreadGuid, commentThreadOffset } from './comment-thread.js';
|
|
7
6
|
import { ConditionalFormattingOverlay } from './conditional-formatting-overlay.js';
|
|
8
|
-
import { replaceContents } from './containers.js';
|
|
9
7
|
import { DataValidationOverlay } from './data-validation-overlay.js';
|
|
10
8
|
import { GridEdits } from './grid-edits.js';
|
|
11
|
-
import { PX_TO_EMU, resolveAnchorPoint, } from './image.js';
|
|
12
9
|
import { INTERNAL } from './internal.js';
|
|
13
|
-
import { clearCoveredValues, masterOf
|
|
10
|
+
import { clearCoveredValues, masterOf } from './merge.js';
|
|
14
11
|
import { PivotTable } from './pivot-table.js';
|
|
15
12
|
import { deriveCredential, } from './protection.js';
|
|
16
13
|
import { Range, rangeFrom } from './range.js';
|
|
14
|
+
import { buildRowCells, positionalPlacements, rowPlacements } from './row-input.js';
|
|
17
15
|
import { Row } from './row.js';
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
16
|
+
import { Table } from './table.js';
|
|
17
|
+
import { WorksheetComments } from './worksheet-comments.js';
|
|
20
18
|
import { WORKSHEET_MODEL_FACETS } from './worksheet-model.js';
|
|
19
|
+
import { WorksheetPictures } from './worksheet-pictures.js';
|
|
20
|
+
const VISIBILITIES = { visible: true, hidden: true, veryHidden: true };
|
|
21
|
+
export function isVisibility(value) {
|
|
22
|
+
return Object.hasOwn(VISIBILITIES, value);
|
|
23
|
+
}
|
|
21
24
|
export class Worksheet {
|
|
22
25
|
name;
|
|
23
26
|
id;
|
|
@@ -38,10 +41,12 @@ export class Worksheet {
|
|
|
38
41
|
#tables = [];
|
|
39
42
|
#pivotTables = [];
|
|
40
43
|
#loadedPivotTables = [];
|
|
41
|
-
#
|
|
44
|
+
#comments = new WorksheetComments(() => this.name);
|
|
42
45
|
#merges = [];
|
|
43
|
-
#images =
|
|
44
|
-
|
|
46
|
+
#images = new WorksheetPictures({
|
|
47
|
+
columnWidth: (col) => this.#columns.get(col + 1)?.width ?? this.properties.defaultColWidth,
|
|
48
|
+
rowHeight: (row) => this.#rowProperties.get(row + 1)?.height ?? this.properties.defaultRowHeight,
|
|
49
|
+
});
|
|
45
50
|
#preservedReferences = [];
|
|
46
51
|
#mergeRects = [];
|
|
47
52
|
#dataValidations = new DataValidationOverlay();
|
|
@@ -60,14 +65,20 @@ export class Worksheet {
|
|
|
60
65
|
merges: this.#merges,
|
|
61
66
|
mergeRects: this.#mergeRects,
|
|
62
67
|
tables: this.#tables,
|
|
63
|
-
images: this.#images,
|
|
68
|
+
images: this.#images.anchors,
|
|
69
|
+
dataValidations: this.#dataValidations,
|
|
70
|
+
conditionalFormattings: this.#conditionalFormattings,
|
|
71
|
+
comments: this.#comments,
|
|
72
|
+
autoFilter: {
|
|
73
|
+
get: () => this.#autoFilter,
|
|
74
|
+
set: (next) => {
|
|
75
|
+
this.#autoFilter = next;
|
|
76
|
+
},
|
|
77
|
+
},
|
|
64
78
|
});
|
|
65
79
|
}
|
|
66
80
|
getCell(reference) {
|
|
67
|
-
const { col, row } =
|
|
68
|
-
if (col === undefined || row === undefined) {
|
|
69
|
-
throw new SyntaxError(`"${reference}" is not a single-cell reference — it omits a column or row`);
|
|
70
|
-
}
|
|
81
|
+
const { col, row } = decodeCellRef(reference);
|
|
71
82
|
const master = masterOf(this.#mergeRects, row, col);
|
|
72
83
|
return this.#cellAt(master.row, master.col);
|
|
73
84
|
}
|
|
@@ -153,46 +164,17 @@ export class Worksheet {
|
|
|
153
164
|
}
|
|
154
165
|
}
|
|
155
166
|
addTable(options) {
|
|
156
|
-
const table = new Table(options,
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
167
|
+
const table = new Table(options, {
|
|
168
|
+
holdsValue: (row, col) => this.hasCell(row, col) && this.#cellAt(row, col).value != null,
|
|
169
|
+
writeCell: (row, col, value, style) => {
|
|
170
|
+
const cell = this.#cellAt(row, col);
|
|
171
|
+
cell.value = value;
|
|
172
|
+
if (style !== undefined)
|
|
173
|
+
applyCellStyle(cell, style);
|
|
174
|
+
},
|
|
175
|
+
insertRow: (row) => this.spliceRows(row, 0, []),
|
|
176
|
+
});
|
|
162
177
|
this.#tables.push(table);
|
|
163
|
-
if (table.headerRow) {
|
|
164
|
-
const { top, left } = table.region;
|
|
165
|
-
table.columns.forEach((column, index) => {
|
|
166
|
-
const col = left + index;
|
|
167
|
-
if (this.hasCell(top, col) && this.#cellAt(top, col).value != null)
|
|
168
|
-
return;
|
|
169
|
-
this.#cellAt(top, col).value = column.name;
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
if (table.totalsRow) {
|
|
173
|
-
const { left, bottom } = table.region;
|
|
174
|
-
table.columns.forEach((column, index) => {
|
|
175
|
-
const col = left + index;
|
|
176
|
-
if (this.hasCell(bottom, col) && this.#cellAt(bottom, col).value != null)
|
|
177
|
-
return;
|
|
178
|
-
if (column.totalsRowLabel !== undefined) {
|
|
179
|
-
this.#cellAt(bottom, col).value = column.totalsRowLabel;
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
if (column.totalsRowFunction !== undefined) {
|
|
183
|
-
const code = TOTALS_ROW_SUBTOTAL_CODE[column.totalsRowFunction];
|
|
184
|
-
if (code !== undefined) {
|
|
185
|
-
this.#cellAt(bottom, col).value = {
|
|
186
|
-
formula: `SUBTOTAL(${code},${table.name}[${column.name}])`,
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
else if (column.totalsRowFunction === 'custom' &&
|
|
190
|
-
column.totalsRowFormula !== undefined) {
|
|
191
|
-
this.#cellAt(bottom, col).value = { formula: column.totalsRowFormula };
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
178
|
return table;
|
|
197
179
|
}
|
|
198
180
|
get tables() {
|
|
@@ -213,82 +195,34 @@ export class Worksheet {
|
|
|
213
195
|
return this.#loadedPivotTables;
|
|
214
196
|
}
|
|
215
197
|
addCommentThread(thread) {
|
|
216
|
-
|
|
217
|
-
const comments = thread.comments.map((comment) => {
|
|
218
|
-
const id = commentThreadGuid(comment.id, 'a comment id');
|
|
219
|
-
if (taken.has(id)) {
|
|
220
|
-
throw new SyntaxError(`a comment id must be unique within a sheet, but "${id}" is already used on "${this.name}" — ` +
|
|
221
|
-
'a reply and the legacy fallback comment both find their thread by it');
|
|
222
|
-
}
|
|
223
|
-
taken.add(id);
|
|
224
|
-
return {
|
|
225
|
-
...comment,
|
|
226
|
-
id,
|
|
227
|
-
...(comment.personId !== undefined
|
|
228
|
-
? { personId: commentThreadGuid(comment.personId, "a comment's author id") }
|
|
229
|
-
: {}),
|
|
230
|
-
mentions: comment.mentions.map((mention) => ({
|
|
231
|
-
...mention,
|
|
232
|
-
personId: commentThreadGuid(mention.personId, "a mention's person id"),
|
|
233
|
-
startIndex: commentThreadOffset(mention.startIndex, "a mention's startIndex"),
|
|
234
|
-
length: commentThreadOffset(mention.length, "a mention's length"),
|
|
235
|
-
...(mention.mentionId !== undefined
|
|
236
|
-
? { mentionId: commentThreadGuid(mention.mentionId, 'a mention id') }
|
|
237
|
-
: {}),
|
|
238
|
-
})),
|
|
239
|
-
};
|
|
240
|
-
});
|
|
241
|
-
this.#commentThreads.push({ ...thread, ref: this.#anchorRef(thread.ref), comments });
|
|
198
|
+
this.#comments.add(thread);
|
|
242
199
|
}
|
|
243
200
|
get commentThreads() {
|
|
244
|
-
return this.#
|
|
245
|
-
}
|
|
246
|
-
#anchorRef(reference) {
|
|
247
|
-
const { col, row } = decodeAddress(reference);
|
|
248
|
-
if (col === undefined || row === undefined) {
|
|
249
|
-
throw new SyntaxError(`"${reference}" is not a single-cell reference — it omits a column or row`);
|
|
250
|
-
}
|
|
251
|
-
return encodeAddress(col, row);
|
|
201
|
+
return this.#comments.threads;
|
|
252
202
|
}
|
|
253
203
|
commentThreadAt(reference) {
|
|
254
|
-
|
|
255
|
-
return this.#commentThreads.find((thread) => thread.ref === anchor);
|
|
204
|
+
return this.#comments.at(reference);
|
|
256
205
|
}
|
|
257
206
|
addImage(imageId, anchor) {
|
|
258
|
-
|
|
259
|
-
const rowHeight = (row) => this.#rowProperties.get(row + 1)?.height ?? this.properties.defaultRowHeight;
|
|
260
|
-
if ('ext' in anchor) {
|
|
261
|
-
const ext = {
|
|
262
|
-
cx: Math.round(anchor.ext.width * PX_TO_EMU),
|
|
263
|
-
cy: Math.round(anchor.ext.height * PX_TO_EMU),
|
|
264
|
-
};
|
|
265
|
-
const from = resolveAnchorPoint(anchor.tl, columnWidth, rowHeight);
|
|
266
|
-
this.#images.push({ imageId, anchor: { from, ext } });
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
const from = resolveAnchorPoint(anchor.tl, columnWidth, rowHeight);
|
|
270
|
-
const to = resolveAnchorPoint(anchor.br, columnWidth, rowHeight);
|
|
271
|
-
const twoCell = anchor.editAs !== undefined ? { from, to, editAs: anchor.editAs } : { from, to };
|
|
272
|
-
this.#images.push({ imageId, anchor: twoCell });
|
|
207
|
+
this.#images.add(imageId, anchor);
|
|
273
208
|
}
|
|
274
209
|
addImageAnchor(imageId, anchor) {
|
|
275
|
-
this.#images.
|
|
210
|
+
this.#images.addAnchor(imageId, anchor);
|
|
276
211
|
}
|
|
277
212
|
removeImage(imageId) {
|
|
278
|
-
|
|
279
|
-
replaceContents(this.#images, kept);
|
|
213
|
+
this.#images.remove(imageId);
|
|
280
214
|
}
|
|
281
215
|
get images() {
|
|
282
|
-
return this.#images;
|
|
216
|
+
return this.#images.anchors;
|
|
283
217
|
}
|
|
284
218
|
addBackgroundImage(imageId) {
|
|
285
|
-
this.#
|
|
219
|
+
this.#images.setBackground(imageId);
|
|
286
220
|
}
|
|
287
221
|
removeBackgroundImage() {
|
|
288
|
-
this.#
|
|
222
|
+
this.#images.setBackground(undefined);
|
|
289
223
|
}
|
|
290
224
|
get backgroundImageId() {
|
|
291
|
-
return this.#backgroundImageId;
|
|
225
|
+
return this.#images.backgroundImageId;
|
|
292
226
|
}
|
|
293
227
|
get preservedReferences() {
|
|
294
228
|
return this.#preservedReferences;
|
|
@@ -341,18 +275,11 @@ export class Worksheet {
|
|
|
341
275
|
return this.#conditionalFormattings.entries;
|
|
342
276
|
}
|
|
343
277
|
dataValidationAt(reference) {
|
|
344
|
-
const
|
|
345
|
-
|
|
346
|
-
return undefined;
|
|
347
|
-
return this.#dataValidations.at(col, row);
|
|
278
|
+
const cell = tryDecodeCellRef(reference);
|
|
279
|
+
return cell === undefined ? undefined : this.#dataValidations.at(cell.col, cell.row);
|
|
348
280
|
}
|
|
349
281
|
spliceRows(start, count, ...inserts) {
|
|
350
|
-
|
|
351
|
-
throw new RangeError(`splice start ${start} is out of bounds — rows start at 1`);
|
|
352
|
-
}
|
|
353
|
-
if (!Number.isInteger(count) || count < 0) {
|
|
354
|
-
throw new RangeError(`splice count ${count} is invalid — it must be a non-negative integer`);
|
|
355
|
-
}
|
|
282
|
+
assertStartAndCount('splice', 'row', start, count);
|
|
356
283
|
const inserted = inserts.map((values, i) => buildRowCells(start + i, values, this.#columns));
|
|
357
284
|
this.#edits.spliceRows(start, count, inserted);
|
|
358
285
|
}
|
|
@@ -394,12 +321,7 @@ export class Worksheet {
|
|
|
394
321
|
}
|
|
395
322
|
duplicateRow(start, options = {}) {
|
|
396
323
|
const { count = 1, insert = true } = options;
|
|
397
|
-
|
|
398
|
-
throw new RangeError(`duplicate start ${start} is out of bounds — rows start at 1`);
|
|
399
|
-
}
|
|
400
|
-
if (!Number.isInteger(count) || count < 0) {
|
|
401
|
-
throw new RangeError(`duplicate count ${count} is invalid — it must be a non-negative integer`);
|
|
402
|
-
}
|
|
324
|
+
assertStartAndCount('duplicate', 'row', start, count);
|
|
403
325
|
const source = this.#rows.get(start);
|
|
404
326
|
const snapshot = (destRow) => {
|
|
405
327
|
const row = new Map();
|
|
@@ -422,12 +344,7 @@ export class Worksheet {
|
|
|
422
344
|
}
|
|
423
345
|
}
|
|
424
346
|
spliceColumns(start, count, ...inserts) {
|
|
425
|
-
|
|
426
|
-
throw new RangeError(`splice start ${start} is out of bounds — columns start at 1`);
|
|
427
|
-
}
|
|
428
|
-
if (!Number.isInteger(count) || count < 0) {
|
|
429
|
-
throw new RangeError(`splice count ${count} is invalid — it must be a non-negative integer`);
|
|
430
|
-
}
|
|
347
|
+
assertStartAndCount('splice', 'column', start, count);
|
|
431
348
|
this.#edits.spliceColumns(start, count, inserts);
|
|
432
349
|
}
|
|
433
350
|
insertColumn(pos, values) {
|
|
@@ -440,15 +357,11 @@ export class Worksheet {
|
|
|
440
357
|
let index = this.columnCount;
|
|
441
358
|
return columns.map((values) => {
|
|
442
359
|
index += 1;
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
if (value === undefined)
|
|
446
|
-
return;
|
|
447
|
-
const cell = this.#cellAt(i + 1, index);
|
|
360
|
+
return positionalPlacements(values).map(([row, value]) => {
|
|
361
|
+
const cell = this.#cellAt(row, index);
|
|
448
362
|
cell.value = value;
|
|
449
|
-
|
|
363
|
+
return cell;
|
|
450
364
|
});
|
|
451
|
-
return cells;
|
|
452
365
|
});
|
|
453
366
|
}
|
|
454
367
|
get model() {
|
|
@@ -510,7 +423,7 @@ export class Worksheet {
|
|
|
510
423
|
this.#loadedPivotTables.push(pivot);
|
|
511
424
|
},
|
|
512
425
|
restoreCommentThreads: (threads) => {
|
|
513
|
-
|
|
426
|
+
this.#comments.restore(threads);
|
|
514
427
|
},
|
|
515
428
|
addPreservedReference: (reference) => {
|
|
516
429
|
this.#preservedReferences.push(reference);
|
|
@@ -552,3 +465,11 @@ export class Worksheet {
|
|
|
552
465
|
},
|
|
553
466
|
};
|
|
554
467
|
}
|
|
468
|
+
function assertStartAndCount(verb, axis, start, count) {
|
|
469
|
+
if (!Number.isInteger(start) || start < 1) {
|
|
470
|
+
throw new RangeError(`${verb} start ${start} is out of bounds: ${axis}s start at 1`);
|
|
471
|
+
}
|
|
472
|
+
if (!Number.isInteger(count) || count < 0) {
|
|
473
|
+
throw new RangeError(`${verb} count ${count} is invalid: it must be a non-negative integer`);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { XlsxError } from '../errors.ts';
|
|
2
2
|
/**
|
|
3
3
|
* Thrown when a `customUI` ribbon-customisation part (`customUI/customUI.xml` or
|
|
4
|
-
* `customUI/customUI14.xml`) is present but cannot be parsed into a {@link CustomUiDocument}
|
|
4
|
+
* `customUI/customUI14.xml`) is present but cannot be parsed into a {@link CustomUiDocument}: malformed
|
|
5
5
|
* XML, a missing or unrecognised `<customUI>` root namespace, or nesting deep enough to look hostile.
|
|
6
6
|
* A workbook with no ribbon customisation never produces this: {@link Workbook.customUI} is an empty
|
|
7
7
|
* array instead.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** The `customUI` schema a part is written against
|
|
1
|
+
/** The `customUI` schema a part is written against. The read model keys off this, not the (frequently
|
|
2
2
|
* mis-copied) relationship type. `2007` is the original RibbonX (`customUI.xml`); `2010` is the later
|
|
3
3
|
* schema (`customUI14.xml`) that also carries backstage/QAT/commands. */
|
|
4
4
|
export type RibbonDialect = '2007' | '2010';
|
|
@@ -15,7 +15,7 @@ export declare function isCustomUiRelType(type: string): boolean;
|
|
|
15
15
|
* as `unknown` rather than dropped. The three identity attributes (`id` a document-defined control,
|
|
16
16
|
* `idQ` a qualified id, `idMso` a built-in control) and the two most-consulted display/behaviour
|
|
17
17
|
* attributes (`label`, `onAction`) are lifted out as typed conveniences; every attribute the element
|
|
18
|
-
* actually carried
|
|
18
|
+
* actually carried, including the many `get*` dynamic callbacks and layout hints not modelled here,
|
|
19
19
|
* is preserved verbatim in {@link attributes}, so nothing is lost. Container controls (a `menu`,
|
|
20
20
|
* `splitButton`, `gallery`, `dropDown`, `box`, …) carry their nested controls/items in {@link children}.
|
|
21
21
|
*/
|
|
@@ -29,7 +29,7 @@ export interface RibbonControl {
|
|
|
29
29
|
readonly idMso?: string;
|
|
30
30
|
/** The static label, when the element carries one (a dynamic label uses `getLabel`, in {@link attributes}). */
|
|
31
31
|
readonly label?: string;
|
|
32
|
-
/** The callback procedure name invoked on activation
|
|
32
|
+
/** The callback procedure name invoked on activation: the macro a click runs. */
|
|
33
33
|
readonly onAction?: string;
|
|
34
34
|
/** Every attribute on the element, verbatim and entity-decoded. The typed fields above are lifted from
|
|
35
35
|
* here; this map is the complete record, including attributes this model does not lift out. */
|
package/dist/customui/ribbon.js
CHANGED
|
@@ -9,26 +9,29 @@ export function isCustomUiRelType(type) {
|
|
|
9
9
|
return type.endsWith('/ui/extensibility');
|
|
10
10
|
}
|
|
11
11
|
const MAX_DEPTH = 256;
|
|
12
|
-
const KNOWN_KINDS =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
12
|
+
const KNOWN_KINDS = {
|
|
13
|
+
button: true,
|
|
14
|
+
toggleButton: true,
|
|
15
|
+
checkBox: true,
|
|
16
|
+
editBox: true,
|
|
17
|
+
dropDown: true,
|
|
18
|
+
comboBox: true,
|
|
19
|
+
gallery: true,
|
|
20
|
+
menu: true,
|
|
21
|
+
dynamicMenu: true,
|
|
22
|
+
splitButton: true,
|
|
23
|
+
buttonGroup: true,
|
|
24
|
+
box: true,
|
|
25
|
+
labelControl: true,
|
|
26
|
+
separator: true,
|
|
27
|
+
menuSeparator: true,
|
|
28
|
+
dialogBoxLauncher: true,
|
|
29
|
+
control: true,
|
|
30
|
+
item: true,
|
|
31
|
+
};
|
|
32
|
+
function isKnownControlKind(local) {
|
|
33
|
+
return Object.hasOwn(KNOWN_KINDS, local);
|
|
34
|
+
}
|
|
32
35
|
export function parseCustomUi(input) {
|
|
33
36
|
const xml = typeof input === 'string' ? input : strFromU8(input);
|
|
34
37
|
let root;
|
|
@@ -79,9 +82,7 @@ function toGroup(groupEl) {
|
|
|
79
82
|
};
|
|
80
83
|
}
|
|
81
84
|
function toControl(el) {
|
|
82
|
-
const kind =
|
|
83
|
-
? el.local
|
|
84
|
-
: 'unknown';
|
|
85
|
+
const kind = isKnownControlKind(el.local) ? el.local : 'unknown';
|
|
85
86
|
return {
|
|
86
87
|
kind,
|
|
87
88
|
...identity(el.attrs),
|
package/dist/entries/core.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
export { type CellAddress, columnToNumber, decodeAddress, decodeRange, encodeAddress, MAX_COLUMN, MAX_ROW, numberToColumn, type RangeAddress, } from '../core/address.ts';
|
|
1
|
+
export { type CellAddress, columnToNumber, decodeAddress, decodeRange, encodeAddress, type GridRect, MAX_COLUMN, MAX_ROW, numberToColumn, type RangeAddress, } from '../core/address.ts';
|
|
2
2
|
export type { AutoFilter, CustomFilter, CustomFilterOperator, CustomFilterPredicate, FilterColumn, FilterCriteria, ValuesFilter, } from '../core/autofilter.ts';
|
|
3
3
|
export { Cell } from '../core/cell.ts';
|
|
4
4
|
export { applyTint, type ColorResolutionContext, DEFAULT_INDEXED_COLORS, resolveColor, SYSTEM_INDEXED_COLORS, } from '../core/color-resolution.ts';
|
|
5
5
|
export { Column } from '../core/column.ts';
|
|
6
|
-
export type { Comment, CommentThread, Mention, Person } from '../core/comment-thread.ts';
|
|
7
|
-
export type { CfValueObject, ConditionalFormatting, ConditionalFormattingRule, } from '../core/conditional-formatting.ts';
|
|
6
|
+
export type { Comment, CommentThread, Mention, MentionRef, Person } from '../core/comment-thread.ts';
|
|
7
|
+
export type { CfTimePeriod, CfValueObject, CfValueObjectType, ConditionalFormatting, ConditionalFormattingOperator, ConditionalFormattingRule, ConditionalFormattingType, IconSetType, } from '../core/conditional-formatting.ts';
|
|
8
8
|
export type { DataValidation, DataValidationEntry, DataValidationErrorStyle, DataValidationOperator, DataValidationType, } from '../core/data-validation.ts';
|
|
9
|
-
export { type AnchoredImage, type AnchorPoint, type Extent, type ImageAnchor, type ImageEditAs, isOneCellAnchor, type OneCellAnchor, PX_TO_EMU, type TwoCellAnchor, type WorkbookImage, } from '../core/image.ts';
|
|
9
|
+
export { type AnchoredImage, type AnchorPoint, type Extent, type ImageAnchor, type ImageEditAs, isOneCellAnchor, type OneCellAnchor, type PortableImage, PX_TO_EMU, type TwoCellAnchor, type WorkbookImage, type WorksheetImages, } from '../core/image.ts';
|
|
10
10
|
export { MAX_COLUMN_WIDTH, MAX_ROW_HEIGHT } from '../core/limits.ts';
|
|
11
|
-
export type { HeaderFooter, PageBreak, PageMargins, PageSetup, PrintOptions, } from '../core/page-setup.ts';
|
|
11
|
+
export type { HeaderFooter, PageBreak, PageMargins, PageOrder, PageOrientation, PageSetup, PrintOptions, } from '../core/page-setup.ts';
|
|
12
12
|
export { type ParsedPivotField, type ParsedPivotSource, type ParsedPivotTable, type PivotCacheField, type PivotItem, type PivotMetric, type PivotNumericSummary, type PivotRecordCell, type PivotSourceKind, PivotTable, type PivotTableOptions, } from '../core/pivot-table.ts';
|
|
13
13
|
export type { PreservedPart, PreservedRelationship, PreservedRootReference, PreservedWorksheetReference, } from '../core/preserved.ts';
|
|
14
14
|
export type { SheetProtection, SheetProtectionCredential, SheetProtectionFlags, SheetProtectionOptions, } from '../core/protection.ts';
|
|
@@ -18,8 +18,8 @@ export type { Alignment, Border, BorderEdge, BorderStyle, CellStyle, Color, Diff
|
|
|
18
18
|
export { Table, type TableColumn, type TableColumnStyle, type TableOptions, type TableRegion, type TableStyleInfo, } from '../core/table.ts';
|
|
19
19
|
export { isTableStyleElementType, STRIPE_ELEMENT_TYPES, TABLE_STYLE_ELEMENT_TYPES, type TableStyle, type TableStyleElement, type TableStyleElementType, } from '../core/table-style.ts';
|
|
20
20
|
export { estimateWrappedLines } from '../core/text-metrics.ts';
|
|
21
|
-
export { DEFAULT_THEME_COLOR_SCHEME, DEFAULT_THEME_FONTS,
|
|
21
|
+
export { DEFAULT_THEME_COLOR_SCHEME, DEFAULT_THEME_FONTS, THEME_COLOR_SLOTS, type ThemeColorScheme, type ThemeColorSlot, type ThemeFontScheme, type ThemeOverrides, } from '../core/theme.ts';
|
|
22
22
|
export { type CellValue, cellValueToText, coerceCellValue, type DataTableFormulaValue, detectValueType, ERROR_CODES, type ErrorCode, type ErrorValue, type FormulaResult, type FormulaValue, type HyperlinkValue, isDataTableFormulaValue, isErrorCode, isErrorValue, isFormulaValue, isHyperlinkValue, isRichTextValue, isSharedFormulaValue, type RichTextRun, type RichTextValue, richTextToPlain, type SharedFormulaValue, ValueType, } from '../core/value.ts';
|
|
23
23
|
export { type AddImageOptions, type AddWorksheetOptions, DEFAULT_WORKBOOK_VIEW, type DefinedName, type PreservedWorkbookReference, Workbook, type WorkbookProperties, type WorkbookView, } from '../core/workbook.ts';
|
|
24
24
|
export type { WorkbookProtection, WorkbookProtectionCredentialAttr, } from '../core/workbook-protection.ts';
|
|
25
|
-
export { type CellModel, type ColumnProperties, type OutlineProperties, type RowInput, type RowProperties, type SheetView, Worksheet, type WorksheetModel, type WorksheetProperties, type WorksheetState, } from '../core/worksheet.ts';
|
|
25
|
+
export { type CellModel, type ColumnProperties, type OutlineProperties, type RowInput, type RowProperties, type SheetView, type Visibility, Worksheet, type WorksheetModel, type WorksheetProperties, type WorksheetState, } from '../core/worksheet.ts';
|
package/dist/entries/core.js
CHANGED
|
@@ -10,7 +10,7 @@ export { Row } from '../core/row.js';
|
|
|
10
10
|
export { Table, } from '../core/table.js';
|
|
11
11
|
export { isTableStyleElementType, STRIPE_ELEMENT_TYPES, TABLE_STYLE_ELEMENT_TYPES, } from '../core/table-style.js';
|
|
12
12
|
export { estimateWrappedLines } from '../core/text-metrics.js';
|
|
13
|
-
export { DEFAULT_THEME_COLOR_SCHEME, DEFAULT_THEME_FONTS,
|
|
13
|
+
export { DEFAULT_THEME_COLOR_SCHEME, DEFAULT_THEME_FONTS, THEME_COLOR_SLOTS, } from '../core/theme.js';
|
|
14
14
|
export { cellValueToText, coerceCellValue, detectValueType, ERROR_CODES, isDataTableFormulaValue, isErrorCode, isErrorValue, isFormulaValue, isHyperlinkValue, isRichTextValue, isSharedFormulaValue, richTextToPlain, ValueType, } from '../core/value.js';
|
|
15
15
|
export { DEFAULT_WORKBOOK_VIEW, Workbook, } from '../core/workbook.js';
|
|
16
16
|
export { Worksheet, } from '../core/worksheet.js';
|
package/dist/entries/csv.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { type CsvReadOptions, readCsv } from '../io/csv/read.ts';
|
|
2
|
-
export { type CsvWriteOptions, writeCsv, writeCsvText } from '../io/csv/write.ts';
|
|
2
|
+
export { type CsvEncoding, type CsvWriteOptions, writeCsv, writeCsvText } from '../io/csv/write.ts';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Not available outside Node; see {@link WorkbookStreamWriter}. */
|
|
2
|
+
export declare class StreamedRow {
|
|
3
|
+
constructor();
|
|
4
|
+
}
|
|
5
|
+
/** Not available outside Node; see {@link WorkbookStreamWriter}. */
|
|
6
|
+
export declare class WorksheetStreamWriter {
|
|
7
|
+
constructor();
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Not available outside Node. The streaming writer needs `node:fs` and `node:stream`; in a browser,
|
|
11
|
+
* build the workbook in memory and call `writeXlsx`.
|
|
12
|
+
*/
|
|
13
|
+
export declare class WorkbookStreamWriter {
|
|
14
|
+
constructor();
|
|
15
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const WHY = 'the streaming writer opens files and pipes Node streams, which a browser has neither of. ' +
|
|
2
|
+
'Use writeXlsx (or writeXlsxAsync), which produce the same package as bytes.';
|
|
3
|
+
function unavailable(name) {
|
|
4
|
+
throw new Error(`ts-xlsx: ${name} is not available in this environment: ${WHY}`);
|
|
5
|
+
}
|
|
6
|
+
export class StreamedRow {
|
|
7
|
+
constructor() {
|
|
8
|
+
unavailable('StreamedRow');
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export class WorksheetStreamWriter {
|
|
12
|
+
constructor() {
|
|
13
|
+
unavailable('WorksheetStreamWriter');
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export class WorkbookStreamWriter {
|
|
17
|
+
constructor() {
|
|
18
|
+
unavailable('WorkbookStreamWriter');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { type CalcProperties, StreamedRow, WorkbookStreamWriter, type WorkbookStreamWriterOptions, WorksheetStreamWriter, } from '../io/xlsx/write-stream.ts';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { StreamedRow, WorkbookStreamWriter, WorksheetStreamWriter, } from '../io/xlsx/write-stream.js';
|
package/dist/entries/vba.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { parseVbaProject, type VbaModule, type VbaModuleKind, type VbaProject, type VbaProjectSignature, type VbaProjectSignatureKind, } from '../vba/project.ts';
|
|
2
|
-
export { addVbaReference, removeVbaModule, type VbaLibraryReference
|
|
2
|
+
export { addVbaReference, removeVbaModule, type VbaLibraryReference } from '../vba/project-editor.ts';
|
package/dist/entries/vba.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { parseVbaProject, } from '../vba/project.js';
|
|
2
|
-
export { addVbaReference, removeVbaModule
|
|
2
|
+
export { addVbaReference, removeVbaModule } from '../vba/project-editor.js';
|
package/dist/entries/xlsx.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { editXlsxVbaAddReference, editXlsxVbaRemoveModule } from '../io/xlsx/edit-vba.ts';
|
|
2
2
|
export { type ReadXlsxOptions, readXlsx } from '../io/xlsx/read.ts';
|
|
3
3
|
export { type ReadSheetRowsOptions, readSheetRows, readWorkbookStream, } from '../io/xlsx/read-rows.ts';
|
|
4
|
+
export { DEFAULT_THEME_XML, parseThemeColorScheme, parseThemeFontScheme, } from '../io/xlsx/theme-xml.ts';
|
|
4
5
|
export { type WriteOptions, writeXlsx, writeXlsxAsync } from '../io/xlsx/write.ts';
|
|
5
|
-
export { type CalcProperties, StreamedRow, WorkbookStreamWriter, type WorkbookStreamWriterOptions, WorksheetStreamWriter, } from '../io/xlsx/write-stream.ts';
|
package/dist/entries/xlsx.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { editXlsxVbaAddReference, editXlsxVbaRemoveModule } from '../io/xlsx/edit-vba.js';
|
|
2
2
|
export { readXlsx } from '../io/xlsx/read.js';
|
|
3
3
|
export { readSheetRows, readWorkbookStream, } from '../io/xlsx/read-rows.js';
|
|
4
|
+
export { DEFAULT_THEME_XML, parseThemeColorScheme, parseThemeFontScheme, } from '../io/xlsx/theme-xml.js';
|
|
4
5
|
export { writeXlsx, writeXlsxAsync } from '../io/xlsx/write.js';
|
|
5
|
-
export { StreamedRow, WorkbookStreamWriter, WorksheetStreamWriter, } from '../io/xlsx/write-stream.js';
|
package/dist/errors.d.ts
CHANGED
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
* What kind of failure an {@link XlsxError} reports. This is the branch most callers want, and it is
|
|
3
3
|
* deliberately coarse: the four answers are the four different things a caller would *do* next.
|
|
4
4
|
*
|
|
5
|
-
* - `'unsupported-format'
|
|
5
|
+
* - `'unsupported-format'`: the input is not a container this library reads at all (a legacy `.xls`,
|
|
6
6
|
* a blob that is not a spreadsheet). Nothing is wrong with the file; it is the wrong file *for us*.
|
|
7
|
-
* - `'malformed-input'
|
|
7
|
+
* - `'malformed-input'`: a part we do read is corrupt or does not conform to its specification. The
|
|
8
8
|
* file is broken, or hostile.
|
|
9
|
-
* - `'authoring'
|
|
10
|
-
* - `'internal'
|
|
9
|
+
* - `'authoring'`: the caller described a document that cannot exist. The bug is in the calling code.
|
|
10
|
+
* - `'internal'`: an invariant this library maintains did not hold. It should be unreachable; if it
|
|
11
11
|
* fires, the bug is ours.
|
|
12
12
|
*
|
|
13
13
|
* There is deliberately no "not implemented yet" code. Every candidate for one turned out to be an
|
|
14
|
-
* unreachable exhaustiveness guard (so: `'internal'`), and the one genuine feature gap
|
|
15
|
-
* `.xlsb` cannot be row-streamed
|
|
14
|
+
* unreachable exhaustiveness guard (so: `'internal'`), and the one genuine feature gap (a binary
|
|
15
|
+
* `.xlsb` cannot be row-streamed) is already reported by {@link UnsupportedFormatError}'s `format`
|
|
16
16
|
* branch. A code with no throw site would be a promise the library does not keep.
|
|
17
17
|
*
|
|
18
18
|
* **Which of these is worth reporting upstream.** `'internal'` always is, and says so at runtime.
|
|
19
19
|
* `'unsupported-format'` and `'malformed-input'` are worth reporting when the file in hand opens
|
|
20
|
-
* cleanly in Excel
|
|
20
|
+
* cleanly in Excel: that combination means we are the ones who cannot read it, which is a gap, not
|
|
21
21
|
* a corrupt input. `'authoring'` is worth reporting only if the document it refused is one a real
|
|
22
22
|
* workbook can express. See `skills/ts-xlsx-upstream` for how to file one.
|
|
23
23
|
*/
|
|
@@ -29,7 +29,7 @@ export type XlsxErrorCode = 'unsupported-format' | 'malformed-input' | 'authorin
|
|
|
29
29
|
*
|
|
30
30
|
* Abstract on purpose: a failure always has a kind, so there is never a reason to throw the base.
|
|
31
31
|
* Every subclass fixes {@link code} to a literal, which makes the class hierarchy a discriminated
|
|
32
|
-
* union
|
|
32
|
+
* union, so narrowing on `error.code` narrows the type.
|
|
33
33
|
*
|
|
34
34
|
* The constructor is inherited from `Error`, so every subclass accepts `{cause}`; layers that wrap a
|
|
35
35
|
* lower-level failure are expected to pass it rather than flatten it into the message.
|
|
@@ -43,13 +43,13 @@ export declare abstract class XlsxError extends Error {
|
|
|
43
43
|
* worksheets. The document model, not a single argument, is what is wrong.
|
|
44
44
|
*
|
|
45
45
|
* **Where the line falls against native errors.** A single scalar that is out of range, unparseable,
|
|
46
|
-
* or the wrong type stays a native `RangeError` / `SyntaxError` / `TypeError
|
|
46
|
+
* or the wrong type stays a native `RangeError` / `SyntaxError` / `TypeError`: those types exist for
|
|
47
47
|
* exactly that, every caller already reads them, and wrapping them would make this taxonomy a
|
|
48
48
|
* re-implementation of the language's. `AuthoringError` starts where a *composite* is internally
|
|
49
49
|
* inconsistent, or contradicts something a workbook can express. `getColumn(0)` is a `RangeError`;
|
|
50
50
|
* a table that names a column twice is an `AuthoringError`.
|
|
51
51
|
*
|
|
52
|
-
* It is always the calling code that is wrong, never the input file
|
|
52
|
+
* It is always the calling code that is wrong, never the input file; a malformed file raises a
|
|
53
53
|
* `'malformed-input'` error instead.
|
|
54
54
|
*/
|
|
55
55
|
export declare class AuthoringError extends XlsxError {
|
|
@@ -57,7 +57,7 @@ export declare class AuthoringError extends XlsxError {
|
|
|
57
57
|
readonly code = "authoring";
|
|
58
58
|
}
|
|
59
59
|
/**
|
|
60
|
-
* Thrown where an invariant the library itself maintains turns out not to hold
|
|
60
|
+
* Thrown where an invariant the library itself maintains turns out not to hold: typically an index
|
|
61
61
|
* that a preceding pass proved to be in range, re-checked because `noUncheckedIndexedAccess` makes
|
|
62
62
|
* the possibility of `undefined` explicit and casting it away would be worse.
|
|
63
63
|
*
|
|
@@ -67,7 +67,7 @@ export declare class AuthoringError extends XlsxError {
|
|
|
67
67
|
*
|
|
68
68
|
* It is the one class in the taxonomy that rewrites its own message, appending {@link REPORT_NOTICE}
|
|
69
69
|
* below the invariant that broke. The constructor is where that lives so a throw site added later
|
|
70
|
-
* inherits it
|
|
70
|
+
* inherits it; the alternative, a notice pasted at each of the throw sites, is one every future
|
|
71
71
|
* site can forget. Every other class leaves `message` exactly as given: `'malformed-input'` is a
|
|
72
72
|
* routine outcome for a library that reads untrusted files, and a "report this" banner on each
|
|
73
73
|
* corrupt input would train callers to ignore the one banner that always means something.
|
package/dist/io/csv/read.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { Workbook } from '../../core/workbook.js';
|
|
2
|
-
import { AuthoringError } from '../../errors.js';
|
|
3
2
|
export function readCsv(input, options = {}) {
|
|
4
|
-
const text = stripBom(typeof input === 'string' ? input :
|
|
3
|
+
const text = stripBom(typeof input === 'string' ? input : new TextDecoder('utf-8', { ignoreBOM: true }).decode(input));
|
|
5
4
|
const delimiter = options.delimiter ?? ',';
|
|
6
5
|
if (delimiter.length !== 1) {
|
|
7
|
-
throw new
|
|
6
|
+
throw new RangeError(`CSV delimiter must be a single character, got ${JSON.stringify(delimiter)}`);
|
|
8
7
|
}
|
|
9
8
|
let rows = parseCsvRows(text, delimiter);
|
|
10
9
|
if (options.headers)
|