@shbernal/ts-xlsx 3.0.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -24
- package/dist/bytes.d.ts +10 -2
- package/dist/bytes.js +22 -0
- package/dist/core/address.d.ts +96 -2
- package/dist/core/address.js +87 -33
- package/dist/core/array-formula-ranges.d.ts +33 -0
- package/dist/core/array-formula-ranges.js +62 -0
- package/dist/core/autofilter.d.ts +4 -3
- package/dist/core/autofilter.js +31 -30
- package/dist/core/axis-handle.d.ts +2 -0
- package/dist/core/axis-handle.js +5 -2
- package/dist/core/cell.d.ts +4 -3
- package/dist/core/cell.js +4 -6
- package/dist/core/clone.d.ts +29 -0
- package/dist/core/clone.js +24 -0
- package/dist/core/color-resolution.js +4 -6
- package/dist/core/column.d.ts +1 -0
- package/dist/core/column.js +6 -2
- package/dist/core/comment-thread.d.ts +7 -3
- package/dist/core/comment-thread.js +2 -1
- package/dist/core/conditional-formatting-overlay.d.ts +11 -1
- package/dist/core/conditional-formatting-overlay.js +30 -3
- package/dist/core/conditional-formatting.d.ts +107 -11
- package/dist/core/conditional-formatting.js +76 -19
- package/dist/core/containers.d.ts +12 -0
- package/dist/core/containers.js +5 -0
- package/dist/core/data-validation-overlay.d.ts +7 -1
- package/dist/core/data-validation-overlay.js +19 -4
- package/dist/core/data-validation.d.ts +22 -0
- package/dist/core/data-validation.js +30 -4
- package/dist/core/date-format.d.ts +20 -0
- package/dist/core/date-format.js +170 -0
- package/dist/core/date.d.ts +43 -8
- package/dist/core/date.js +19 -3
- package/dist/core/formula-references.d.ts +26 -0
- package/dist/core/formula-references.js +173 -0
- package/dist/core/formula-scan.d.ts +2 -0
- package/dist/core/formula-scan.js +58 -0
- package/dist/core/formula.d.ts +76 -17
- package/dist/core/formula.js +87 -80
- package/dist/core/function-values.d.ts +4 -0
- package/dist/core/function-values.js +58 -0
- package/dist/core/future-functions.d.ts +3 -0
- package/dist/core/{modern-functions.js → future-functions.js} +119 -88
- package/dist/core/grid-edits.d.ts +30 -3
- package/dist/core/grid-edits.js +248 -81
- package/dist/core/grid-shift.d.ts +58 -9
- package/dist/core/grid-shift.js +26 -4
- package/dist/core/hyperlink.d.ts +39 -0
- package/dist/core/hyperlink.js +88 -0
- package/dist/core/image.d.ts +49 -14
- package/dist/core/image.js +16 -5
- package/dist/core/internal.d.ts +10 -2
- package/dist/core/limits.d.ts +25 -0
- package/dist/core/limits.js +4 -0
- package/dist/core/merge.d.ts +18 -4
- package/dist/core/merge.js +33 -20
- package/dist/core/page-setup.d.ts +26 -11
- package/dist/core/pivot-table.d.ts +49 -10
- package/dist/core/pivot-table.js +112 -60
- package/dist/core/protection.d.ts +66 -4
- package/dist/core/protection.js +6 -11
- package/dist/core/range.js +34 -30
- package/dist/core/row-input.js +2 -2
- package/dist/core/row.d.ts +1 -0
- package/dist/core/row.js +6 -2
- package/dist/core/structured-reference.d.ts +7 -0
- package/dist/core/structured-reference.js +7 -0
- package/dist/core/style.d.ts +85 -70
- package/dist/core/style.js +92 -28
- package/dist/core/table-style.d.ts +1 -1
- package/dist/core/table-style.js +4 -4
- package/dist/core/table.d.ts +64 -16
- package/dist/core/table.js +87 -40
- package/dist/core/theme.d.ts +2 -0
- package/dist/core/theme.js +9 -5
- package/dist/core/value.d.ts +60 -28
- package/dist/core/value.js +48 -43
- package/dist/core/workbook-media.d.ts +34 -0
- package/dist/core/workbook-media.js +44 -0
- package/dist/core/workbook-styles.d.ts +83 -1
- package/dist/core/workbook-styles.js +4 -0
- package/dist/core/workbook-theme.js +5 -3
- package/dist/core/workbook-vba.js +3 -2
- package/dist/core/workbook.d.ts +41 -3
- package/dist/core/workbook.js +46 -41
- package/dist/core/worksheet-comments.d.ts +2 -1
- package/dist/core/worksheet-comments.js +20 -13
- package/dist/core/worksheet-merges.d.ts +49 -0
- package/dist/core/worksheet-merges.js +65 -0
- package/dist/core/worksheet-model.d.ts +10 -2
- package/dist/core/worksheet-model.js +28 -9
- package/dist/core/worksheet-pictures.d.ts +3 -3
- package/dist/core/worksheet-pictures.js +7 -6
- package/dist/core/worksheet.d.ts +165 -27
- package/dist/core/worksheet.js +206 -89
- package/dist/customui/ribbon.js +2 -1
- package/dist/entries/core.d.ts +21 -14
- package/dist/entries/core.js +14 -7
- package/dist/entries/errors.d.ts +1 -0
- package/dist/entries/errors.js +1 -0
- package/dist/entries/xlsx.d.ts +1 -1
- package/dist/errors.d.ts +64 -0
- package/dist/errors.js +22 -0
- package/dist/hex.d.ts +8 -0
- package/dist/hex.js +3 -0
- package/dist/io/cell-metadata/metadata.d.ts +42 -0
- package/dist/io/cell-metadata/metadata.js +35 -0
- package/dist/io/cell-metadata/rich-values.d.ts +11 -0
- package/dist/io/cell-metadata/rich-values.js +80 -0
- package/dist/io/csv/delimiter.d.ts +21 -0
- package/dist/io/csv/delimiter.js +18 -0
- package/dist/io/csv/errors.d.ts +14 -0
- package/dist/io/csv/errors.js +5 -0
- package/dist/io/csv/read.d.ts +6 -1
- package/dist/io/csv/read.js +51 -22
- package/dist/io/csv/write.d.ts +19 -5
- package/dist/io/csv/write.js +24 -44
- package/dist/io/opc/inflate.js +14 -0
- package/dist/io/opc/namespaces.d.ts +16 -0
- package/dist/io/opc/namespaces.js +4 -0
- package/dist/io/opc/part-paths.d.ts +9 -0
- package/dist/io/opc/part-paths.js +5 -5
- package/dist/io/opc/read-opc.d.ts +58 -14
- package/dist/io/opc/read-opc.js +49 -21
- package/dist/io/opc/read-options.d.ts +5 -1
- package/dist/io/opc/sniff-format.d.ts +3 -3
- package/dist/io/opc/sniff-format.js +2 -2
- package/dist/io/opc/strict-relationships.d.ts +2 -0
- package/dist/io/opc/strict-relationships.js +12 -0
- package/dist/io/read-policy/column-budget.d.ts +26 -0
- package/dist/io/read-policy/column-budget.js +18 -0
- package/dist/io/read-policy/read-repair.d.ts +74 -0
- package/dist/io/read-policy/read-repair.js +119 -0
- package/dist/io/style/cell-style-resolution.d.ts +25 -0
- package/dist/io/style/cell-style-resolution.js +30 -0
- package/dist/io/style/xf-style.d.ts +23 -1
- package/dist/io/style/xf-style.js +8 -0
- package/dist/io/xlsb/formula.d.ts +2 -2
- package/dist/io/xlsb/formula.js +52 -35
- package/dist/io/xlsb/primitives.js +8 -14
- package/dist/io/xlsb/ptg-functions.d.ts +19 -10
- package/dist/io/xlsb/ptg-functions.js +495 -596
- package/dist/io/xlsb/read-metadata.d.ts +7 -0
- package/dist/io/xlsb/read-metadata.js +69 -0
- package/dist/io/xlsb/read-styles.js +45 -81
- package/dist/io/xlsb/read-worksheet.d.ts +26 -1
- package/dist/io/xlsb/read-worksheet.js +148 -106
- package/dist/io/xlsb/read.d.ts +6 -3
- package/dist/io/xlsb/read.js +70 -31
- package/dist/io/xlsb/record-stream.d.ts +30 -0
- package/dist/io/xlsb/record-stream.js +20 -0
- package/dist/io/xlsb/record-types.d.ts +14 -5
- package/dist/io/xlsb/record-types.js +14 -5
- package/dist/io/xlsb/sheet-protection.d.ts +20 -0
- package/dist/io/xlsb/sheet-protection.js +60 -0
- package/dist/io/xlsx/cell-accumulator.d.ts +24 -9
- package/dist/io/xlsx/cell-accumulator.js +74 -21
- package/dist/io/xlsx/cell-metadata.d.ts +39 -0
- package/dist/io/xlsx/cell-metadata.js +162 -0
- package/dist/io/xlsx/cell-value.d.ts +19 -5
- package/dist/io/xlsx/cell-value.js +45 -30
- package/dist/io/xlsx/color-xml.js +3 -2
- package/dist/io/xlsx/column-span.d.ts +11 -0
- package/dist/io/xlsx/column-span.js +9 -0
- package/dist/io/xlsx/comments.d.ts +9 -30
- package/dist/io/xlsx/comments.js +25 -83
- package/dist/io/xlsx/conditional-formatting.d.ts +43 -23
- package/dist/io/xlsx/conditional-formatting.js +437 -138
- package/dist/io/xlsx/data-validation.d.ts +12 -7
- package/dist/io/xlsx/data-validation.js +67 -53
- package/dist/io/xlsx/edit-vba.d.ts +7 -2
- package/dist/io/xlsx/edit-vba.js +52 -52
- package/dist/io/xlsx/font-xml.d.ts +7 -0
- package/dist/io/xlsx/font-xml.js +104 -0
- package/dist/io/xlsx/hyperlinks.d.ts +19 -21
- package/dist/io/xlsx/hyperlinks.js +12 -32
- package/dist/io/xlsx/images.d.ts +49 -16
- package/dist/io/xlsx/images.js +149 -50
- package/dist/io/xlsx/namespaces.d.ts +24 -0
- package/dist/io/xlsx/namespaces.js +11 -0
- package/dist/io/xlsx/package-plan.d.ts +60 -15
- package/dist/io/xlsx/package-plan.js +83 -18
- package/dist/io/xlsx/part-names.d.ts +6 -8
- package/dist/io/xlsx/part-names.js +3 -7
- package/dist/io/xlsx/pivot.d.ts +5 -5
- package/dist/io/xlsx/pivot.js +26 -24
- package/dist/io/xlsx/preserved-splices.d.ts +6 -0
- package/dist/io/xlsx/preserved-splices.js +74 -0
- package/dist/io/xlsx/read-comments.d.ts +29 -0
- package/dist/io/xlsx/read-comments.js +75 -0
- package/dist/io/xlsx/read-parts.d.ts +59 -0
- package/dist/io/xlsx/read-parts.js +259 -0
- package/dist/io/xlsx/read-pivot.js +11 -4
- package/dist/io/xlsx/{rich-runs.d.ts → read-rich-runs.d.ts} +8 -5
- package/dist/io/xlsx/{rich-runs.js → read-rich-runs.js} +24 -4
- package/dist/io/xlsx/read-rows.d.ts +35 -11
- package/dist/io/xlsx/read-rows.js +73 -49
- package/dist/io/xlsx/read-shared-strings.js +3 -2
- package/dist/io/xlsx/read-styles.d.ts +0 -30
- package/dist/io/xlsx/read-styles.js +45 -105
- package/dist/io/xlsx/read-workbook-xml.d.ts +42 -0
- package/dist/io/xlsx/read-workbook-xml.js +175 -0
- package/dist/io/xlsx/read-worksheet.d.ts +9 -3
- package/dist/io/xlsx/read-worksheet.js +70 -177
- package/dist/io/xlsx/read.d.ts +3 -14
- package/dist/io/xlsx/read.js +74 -411
- package/dist/io/xlsx/relationships.d.ts +3 -0
- package/dist/io/xlsx/relationships.js +4 -0
- package/dist/io/xlsx/rich-text.js +1 -1
- package/dist/io/xlsx/row-position.d.ts +20 -0
- package/dist/io/xlsx/row-position.js +11 -0
- package/dist/io/xlsx/row-xml.d.ts +139 -0
- package/dist/io/xlsx/row-xml.js +222 -0
- package/dist/io/xlsx/shared-formulas.js +2 -2
- package/dist/io/xlsx/sheet-properties.d.ts +10 -1
- package/dist/io/xlsx/sheet-properties.js +182 -20
- package/dist/io/xlsx/strict-parts.d.ts +7 -0
- package/dist/io/xlsx/strict-parts.js +171 -0
- package/dist/io/xlsx/style-elements.d.ts +41 -0
- package/dist/io/xlsx/style-elements.js +136 -0
- package/dist/io/xlsx/styles.d.ts +17 -3
- package/dist/io/xlsx/styles.js +13 -209
- package/dist/io/xlsx/tables.d.ts +10 -2
- package/dist/io/xlsx/tables.js +55 -52
- package/dist/io/xlsx/theme-xml.d.ts +32 -4
- package/dist/io/xlsx/theme-xml.js +106 -71
- package/dist/io/xlsx/threaded-comments.d.ts +14 -11
- package/dist/io/xlsx/threaded-comments.js +16 -8
- package/dist/io/xlsx/workbook-xml.d.ts +45 -6
- package/dist/io/xlsx/workbook-xml.js +62 -54
- package/dist/io/xlsx/worksheet-xml.d.ts +26 -70
- package/dist/io/xlsx/worksheet-xml.js +69 -282
- package/dist/io/xlsx/write-stream.d.ts +90 -19
- package/dist/io/xlsx/write-stream.js +80 -25
- package/dist/io/xlsx/write.d.ts +12 -6
- package/dist/io/xlsx/write.js +226 -123
- package/dist/rel-type.d.ts +25 -0
- package/dist/rel-type.js +9 -0
- package/dist/token-set.d.ts +13 -0
- package/dist/token-set.js +4 -1
- package/dist/vba/bytes.d.ts +16 -5
- package/dist/vba/bytes.js +27 -6
- package/dist/vba/cfb-format.d.ts +55 -0
- package/dist/vba/cfb-format.js +35 -0
- package/dist/vba/cfb-writer.d.ts +8 -0
- package/dist/vba/cfb-writer.js +40 -40
- package/dist/vba/cfb.d.ts +21 -4
- package/dist/vba/cfb.js +124 -90
- package/dist/vba/codepage.js +2 -1
- package/dist/vba/dir-records.d.ts +6 -0
- package/dist/vba/dir-records.js +10 -2
- package/dist/vba/errors.d.ts +11 -4
- package/dist/vba/index.d.ts +0 -2
- package/dist/vba/index.js +0 -2
- package/dist/vba/ms-ovba.d.ts +6 -2
- package/dist/vba/ms-ovba.js +66 -22
- package/dist/vba/project-editor.js +129 -119
- package/dist/vba/project.d.ts +15 -1
- package/dist/vba/project.js +38 -13
- package/dist/vba/vba-encoding.d.ts +4 -10
- package/dist/vba/vba-encoding.js +3 -17
- package/dist/xml/xml-attrs.d.ts +37 -0
- package/dist/xml/xml-attrs.js +30 -0
- package/dist/xml/xml-chars.d.ts +40 -0
- package/dist/xml/xml-chars.js +12 -0
- package/dist/xml/xml-namespaces.d.ts +31 -0
- package/dist/xml/xml-namespaces.js +50 -0
- package/dist/xml/xml-read.d.ts +101 -11
- package/dist/xml/xml-read.js +150 -18
- package/dist/xml/xml-scan.d.ts +25 -34
- package/dist/xml/xml-scan.js +69 -46
- package/dist/xml/xml.d.ts +59 -26
- package/dist/xml/xml.js +45 -23
- package/package.json +15 -9
- package/skills/ts-xlsx-upstream/SKILL.md +21 -13
- package/dist/core/modern-functions.d.ts +0 -1
|
@@ -1,57 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { AuthoringError, InternalError } from '../../errors.js';
|
|
9
|
-
import { assertWritableNumber, escapeAttr, escapeSpreadsheetText, escapeText, numberText, textAttr, textElement, XML_DECLARATION, } from '../../xml/xml.js';
|
|
10
|
-
import { relationship, relationshipsPart } from '../opc/rels.js';
|
|
11
|
-
import { conditionalFormattingsExtXml, conditionalFormattingsXml } from './conditional-formatting.js';
|
|
1
|
+
import { encodeRect } from '../../core/address.js';
|
|
2
|
+
import { arrayRangeConflicts, formulaPlacement } from '../../core/array-formula-ranges.js';
|
|
3
|
+
import { mergesOverlappingTables } from '../../core/merge.js';
|
|
4
|
+
import { pickStyleFacets } from '../../core/style.js';
|
|
5
|
+
import { AuthoringError, InternalError, quoted } from '../../errors.js';
|
|
6
|
+
import { escapeAttr, numberText, XML_DECLARATION } from '../../xml/xml.js';
|
|
7
|
+
import { conditionalFormattingsExtXml, conditionalFormattingsXml, planConditionalFormatting, } from './conditional-formatting.js';
|
|
12
8
|
import { dataValidationsExtXml, dataValidationsXml } from './data-validation.js';
|
|
13
9
|
import { hyperlinksXml } from './hyperlinks.js';
|
|
14
10
|
import { SLICER_LIST_EXT_URI } from './namespaces.js';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import { richTextRunsXml } from './rich-text.js';
|
|
11
|
+
import { NS } from './relationships.js';
|
|
12
|
+
import { assertWritableLevel, buildColumnDefaults, Extent, outlineAttr, renderRow, rowOpenTag, } from './row-xml.js';
|
|
18
13
|
import { planSharedFormulas } from './shared-formulas.js';
|
|
19
14
|
import { autoFilterXml, headerFooterXml, pageBreaksXml, pageMarginsXml, pageSetupXml, printOptionsXml, sheetProtectionXml, sheetPrXml, sheetViewsXml, } from './sheet-properties.js';
|
|
20
15
|
import { x14Ext } from './x14-ext.js';
|
|
21
|
-
export
|
|
22
|
-
|
|
23
|
-
left = Infinity;
|
|
24
|
-
bottom = -Infinity;
|
|
25
|
-
right = -Infinity;
|
|
26
|
-
constructor(seed) {
|
|
27
|
-
if (seed) {
|
|
28
|
-
this.top = seed.top;
|
|
29
|
-
this.left = seed.left;
|
|
30
|
-
this.bottom = seed.bottom;
|
|
31
|
-
this.right = seed.right;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
get isEmpty() {
|
|
35
|
-
return this.bottom === -Infinity;
|
|
36
|
-
}
|
|
37
|
-
add(row, minCol, maxCol) {
|
|
38
|
-
if (minCol === Infinity)
|
|
39
|
-
return;
|
|
40
|
-
if (row < this.top)
|
|
41
|
-
this.top = row;
|
|
42
|
-
if (row > this.bottom)
|
|
43
|
-
this.bottom = row;
|
|
44
|
-
if (minCol < this.left)
|
|
45
|
-
this.left = minCol;
|
|
46
|
-
if (maxCol > this.right)
|
|
47
|
-
this.right = maxCol;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
export function worksheetXml(sheet, tables, styles, references, hyperlinks, sharedStrings, active, flushed) {
|
|
16
|
+
export function worksheetXml(inputs) {
|
|
17
|
+
const { sheet, tables, styles, references, hyperlinks, sharedStrings, cellMetadata, dateEpoch, formulaNames, active, flushed, } = inputs;
|
|
51
18
|
validateMerges(sheet);
|
|
19
|
+
validateArrayRanges(sheet, flushed);
|
|
52
20
|
const columnDefaults = buildColumnDefaults(sheet);
|
|
53
21
|
const sharedRoles = planSharedFormulas(sheet);
|
|
54
|
-
const
|
|
22
|
+
const formattingPlan = planConditionalFormatting(sheet.conditionalFormattings);
|
|
23
|
+
const rowOutline = scanRowOutline(sheet, flushed);
|
|
55
24
|
const collapsedSummaries = rowOutline.collapsedSummaries;
|
|
56
25
|
const context = {
|
|
57
26
|
columnDefaults,
|
|
@@ -59,6 +28,9 @@ export function worksheetXml(sheet, tables, styles, references, hyperlinks, shar
|
|
|
59
28
|
sharedStrings,
|
|
60
29
|
sharedRoles,
|
|
61
30
|
collapsedSummaries,
|
|
31
|
+
dateEpoch,
|
|
32
|
+
formulaNames,
|
|
33
|
+
cellMetadata,
|
|
62
34
|
};
|
|
63
35
|
const liveRows = [];
|
|
64
36
|
const extent = new Extent(flushed?.extent);
|
|
@@ -69,11 +41,9 @@ export function worksheetXml(sheet, tables, styles, references, hyperlinks, shar
|
|
|
69
41
|
liveRows.push({ number: entry.number, xml });
|
|
70
42
|
extent.add(entry.number, minCol, maxCol);
|
|
71
43
|
}
|
|
72
|
-
const dimensionRef = extent.isEmpty
|
|
73
|
-
? 'A1'
|
|
74
|
-
: `${encodeAddress(extent.left, extent.top)}:${encodeAddress(extent.right, extent.bottom)}`;
|
|
44
|
+
const dimensionRef = extent.isEmpty ? 'A1' : encodeRect(extent);
|
|
75
45
|
const orderedRows = flushed
|
|
76
|
-
? [...flushed.rows, ...liveRows].sort((a, b) => a.number - b.number)
|
|
46
|
+
? [...flushed.rows.map((row) => completeCollapsed(row, collapsedSummaries)), ...liveRows].sort((a, b) => a.number - b.number)
|
|
77
47
|
: liveRows;
|
|
78
48
|
const bodyXml = orderedRows.map((row) => row.xml).join('');
|
|
79
49
|
const sheetData = bodyXml === '' ? '<sheetData/>' : `<sheetData>${bodyXml}</sheetData>`;
|
|
@@ -84,15 +54,15 @@ export function worksheetXml(sheet, tables, styles, references, hyperlinks, shar
|
|
|
84
54
|
sheetViewsXml(sheet.view, active) +
|
|
85
55
|
sheetFormatPr(sheet.properties, {
|
|
86
56
|
col: maxColumnOutlineLevel(sheet),
|
|
87
|
-
row:
|
|
57
|
+
row: rowOutline.maxLevel,
|
|
88
58
|
}) +
|
|
89
59
|
colsXml(sheet, styles) +
|
|
90
60
|
sheetData +
|
|
91
61
|
sheetProtectionXml(sheet.protection) +
|
|
92
62
|
autoFilterXml(sheet.autoFilter) +
|
|
93
63
|
mergeCellsXml(sheet.merges) +
|
|
94
|
-
conditionalFormattingsXml(sheet.conditionalFormattings, styles) +
|
|
95
|
-
dataValidationsXml(sheet.dataValidations) +
|
|
64
|
+
conditionalFormattingsXml(sheet.conditionalFormattings, styles, formattingPlan, formulaNames) +
|
|
65
|
+
dataValidationsXml(sheet.dataValidations, formulaNames) +
|
|
96
66
|
hyperlinksXml(hyperlinks) +
|
|
97
67
|
printOptionsXml(sheet.printOptions) +
|
|
98
68
|
pageMarginsXml(sheet.pageMargins) +
|
|
@@ -105,58 +75,13 @@ export function worksheetXml(sheet, tables, styles, references, hyperlinks, shar
|
|
|
105
75
|
refElement('legacyDrawingHF', references.legacyDrawingHFRelId) +
|
|
106
76
|
refElement('picture', references.backgroundRelId) +
|
|
107
77
|
tablePartsXml(tables) +
|
|
108
|
-
worksheetExtLstXml(sheet, references.slicerRelIds) +
|
|
78
|
+
worksheetExtLstXml(sheet, styles, references.slicerRelIds, formattingPlan, formulaNames) +
|
|
109
79
|
'</worksheet>');
|
|
110
80
|
}
|
|
111
|
-
|
|
112
|
-
const columnDefaults = new Map();
|
|
113
|
-
for (const { index, properties } of sheet.columns())
|
|
114
|
-
columnDefaults.set(index, properties ?? {});
|
|
115
|
-
return columnDefaults;
|
|
116
|
-
}
|
|
117
|
-
export function renderRow(entry, ctx) {
|
|
118
|
-
const { number, cells, properties } = entry;
|
|
119
|
-
const rendered = cells.filter((cell) => cell.value !== null || cellHasOwnStyle(cell));
|
|
120
|
-
const attrs = rowAttrs(properties, ctx.styles, ctx.collapsedSummaries.has(number));
|
|
121
|
-
if (rendered.length === 0 && attrs === '')
|
|
122
|
-
return { xml: '', minCol: Infinity, maxCol: -Infinity };
|
|
123
|
-
const rowFill = properties?.fill;
|
|
124
|
-
const cellsXml = rendered
|
|
125
|
-
.map((cell) => {
|
|
126
|
-
const style = ctx.styles.styleId(composeCellStyle(cell, rowFill, ctx.columnDefaults.get(cell.col)));
|
|
127
|
-
return cellXml(cell, style, ctx.sharedRoles.get(cell.address), ctx.sharedStrings);
|
|
128
|
-
})
|
|
129
|
-
.join('');
|
|
130
|
-
let minCol = Infinity;
|
|
131
|
-
let maxCol = -Infinity;
|
|
132
|
-
for (const cell of rendered) {
|
|
133
|
-
if (cell.col < minCol)
|
|
134
|
-
minCol = cell.col;
|
|
135
|
-
if (cell.col > maxCol)
|
|
136
|
-
maxCol = cell.col;
|
|
137
|
-
}
|
|
138
|
-
return { xml: `<row r="${number}"${attrs}>${cellsXml}</row>`, minCol, maxCol };
|
|
139
|
-
}
|
|
140
|
-
function composeCellStyle(cell, rowFill, colDef) {
|
|
141
|
-
const style = {};
|
|
142
|
-
for (const facet of CELL_STYLE_FACETS)
|
|
143
|
-
inheritFacet(style, facet, cell, colDef);
|
|
144
|
-
style.fill = cell.fill ?? rowFill ?? colDef?.fill;
|
|
145
|
-
style.numFmt = cell.numFmt ?? colDef?.numFmt ?? dateDefaultNumFmt(cell.value);
|
|
146
|
-
if (cell.quotePrefix !== undefined)
|
|
147
|
-
style.quotePrefix = cell.quotePrefix;
|
|
148
|
-
const xfId = cell[NAMED_STYLE_ID];
|
|
149
|
-
if (xfId !== undefined)
|
|
150
|
-
style.xfId = xfId;
|
|
151
|
-
return style;
|
|
152
|
-
}
|
|
153
|
-
function inheritFacet(target, key, cell, colDef) {
|
|
154
|
-
target[key] = cell[key] ?? colDef?.[key];
|
|
155
|
-
}
|
|
156
|
-
function worksheetExtLstXml(sheet, slicerRelIds) {
|
|
81
|
+
function worksheetExtLstXml(sheet, styles, slicerRelIds, formattingPlan, formulaNames) {
|
|
157
82
|
const exts = [
|
|
158
|
-
conditionalFormattingsExtXml(sheet.conditionalFormattings),
|
|
159
|
-
dataValidationsExtXml(sheet.dataValidations),
|
|
83
|
+
conditionalFormattingsExtXml(sheet.conditionalFormattings, styles, formattingPlan, formulaNames),
|
|
84
|
+
dataValidationsExtXml(sheet.dataValidations, formulaNames),
|
|
160
85
|
slicerListExtXml(slicerRelIds),
|
|
161
86
|
].filter((ext) => ext !== '');
|
|
162
87
|
return exts.length === 0 ? '' : `<extLst>${exts.join('')}</extLst>`;
|
|
@@ -168,30 +93,33 @@ function slicerListExtXml(slicerRelIds) {
|
|
|
168
93
|
return x14Ext(SLICER_LIST_EXT_URI, `<x14:slicerList>${slicers}</x14:slicerList>`);
|
|
169
94
|
}
|
|
170
95
|
function validateMerges(sheet) {
|
|
171
|
-
|
|
96
|
+
const [conflict] = mergesOverlappingTables(sheet.merges, sheet.tables);
|
|
97
|
+
if (conflict === undefined)
|
|
172
98
|
return;
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
if (overlaps) {
|
|
184
|
-
throw new AuthoringError(`merged range ${merge} overlaps table "${table.name}" (${table.range}): Excel forbids a merge inside a table`);
|
|
185
|
-
}
|
|
99
|
+
const { merge, table } = conflict;
|
|
100
|
+
throw new AuthoringError(`merged range ${merge} overlaps table ${quoted(table.name)} (${table.range}): Excel forbids a merge inside a table`);
|
|
101
|
+
}
|
|
102
|
+
function validateArrayRanges(sheet, flushed) {
|
|
103
|
+
const placements = [...(flushed?.formulas ?? [])];
|
|
104
|
+
for (const { cells } of sheet.rows()) {
|
|
105
|
+
for (const cell of cells) {
|
|
106
|
+
const placement = formulaPlacement(cell.address, cell.col, cell.row, cell.value);
|
|
107
|
+
if (placement !== undefined)
|
|
108
|
+
placements.push(placement);
|
|
186
109
|
}
|
|
187
110
|
}
|
|
111
|
+
const [conflict] = arrayRangeConflicts(placements);
|
|
112
|
+
if (conflict === undefined)
|
|
113
|
+
return;
|
|
114
|
+
const { array, other, kind } = conflict;
|
|
115
|
+
throw new AuthoringError(kind === 'formula-inside'
|
|
116
|
+
? `the array formula in ${array.address} fills ${quoted(array.arrayRef ?? '')}, which holds the formula in ${other}: Excel repairs a package with a formula inside another array formula's range`
|
|
117
|
+
: `the array formula in ${array.address} fills ${quoted(array.arrayRef ?? '')}, which shares cells with the range of the array formula in ${other}: Excel repairs a package whose array formula ranges overlap`);
|
|
188
118
|
}
|
|
189
119
|
function mergeCellsXml(merges) {
|
|
190
120
|
if (merges.length === 0)
|
|
191
121
|
return '';
|
|
192
|
-
const cells = merges
|
|
193
|
-
.map((range) => `<mergeCell ref="${escapeAttr(decodeRange(range).dimensions)}"/>`)
|
|
194
|
-
.join('');
|
|
122
|
+
const cells = merges.map((range) => `<mergeCell ref="${escapeAttr(range)}"/>`).join('');
|
|
195
123
|
return `<mergeCells count="${merges.length}">${cells}</mergeCells>`;
|
|
196
124
|
}
|
|
197
125
|
function refElement(tag, relId) {
|
|
@@ -203,45 +131,6 @@ function tablePartsXml(tables) {
|
|
|
203
131
|
const parts = tables.map(({ relId }) => `<tablePart r:id="${relId}"/>`).join('');
|
|
204
132
|
return `<tableParts count="${tables.length}">${parts}</tableParts>`;
|
|
205
133
|
}
|
|
206
|
-
export function worksheetRelsXml(tables, drawing, comments, threadedComments, printerSettings, background, hyperlinks, preservedReferences, pivots) {
|
|
207
|
-
const rels = [
|
|
208
|
-
...tables.map(({ relId, number }) => relationship(relId, REL.table, targetFromWorksheet(tablePart(number)))),
|
|
209
|
-
...pivots.map((pivot) => relationship(pivot.sheetRelId, REL.pivotTable, targetFromWorksheet(pivotTablePart(pivot.number)))),
|
|
210
|
-
...(drawing === null
|
|
211
|
-
? []
|
|
212
|
-
: [
|
|
213
|
-
relationship(drawing.relId, REL.drawing, targetFromWorksheet(drawingPart(drawing.number))),
|
|
214
|
-
]),
|
|
215
|
-
...(comments === null
|
|
216
|
-
? []
|
|
217
|
-
: [
|
|
218
|
-
relationship(comments.vmlRelId, REL.vmlDrawing, targetFromWorksheet(vmlDrawingPart(comments.number))),
|
|
219
|
-
relationship(comments.commentsRelId, REL.comments, targetFromWorksheet(commentsPart(comments.number))),
|
|
220
|
-
]),
|
|
221
|
-
...(threadedComments === null
|
|
222
|
-
? []
|
|
223
|
-
: [
|
|
224
|
-
relationship(threadedComments.relId, REL.threadedComment, targetFromWorksheet(threadedCommentsPart(threadedComments.number))),
|
|
225
|
-
]),
|
|
226
|
-
...(printerSettings === null
|
|
227
|
-
? []
|
|
228
|
-
: [
|
|
229
|
-
relationship(printerSettings.relId, REL.printerSettings, targetFromWorksheet(printerSettingsPart(printerSettings.number))),
|
|
230
|
-
]),
|
|
231
|
-
...(background === null
|
|
232
|
-
? []
|
|
233
|
-
: [
|
|
234
|
-
relationship(background.relId, REL.image, targetFromWorksheet(mediaPart(background.mediaNumber, background.extension))),
|
|
235
|
-
]),
|
|
236
|
-
...preservedReferences.map((reference) => relationship(reference.relId, reference.relType, escapeAttr(targetFromWorksheet(reference.entryPath)))),
|
|
237
|
-
...hyperlinks
|
|
238
|
-
.filter((link) => link.relId !== undefined && link.target !== undefined)
|
|
239
|
-
.map((link) => relationship(link.relId, REL.hyperlink, link.target, {
|
|
240
|
-
external: true,
|
|
241
|
-
})),
|
|
242
|
-
];
|
|
243
|
-
return relationshipsPart(rels);
|
|
244
|
-
}
|
|
245
134
|
const DEFAULT_ROW_HEIGHT = 15;
|
|
246
135
|
function sheetFormatPr(properties, outlineLevel) {
|
|
247
136
|
const rowHeight = properties.defaultRowHeight ?? DEFAULT_ROW_HEIGHT;
|
|
@@ -255,12 +144,6 @@ function sheetFormatPr(properties, outlineLevel) {
|
|
|
255
144
|
attrs += outlineAttr('outlineLevelRow', outlineLevel.row);
|
|
256
145
|
return `<sheetFormatPr${attrs}/>`;
|
|
257
146
|
}
|
|
258
|
-
function outlineAttr(name, level) {
|
|
259
|
-
if (level === undefined)
|
|
260
|
-
return '';
|
|
261
|
-
const text = numberText(level);
|
|
262
|
-
return level > 0 ? ` ${name}="${text}"` : '';
|
|
263
|
-
}
|
|
264
147
|
function maxColumnOutlineLevel(sheet) {
|
|
265
148
|
let max = 0;
|
|
266
149
|
for (const column of sheet.columns())
|
|
@@ -313,33 +196,35 @@ function colBody(properties, styles) {
|
|
|
313
196
|
}
|
|
314
197
|
return meaningful ? attrs : null;
|
|
315
198
|
}
|
|
316
|
-
function
|
|
317
|
-
if (
|
|
318
|
-
return
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
if (style !== 0)
|
|
329
|
-
attrs += ` s="${style}" customFormat="1"`;
|
|
330
|
-
return attrs;
|
|
199
|
+
function completeCollapsed(row, collapsedSummaries) {
|
|
200
|
+
if (!collapsedSummaries.has(row.number) || row.attrs.includes(' collapsed="1"')) {
|
|
201
|
+
return { number: row.number, xml: row.xml };
|
|
202
|
+
}
|
|
203
|
+
const open = rowOpenTag(row.number);
|
|
204
|
+
if (!row.xml.startsWith(open)) {
|
|
205
|
+
throw new InternalError(`flushed row ${row.number} does not open with ${quoted(open)}`);
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
number: row.number,
|
|
209
|
+
xml: `${open} collapsed="1"${row.xml.slice(open.length)}`,
|
|
210
|
+
};
|
|
331
211
|
}
|
|
332
|
-
function scanRowOutline(sheet) {
|
|
212
|
+
function scanRowOutline(sheet, flushed) {
|
|
333
213
|
const level = new Map();
|
|
334
214
|
const hidden = new Map();
|
|
335
215
|
let maxLevel = 0;
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
assertWritableNumber(rowLevel);
|
|
216
|
+
const note = (number, rowLevel, rowHidden) => {
|
|
217
|
+
assertWritableLevel(`row ${number} outlineLevel`, rowLevel);
|
|
339
218
|
level.set(number, rowLevel);
|
|
340
|
-
hidden.set(number,
|
|
219
|
+
hidden.set(number, rowHidden);
|
|
341
220
|
if (rowLevel > maxLevel)
|
|
342
221
|
maxLevel = rowLevel;
|
|
222
|
+
};
|
|
223
|
+
for (const [number, entry] of flushed?.rowOutline ?? []) {
|
|
224
|
+
note(number, entry.outlineLevel, entry.hidden);
|
|
225
|
+
}
|
|
226
|
+
for (const { number, properties } of sheet.rows()) {
|
|
227
|
+
note(number, properties?.outlineLevel ?? 0, properties?.hidden ?? false);
|
|
343
228
|
}
|
|
344
229
|
const levelOf = (row) => level.get(row) ?? 0;
|
|
345
230
|
const step = sheet.outline.summaryBelow === false ? 1 : -1;
|
|
@@ -348,7 +233,7 @@ function scanRowOutline(sheet) {
|
|
|
348
233
|
let detail = summary + step;
|
|
349
234
|
let sawDetail = false;
|
|
350
235
|
let allHidden = true;
|
|
351
|
-
while (levelOf(detail) > summaryLevel) {
|
|
236
|
+
while (level.get(detail) !== undefined && levelOf(detail) > summaryLevel) {
|
|
352
237
|
sawDetail = true;
|
|
353
238
|
if (!hidden.get(detail))
|
|
354
239
|
allHidden = false;
|
|
@@ -359,101 +244,3 @@ function scanRowOutline(sheet) {
|
|
|
359
244
|
}
|
|
360
245
|
return { collapsedSummaries, maxLevel };
|
|
361
246
|
}
|
|
362
|
-
function dateDefaultNumFmt(value) {
|
|
363
|
-
const date = value instanceof Date
|
|
364
|
-
? value
|
|
365
|
-
: (isFormulaValue(value) || isSharedFormulaValue(value)) && value.result instanceof Date
|
|
366
|
-
? value.result
|
|
367
|
-
: undefined;
|
|
368
|
-
return date !== undefined && !Number.isNaN(date.getTime()) ? DEFAULT_DATE_NUMFMT : undefined;
|
|
369
|
-
}
|
|
370
|
-
function cellXml(cell, style, shared, sharedStrings) {
|
|
371
|
-
const ref = cell.address;
|
|
372
|
-
const value = cell.value;
|
|
373
|
-
const s = style !== 0 ? ` s="${style}"` : '';
|
|
374
|
-
const formula = cellFormulaXml(ref, s, value, shared);
|
|
375
|
-
if (formula !== undefined)
|
|
376
|
-
return formula;
|
|
377
|
-
if (value instanceof Date) {
|
|
378
|
-
if (Number.isNaN(value.getTime()))
|
|
379
|
-
return `<c r="${ref}"${s}/>`;
|
|
380
|
-
return `<c r="${ref}"${s}><v>${numberText(dateToSerial(value))}</v></c>`;
|
|
381
|
-
}
|
|
382
|
-
if (typeof value === 'number') {
|
|
383
|
-
if (!Number.isFinite(value))
|
|
384
|
-
return `<c r="${ref}"${s}/>`;
|
|
385
|
-
return `<c r="${ref}"${s}><v>${numberText(value)}</v></c>`;
|
|
386
|
-
}
|
|
387
|
-
if (typeof value === 'boolean') {
|
|
388
|
-
return `<c r="${ref}"${s} t="b"><v>${value ? 1 : 0}</v></c>`;
|
|
389
|
-
}
|
|
390
|
-
if (typeof value === 'string') {
|
|
391
|
-
if (sharedStrings !== null) {
|
|
392
|
-
return `<c r="${ref}"${s} t="s"><v>${sharedStrings.intern(value)}</v></c>`;
|
|
393
|
-
}
|
|
394
|
-
return `<c r="${ref}"${s} t="inlineStr"><is>${textElement(value)}</is></c>`;
|
|
395
|
-
}
|
|
396
|
-
if (isRichTextValue(value)) {
|
|
397
|
-
if (sharedStrings !== null) {
|
|
398
|
-
return `<c r="${ref}"${s} t="s"><v>${sharedStrings.intern(value)}</v></c>`;
|
|
399
|
-
}
|
|
400
|
-
return `<c r="${ref}"${s} t="inlineStr"><is>${richTextRunsXml(value.richText)}</is></c>`;
|
|
401
|
-
}
|
|
402
|
-
if (isHyperlinkValue(value)) {
|
|
403
|
-
const label = typeof value.text === 'string'
|
|
404
|
-
? textElement(value.text)
|
|
405
|
-
: richTextRunsXml(value.text.richText);
|
|
406
|
-
return `<c r="${ref}"${s} t="inlineStr"><is>${label}</is></c>`;
|
|
407
|
-
}
|
|
408
|
-
if (isErrorValue(value)) {
|
|
409
|
-
return `<c r="${ref}"${s} t="e"><v>${value.error}</v></c>`;
|
|
410
|
-
}
|
|
411
|
-
if (value === null)
|
|
412
|
-
return `<c r="${ref}"${s}/>`;
|
|
413
|
-
throw new InternalError(`writing a ${detectValueType(value)} cell value has no arm: every CellValue kind is handled above`);
|
|
414
|
-
}
|
|
415
|
-
function cellFormulaXml(ref, s, value, shared) {
|
|
416
|
-
if (shared !== undefined) {
|
|
417
|
-
if (shared.ref !== undefined && isFormulaValue(value)) {
|
|
418
|
-
const f = `<f t="shared" ref="${shared.ref}" si="${shared.si}">${escapeText(mangleFormula(value.formula))}</f>`;
|
|
419
|
-
return formulaBodyXml(ref, s, f, value.result);
|
|
420
|
-
}
|
|
421
|
-
const result = isSharedFormulaValue(value) ? value.result : undefined;
|
|
422
|
-
return formulaBodyXml(ref, s, `<f t="shared" si="${shared.si}"/>`, result);
|
|
423
|
-
}
|
|
424
|
-
if (isDataTableFormulaValue(value)) {
|
|
425
|
-
const attrs = `ref="${escapeAttr(value.ref)}"` +
|
|
426
|
-
` dt2D="${value.dataTable2D ? 1 : 0}"` +
|
|
427
|
-
` dtr="${value.dataTableRow ? 1 : 0}"` +
|
|
428
|
-
textAttr('r1', value.r1) +
|
|
429
|
-
textAttr('r2', value.r2);
|
|
430
|
-
return formulaBodyXml(ref, s, `<f t="dataTable" ${attrs}/>`, value.result);
|
|
431
|
-
}
|
|
432
|
-
if (isFormulaValue(value)) {
|
|
433
|
-
return formulaBodyXml(ref, s, `<f>${escapeText(mangleFormula(value.formula))}</f>`, value.result);
|
|
434
|
-
}
|
|
435
|
-
return undefined;
|
|
436
|
-
}
|
|
437
|
-
function formulaBodyXml(ref, s, f, result) {
|
|
438
|
-
if (result === undefined || (typeof result === 'number' && !Number.isFinite(result))) {
|
|
439
|
-
return `<c r="${ref}"${s}>${f}</c>`;
|
|
440
|
-
}
|
|
441
|
-
if (typeof result === 'number') {
|
|
442
|
-
return `<c r="${ref}"${s}>${f}<v>${numberText(result)}</v></c>`;
|
|
443
|
-
}
|
|
444
|
-
if (typeof result === 'boolean') {
|
|
445
|
-
return `<c r="${ref}"${s} t="b">${f}<v>${result ? 1 : 0}</v></c>`;
|
|
446
|
-
}
|
|
447
|
-
if (typeof result === 'string') {
|
|
448
|
-
return `<c r="${ref}"${s} t="str">${f}<v>${escapeSpreadsheetText(result)}</v></c>`;
|
|
449
|
-
}
|
|
450
|
-
if (isErrorValue(result)) {
|
|
451
|
-
return `<c r="${ref}"${s} t="e">${f}<v>${result.error}</v></c>`;
|
|
452
|
-
}
|
|
453
|
-
if (result instanceof Date) {
|
|
454
|
-
if (Number.isNaN(result.getTime()))
|
|
455
|
-
return `<c r="${ref}"${s}>${f}</c>`;
|
|
456
|
-
return `<c r="${ref}"${s}>${f}<v>${numberText(dateToSerial(result))}</v></c>`;
|
|
457
|
-
}
|
|
458
|
-
throw new InternalError('writing a non-primitive formula result has no arm: every FormulaResult kind is handled above');
|
|
459
|
-
}
|
|
@@ -3,13 +3,17 @@ import type { AutoFilter } from '../../core/autofilter.ts';
|
|
|
3
3
|
import type { Cell } from '../../core/cell.ts';
|
|
4
4
|
import type { ConditionalFormatting } from '../../core/conditional-formatting.ts';
|
|
5
5
|
import type { DataValidation } from '../../core/data-validation.ts';
|
|
6
|
+
import type { DateEpoch } from '../../core/date.ts';
|
|
7
|
+
import type { Hyperlink } from '../../core/hyperlink.ts';
|
|
6
8
|
import type { AnchorPoint } from '../../core/image.ts';
|
|
9
|
+
import { INTERNAL } from '../../core/internal.ts';
|
|
7
10
|
import type { SheetProtectionOptions } from '../../core/protection.ts';
|
|
8
11
|
import { type CellValue } from '../../core/value.ts';
|
|
9
|
-
import { type AddImageOptions, type AddWorksheetOptions, Workbook } from '../../core/workbook.ts';
|
|
12
|
+
import { type AddImageOptions, type AddWorksheetOptions, type DefinedName, Workbook } from '../../core/workbook.ts';
|
|
10
13
|
import type { Worksheet } from '../../core/worksheet.ts';
|
|
14
|
+
import { WorkbookMetadataTable } from './cell-metadata.ts';
|
|
15
|
+
import { type FlushedSheet } from './row-xml.ts';
|
|
11
16
|
import type { StyleRegistry } from './styles.ts';
|
|
12
|
-
import { type FlushedSheet } from './write.ts';
|
|
13
17
|
/** Calculation settings applied to the streamed workbook. Mirrors the {@link Workbook} flags. */
|
|
14
18
|
export interface CalcProperties {
|
|
15
19
|
/** Ask the consumer to recalculate every formula on open: the OOXML `fullCalcOnLoad` flag. */
|
|
@@ -45,6 +49,13 @@ export type WorkbookStreamWriterOptions = SinkOptions & {
|
|
|
45
49
|
* same {@link WriteOptions.useSharedStrings} the buffered writer exposes. Off by default.
|
|
46
50
|
*/
|
|
47
51
|
readonly useSharedStrings?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Which date system this workbook's serials count in ({@link Workbook.dateEpoch}). A construction
|
|
54
|
+
* option rather than a settable property, unlike on the buffered writer: an eager writer serialises
|
|
55
|
+
* each row as it is committed, so a system changed part-way through would leave the rows before the
|
|
56
|
+
* change counting from a different day than the rows after it.
|
|
57
|
+
*/
|
|
58
|
+
readonly dateEpoch?: DateEpoch;
|
|
48
59
|
};
|
|
49
60
|
/**
|
|
50
61
|
* A row appended to a {@link WorksheetStreamWriter}. Style its cells through {@link cells}, then call
|
|
@@ -54,13 +65,25 @@ export type WorkbookStreamWriterOptions = SinkOptions & {
|
|
|
54
65
|
*/
|
|
55
66
|
export declare class StreamedRow {
|
|
56
67
|
#private;
|
|
57
|
-
constructor(
|
|
58
|
-
/** The
|
|
68
|
+
private constructor();
|
|
69
|
+
/** The sheet writer's construction channel, keyed like its own; see `core/internal.ts`. */
|
|
70
|
+
static readonly [INTERNAL]: StreamedRowFactory;
|
|
71
|
+
/** The cells `addRow` materialised, for styling before it is committed. A cell added to the row
|
|
72
|
+
* through {@link WorksheetStreamWriter.getCell} is not among them, and is committed all the same. */
|
|
59
73
|
get cells(): readonly Cell[];
|
|
60
74
|
/** Finalise the row: an eager writer serialises it now and releases its cells; otherwise a no-op.
|
|
61
75
|
* Committing twice is harmless: the second call does nothing rather than re-emitting the row. */
|
|
62
76
|
commit(): void;
|
|
63
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* How a {@link StreamedRow} comes into being. A row belongs to the sheet writer that numbered it, and
|
|
80
|
+
* only that writer knows which number is still open. `sheet` is `null` for a writer that keeps every
|
|
81
|
+
* row live until the workbook commits, where committing a row has nothing to do. Reached as
|
|
82
|
+
* `StreamedRow[INTERNAL]`.
|
|
83
|
+
*/
|
|
84
|
+
export interface StreamedRowFactory {
|
|
85
|
+
create(cells: readonly Cell[], sheet: WorksheetStreamWriter | null, number: number): StreamedRow;
|
|
86
|
+
}
|
|
64
87
|
/**
|
|
65
88
|
* A worksheet being written incrementally. Append rows with {@link addRow}/{@link addRows}, style
|
|
66
89
|
* cells through {@link getCell}, then {@link commit} to freeze it, after which any further mutation
|
|
@@ -68,7 +91,13 @@ export declare class StreamedRow {
|
|
|
68
91
|
*/
|
|
69
92
|
export declare class WorksheetStreamWriter {
|
|
70
93
|
#private;
|
|
71
|
-
constructor(
|
|
94
|
+
private constructor();
|
|
95
|
+
/**
|
|
96
|
+
* The workbook writer's construction channel. A static member keyed by the same symbol as the
|
|
97
|
+
* instance one below, so both halves of this class's internal wiring are reached the one way; see
|
|
98
|
+
* `core/internal.ts`.
|
|
99
|
+
*/
|
|
100
|
+
static readonly [INTERNAL]: WorksheetStreamWriterFactory;
|
|
72
101
|
/** The sheet's name. */
|
|
73
102
|
get name(): string;
|
|
74
103
|
/** The number of rows written so far. Spans gaps and formatted-only rows, like the model, and
|
|
@@ -78,16 +107,6 @@ export declare class WorksheetStreamWriter {
|
|
|
78
107
|
addRow(values: CellValue[]): StreamedRow;
|
|
79
108
|
/** Append a batch of rows in one call, each landing directly below the previous. */
|
|
80
109
|
addRows(rows: CellValue[][]): StreamedRow[];
|
|
81
|
-
/**
|
|
82
|
-
* Serialise an eagerly-committed row and release its cells from the model. Called by
|
|
83
|
-
* {@link StreamedRow.commit}; the row's `<row>` XML is retained (interned into the workbook's live
|
|
84
|
-
* style registry so its ids stay valid) and the cell graph is dropped, bounding peak memory.
|
|
85
|
-
*
|
|
86
|
-
* @throws {AuthoringError} if the row carries a shared-formula cell: a finished row cannot join the
|
|
87
|
-
* whole-sheet formula planning, so shared formulas must be authored through {@link getCell}.
|
|
88
|
-
*/
|
|
89
|
-
flushRow(number: number, cells: readonly Cell[]): void;
|
|
90
|
-
flushedSheet(): FlushedSheet | undefined;
|
|
91
110
|
/**
|
|
92
111
|
* Address a cell by its A1 reference to read or style it before the sheet is committed. The row it
|
|
93
112
|
* names must still be live: a row whose {@link StreamedRow.commit} has run is finished.
|
|
@@ -105,6 +124,12 @@ export declare class WorksheetStreamWriter {
|
|
|
105
124
|
addDataValidation(sqref: string, rule: DataValidation, options?: {
|
|
106
125
|
extended?: boolean;
|
|
107
126
|
}): void;
|
|
127
|
+
/**
|
|
128
|
+
* Put a hyperlink on a cell or a rectangle of cells before the sheet is committed; mirrors
|
|
129
|
+
* {@link Worksheet.addHyperlink}. A link lives beside the grid rather than in a row, so it may cover
|
|
130
|
+
* cells of a row that is already committed.
|
|
131
|
+
*/
|
|
132
|
+
addHyperlink(link: Hyperlink): void;
|
|
108
133
|
/**
|
|
109
134
|
* Attach a conditional formatting to a range before the sheet is committed. Like every other block,
|
|
110
135
|
* it lands in its schema-mandated slot, after `<mergeCells>` and before `<dataValidations>` and
|
|
@@ -139,6 +164,43 @@ export declare class WorksheetStreamWriter {
|
|
|
139
164
|
/** Whether the sheet has been committed. */
|
|
140
165
|
get committed(): boolean;
|
|
141
166
|
get model(): Worksheet;
|
|
167
|
+
readonly [INTERNAL]: WorksheetStreamWriterInternals;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* How a {@link WorksheetStreamWriter} comes into being. Its parameters are the writer's own plumbing
|
|
171
|
+
* -- the interning table its rows' style ids are assigned from, the epoch its dates are serialised
|
|
172
|
+
* against -- and a consumer supplies neither, because a consumer receives the sheet writer from
|
|
173
|
+
* {@link WorkbookStreamWriter.addWorksheet}. Reached as `WorksheetStreamWriter[INTERNAL]`.
|
|
174
|
+
*/
|
|
175
|
+
export interface WorksheetStreamWriterFactory {
|
|
176
|
+
create(sheet: Worksheet, eager: boolean, styles: StyleRegistry, cellMetadata: WorkbookMetadataTable, dateEpoch: DateEpoch, definedNames: readonly DefinedName[]): WorksheetStreamWriter;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* What the streaming writer's own machinery may do to a sheet writer that a caller may not, the same
|
|
180
|
+
* boundary `sheet[INTERNAL]` draws around the model. Reached as `writer[INTERNAL]`; see
|
|
181
|
+
* `core/internal.ts`.
|
|
182
|
+
*
|
|
183
|
+
* Both members were public until they were not. Neither is callable by anyone but this module, and
|
|
184
|
+
* between them they named seven writer-internal types -- `StyleRegistry`, `FlushedSheet` and the
|
|
185
|
+
* shapes those reach -- on a published class's signature, so a consumer could hold values whose types
|
|
186
|
+
* the package would not export. They carried `@unpublished` to record that, which is a note rather
|
|
187
|
+
* than a boundary; this is the boundary.
|
|
188
|
+
*/
|
|
189
|
+
export interface WorksheetStreamWriterInternals {
|
|
190
|
+
/**
|
|
191
|
+
* Serialise an eagerly-committed row and release its cells from the model. Called by
|
|
192
|
+
* {@link StreamedRow.commit}; the row's `<row>` XML is retained (interned into the workbook's live
|
|
193
|
+
* style registry so its ids stay valid) and the cell graph is dropped, bounding peak memory. The
|
|
194
|
+
* row is rendered from every cell the model holds for it, including any `getCell` added after
|
|
195
|
+
* `addRow` returned.
|
|
196
|
+
*
|
|
197
|
+
* @throws {AuthoringError} if the row carries a shared-formula cell: a finished row cannot join the
|
|
198
|
+
* whole-sheet formula planning, so shared formulas must be authored through
|
|
199
|
+
* {@link WorksheetStreamWriter.getCell}.
|
|
200
|
+
*/
|
|
201
|
+
flushRow(number: number): void;
|
|
202
|
+
/** The rows this writer flushed, or undefined if none. Handed to `buildPackageParts` at commit. */
|
|
203
|
+
flushedSheet(): FlushedSheet | undefined;
|
|
142
204
|
}
|
|
143
205
|
/**
|
|
144
206
|
* A workbook written incrementally to a Node stream. Add worksheets, append their rows, commit each
|
|
@@ -169,9 +231,18 @@ export declare class WorkbookStreamWriter {
|
|
|
169
231
|
/** Create a worksheet and append it to the workbook. */
|
|
170
232
|
addWorksheet(name: string, options?: AddWorksheetOptions): WorksheetStreamWriter;
|
|
171
233
|
/**
|
|
172
|
-
* Assemble the workbook into its package
|
|
173
|
-
*
|
|
174
|
-
*
|
|
234
|
+
* Assemble the workbook into its package and stream the bytes out. Every sheet is frozen first, so
|
|
235
|
+
* a row added after this rejects legibly. Idempotent only in that a second call throws rather than
|
|
236
|
+
* re-emitting.
|
|
237
|
+
*
|
|
238
|
+
* **What it resolves with, and why it can be `undefined`.** The archive is handed back only when
|
|
239
|
+
* somebody asked for it: when no sink was supplied, or when {@link stream} was touched, since a
|
|
240
|
+
* `PassThrough` nobody drained would otherwise be the only copy. A caller who passed `{filename}`
|
|
241
|
+
* or their own `stream` and never reached for {@link stream} gets `undefined`, and the package is
|
|
242
|
+
* never materialised as a whole: retaining every chunk to concatenate them at the end costs a
|
|
243
|
+
* second full-size buffer on top of the part map and the archive itself, which is exactly the
|
|
244
|
+
* memory the caller passed a sink to avoid. The type says so rather than the prose alone, because
|
|
245
|
+
* a promise that resolves with a value the caller was told to ignore is a promise they will use.
|
|
175
246
|
*
|
|
176
247
|
* If assembling or zipping the package fails, the returned promise rejects *and* every stream this
|
|
177
248
|
* writer was given or handed out is destroyed with that error. A caller piping {@link stream}, or
|
|
@@ -179,6 +250,6 @@ export declare class WorkbookStreamWriter {
|
|
|
179
250
|
* end; and it is an `error` rather than a clean `end` because the bytes written so far are a
|
|
180
251
|
* truncated package that must not be read as a whole one.
|
|
181
252
|
*/
|
|
182
|
-
commit(): Promise<Uint8Array>;
|
|
253
|
+
commit(): Promise<Uint8Array | undefined>;
|
|
183
254
|
}
|
|
184
255
|
export {};
|