@shbernal/ts-xlsx 2.1.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/bytes.d.ts +7 -0
- package/dist/bytes.js +22 -0
- package/dist/core/address.d.ts +60 -2
- package/dist/core/address.js +40 -24
- package/dist/core/autofilter.d.ts +5 -4
- package/dist/core/autofilter.js +34 -35
- package/dist/core/axis-handle.d.ts +10 -0
- package/dist/core/axis-handle.js +17 -0
- package/dist/core/cell.d.ts +25 -0
- package/dist/core/cell.js +9 -3
- package/dist/core/clone.d.ts +29 -0
- package/dist/core/clone.js +24 -0
- package/dist/core/color-resolution.js +2 -4
- package/dist/core/column.d.ts +5 -1
- package/dist/core/column.js +34 -35
- package/dist/core/comment-thread.js +2 -1
- package/dist/core/conditional-formatting-overlay.d.ts +2 -1
- package/dist/core/conditional-formatting-overlay.js +2 -2
- package/dist/core/conditional-formatting.d.ts +14 -6
- package/dist/core/conditional-formatting.js +45 -43
- package/dist/core/containers.d.ts +12 -0
- package/dist/core/containers.js +5 -0
- package/dist/core/data-validation-overlay.d.ts +2 -1
- package/dist/core/data-validation-overlay.js +4 -4
- package/dist/core/data-validation.d.ts +9 -3
- package/dist/core/data-validation.js +21 -18
- package/dist/core/date-format.d.ts +20 -0
- package/dist/core/date-format.js +160 -0
- package/dist/core/date.d.ts +43 -8
- package/dist/core/date.js +18 -2
- package/dist/core/formula.d.ts +26 -0
- package/dist/core/formula.js +20 -4
- package/dist/core/grid-edits.d.ts +2 -3
- package/dist/core/grid-edits.js +69 -70
- package/dist/core/grid-shift.d.ts +58 -9
- package/dist/core/grid-shift.js +26 -4
- package/dist/core/image.d.ts +14 -10
- package/dist/core/image.js +9 -9
- package/dist/core/internal.d.ts +8 -2
- package/dist/core/limits.d.ts +23 -0
- package/dist/core/limits.js +4 -0
- package/dist/core/merge-index.d.ts +31 -0
- package/dist/core/merge-index.js +60 -0
- package/dist/core/merge.d.ts +5 -14
- package/dist/core/merge.js +18 -27
- package/dist/core/page-setup.d.ts +72 -2
- package/dist/core/page-setup.js +34 -8
- package/dist/core/pivot-table.d.ts +1 -1
- package/dist/core/pivot-table.js +67 -53
- package/dist/core/protection.js +2 -11
- package/dist/core/range.js +34 -30
- package/dist/core/row-input.js +2 -2
- package/dist/core/row.d.ts +5 -1
- package/dist/core/row.js +22 -23
- package/dist/core/style.d.ts +134 -75
- package/dist/core/style.js +112 -53
- package/dist/core/table-style.d.ts +1 -1
- package/dist/core/table-style.js +4 -4
- package/dist/core/table.d.ts +28 -10
- package/dist/core/table.js +54 -39
- package/dist/core/theme.js +6 -5
- package/dist/core/used-extent.d.ts +44 -0
- package/dist/core/used-extent.js +102 -0
- package/dist/core/value.d.ts +9 -0
- package/dist/core/value.js +36 -34
- package/dist/core/workbook-media.d.ts +34 -0
- package/dist/core/workbook-media.js +44 -0
- package/dist/core/workbook-styles.d.ts +67 -1
- package/dist/core/workbook-vba.js +3 -2
- package/dist/core/workbook.d.ts +23 -2
- package/dist/core/workbook.js +24 -40
- package/dist/core/worksheet-comments.d.ts +2 -1
- package/dist/core/worksheet-comments.js +20 -13
- package/dist/core/worksheet-merges.d.ts +44 -0
- package/dist/core/worksheet-merges.js +59 -0
- package/dist/core/worksheet-model.d.ts +9 -1
- package/dist/core/worksheet-model.js +24 -9
- package/dist/core/worksheet.d.ts +72 -12
- package/dist/core/worksheet.js +68 -70
- package/dist/customui/ribbon.js +6 -7
- package/dist/entries/core.d.ts +18 -13
- package/dist/entries/core.js +12 -6
- package/dist/entries/xlsx.d.ts +1 -1
- package/dist/errors.d.ts +64 -0
- package/dist/errors.js +22 -0
- package/dist/hex.d.ts +8 -0
- package/dist/hex.js +3 -0
- package/dist/io/csv/delimiter.d.ts +9 -0
- package/dist/io/csv/delimiter.js +6 -0
- package/dist/io/csv/read.js +11 -4
- package/dist/io/csv/write.d.ts +9 -2
- package/dist/io/csv/write.js +9 -38
- package/dist/io/opc/inflate.js +15 -1
- package/dist/io/opc/namespaces.d.ts +16 -0
- package/dist/io/opc/namespaces.js +4 -0
- package/dist/io/opc/part-paths.d.ts +10 -0
- package/dist/io/opc/part-paths.js +16 -1
- package/dist/io/opc/read-opc.d.ts +69 -10
- package/dist/io/opc/read-opc.js +49 -55
- package/dist/io/opc/read-options.d.ts +5 -1
- package/dist/io/opc/rels.d.ts +1 -6
- package/dist/io/opc/rels.js +1 -4
- package/dist/io/opc/sniff-format.d.ts +3 -3
- package/dist/io/opc/sniff-format.js +2 -2
- package/dist/io/style/xf-style.d.ts +48 -2
- package/dist/io/style/xf-style.js +14 -0
- package/dist/io/xlsb/formula.d.ts +2 -2
- package/dist/io/xlsb/formula.js +49 -34
- package/dist/io/xlsb/primitives.js +8 -14
- package/dist/io/xlsb/ptg-functions.d.ts +19 -10
- package/dist/io/xlsb/ptg-functions.js +385 -596
- package/dist/io/xlsb/read-styles.js +50 -83
- package/dist/io/xlsb/read-worksheet.d.ts +20 -1
- package/dist/io/xlsb/read-worksheet.js +73 -89
- package/dist/io/xlsb/read.d.ts +6 -3
- package/dist/io/xlsb/read.js +47 -29
- package/dist/io/xlsb/record-stream.d.ts +30 -0
- package/dist/io/xlsb/record-stream.js +20 -0
- package/dist/io/xlsb/record-types.d.ts +1 -5
- package/dist/io/xlsb/record-types.js +1 -5
- package/dist/io/xlsx/cell-accumulator.d.ts +9 -2
- package/dist/io/xlsx/cell-accumulator.js +32 -9
- package/dist/io/xlsx/cell-style-resolution.d.ts +25 -0
- package/dist/io/xlsx/cell-style-resolution.js +29 -0
- package/dist/io/xlsx/cell-value.d.ts +5 -3
- package/dist/io/xlsx/cell-value.js +13 -15
- package/dist/io/xlsx/color-xml.js +3 -2
- package/dist/io/xlsx/column-budget.d.ts +26 -0
- package/dist/io/xlsx/column-budget.js +22 -0
- package/dist/io/xlsx/comments.d.ts +6 -2
- package/dist/io/xlsx/comments.js +36 -31
- package/dist/io/xlsx/conditional-formatting.d.ts +9 -5
- package/dist/io/xlsx/conditional-formatting.js +51 -46
- package/dist/io/xlsx/data-validation.d.ts +9 -7
- package/dist/io/xlsx/data-validation.js +38 -35
- package/dist/io/xlsx/edit-vba.d.ts +7 -2
- package/dist/io/xlsx/edit-vba.js +15 -29
- package/dist/io/xlsx/font-xml.d.ts +7 -0
- package/dist/io/xlsx/font-xml.js +104 -0
- package/dist/io/xlsx/hyperlinks.d.ts +41 -7
- package/dist/io/xlsx/hyperlinks.js +40 -28
- package/dist/io/xlsx/images.js +24 -25
- package/dist/io/xlsx/namespaces.d.ts +16 -0
- package/dist/io/xlsx/namespaces.js +7 -0
- package/dist/io/xlsx/package-plan.d.ts +23 -3
- package/dist/io/xlsx/package-plan.js +66 -25
- package/dist/io/xlsx/part-names.d.ts +41 -0
- package/dist/io/xlsx/part-names.js +46 -0
- package/dist/io/xlsx/pivot.js +8 -7
- package/dist/io/xlsx/read-parts.d.ts +59 -0
- package/dist/io/xlsx/read-parts.js +252 -0
- package/dist/io/xlsx/read-pivot.js +3 -1
- package/dist/io/xlsx/read-repair.d.ts +26 -0
- package/dist/io/xlsx/read-repair.js +39 -0
- package/dist/io/xlsx/{rich-runs.d.ts → read-rich-runs.d.ts} +1 -1
- package/dist/io/xlsx/{rich-runs.js → read-rich-runs.js} +7 -3
- package/dist/io/xlsx/read-rows.d.ts +18 -5
- package/dist/io/xlsx/read-rows.js +50 -37
- package/dist/io/xlsx/read-shared-strings.js +5 -3
- package/dist/io/xlsx/read-styles.d.ts +1 -6
- package/dist/io/xlsx/read-styles.js +65 -109
- package/dist/io/xlsx/read-workbook-xml.d.ts +36 -0
- package/dist/io/xlsx/read-workbook-xml.js +170 -0
- package/dist/io/xlsx/read-worksheet.d.ts +11 -1
- package/dist/io/xlsx/read-worksheet.js +51 -193
- package/dist/io/xlsx/read.d.ts +5 -13
- package/dist/io/xlsx/read.js +111 -436
- package/dist/io/xlsx/rich-text.js +1 -1
- package/dist/io/xlsx/row-position.d.ts +18 -0
- package/dist/io/xlsx/row-position.js +11 -0
- package/dist/io/xlsx/row-xml.d.ts +128 -0
- package/dist/io/xlsx/row-xml.js +203 -0
- package/dist/io/xlsx/shared-formulas.js +2 -2
- package/dist/io/xlsx/sheet-properties.d.ts +10 -1
- package/dist/io/xlsx/sheet-properties.js +166 -37
- package/dist/io/xlsx/style-elements.d.ts +43 -0
- package/dist/io/xlsx/style-elements.js +156 -0
- package/dist/io/xlsx/styles.d.ts +12 -3
- package/dist/io/xlsx/styles.js +5 -204
- package/dist/io/xlsx/tables.js +11 -14
- package/dist/io/xlsx/theme-xml.d.ts +26 -4
- package/dist/io/xlsx/theme-xml.js +107 -69
- package/dist/io/xlsx/threaded-comments.d.ts +8 -10
- package/dist/io/xlsx/threaded-comments.js +3 -1
- package/dist/io/xlsx/workbook-xml.d.ts +54 -4
- package/dist/io/xlsx/workbook-xml.js +84 -57
- package/dist/io/xlsx/worksheet-xml.d.ts +23 -70
- package/dist/io/xlsx/worksheet-xml.js +59 -242
- package/dist/io/xlsx/write-stream.d.ts +71 -16
- package/dist/io/xlsx/write-stream.js +79 -41
- package/dist/io/xlsx/write.d.ts +6 -2
- package/dist/io/xlsx/write.js +217 -153
- package/dist/rel-type.d.ts +16 -0
- package/dist/rel-type.js +6 -0
- package/dist/token-set.d.ts +28 -0
- package/dist/token-set.js +7 -0
- package/dist/vba/bytes.d.ts +14 -5
- package/dist/vba/bytes.js +16 -6
- package/dist/vba/cfb-format.d.ts +32 -0
- package/dist/vba/cfb-format.js +13 -0
- package/dist/vba/cfb-writer.d.ts +9 -0
- package/dist/vba/cfb-writer.js +28 -25
- package/dist/vba/cfb.d.ts +13 -1
- package/dist/vba/cfb.js +73 -57
- package/dist/vba/codepage.js +2 -1
- package/dist/vba/errors.d.ts +7 -0
- package/dist/vba/ms-ovba.js +79 -23
- package/dist/vba/project-editor.js +35 -40
- package/dist/vba/project.d.ts +11 -1
- package/dist/vba/project.js +40 -21
- package/dist/vba/vba-encoding.js +5 -6
- package/dist/xml/xml-attrs.d.ts +37 -0
- package/dist/xml/xml-attrs.js +30 -0
- package/dist/xml/xml-chars.d.ts +40 -0
- package/dist/xml/xml-chars.js +12 -0
- package/dist/xml/xml-namespaces.d.ts +31 -0
- package/dist/xml/xml-namespaces.js +50 -0
- package/dist/xml/xml-read.d.ts +128 -81
- package/dist/xml/xml-read.js +161 -178
- package/dist/xml/xml-scan.d.ts +78 -0
- package/dist/xml/xml-scan.js +180 -0
- package/dist/xml/xml.d.ts +29 -28
- package/dist/xml/xml.js +24 -24
- package/package.json +13 -9
package/README.md
CHANGED
|
@@ -149,12 +149,15 @@ const writer = new WorkbookStreamWriter();
|
|
|
149
149
|
const out = writer.addWorksheet('Big');
|
|
150
150
|
for (let i = 1; i <= 1_000_000; i++) out.addRow([i, i * i]).commit();
|
|
151
151
|
out.commit();
|
|
152
|
-
const packaged
|
|
152
|
+
const packaged = await writer.commit(); // Uint8Array here; also delivered via writer.stream
|
|
153
153
|
```
|
|
154
154
|
|
|
155
155
|
The streaming writer is asynchronous where the buffered path is synchronous: `commit()`
|
|
156
156
|
resolves to the package bytes and simultaneously pipes them through `writer.stream` (a Node
|
|
157
157
|
`Readable`), so `writer.stream.pipe(res)` streams a workbook straight to an HTTP response.
|
|
158
|
+
Hand the writer its own sink instead (`{stream}` or `{filename}`) and never touch
|
|
159
|
+
`writer.stream`, and `commit()` resolves with `undefined`: the archive goes to the sink and is
|
|
160
|
+
never assembled as one object, which is what passing a sink was for.
|
|
158
161
|
|
|
159
162
|
## Writing without blocking the event loop
|
|
160
163
|
|
package/dist/bytes.d.ts
CHANGED
|
@@ -22,3 +22,10 @@ export declare function concat(chunks: readonly Uint8Array[], size?: number): Ui
|
|
|
22
22
|
* hash, so the loop below is not on any path where its cost is measurable.
|
|
23
23
|
*/
|
|
24
24
|
export declare function toBase64(bytes: Uint8Array): string;
|
|
25
|
+
/** A string's UTF-16LE bytes, code unit by code unit, with lone surrogates carried through. */
|
|
26
|
+
export declare function utf16leBytes(text: string): Uint8Array;
|
|
27
|
+
/**
|
|
28
|
+
* Decode UTF-16LE code units. A trailing odd byte is dropped: these fields are length-prefixed by
|
|
29
|
+
* their producer, and half a code unit carries nothing to decode.
|
|
30
|
+
*/
|
|
31
|
+
export declare function decodeUtf16le(bytes: Uint8Array): string;
|
package/dist/bytes.js
CHANGED
|
@@ -32,3 +32,25 @@ export function toBase64(bytes) {
|
|
|
32
32
|
}
|
|
33
33
|
return out;
|
|
34
34
|
}
|
|
35
|
+
export function utf16leBytes(text) {
|
|
36
|
+
const bytes = new Uint8Array(text.length * 2);
|
|
37
|
+
for (let i = 0; i < text.length; i++) {
|
|
38
|
+
const unit = text.charCodeAt(i);
|
|
39
|
+
bytes[i * 2] = unit & 0xff;
|
|
40
|
+
bytes[i * 2 + 1] = unit >>> 8;
|
|
41
|
+
}
|
|
42
|
+
return bytes;
|
|
43
|
+
}
|
|
44
|
+
const CHARS_PER_BATCH = 4096;
|
|
45
|
+
export function decodeUtf16le(bytes) {
|
|
46
|
+
let text = '';
|
|
47
|
+
let batch = [];
|
|
48
|
+
for (let i = 0; i + 1 < bytes.length; i += 2) {
|
|
49
|
+
batch.push(bytes[i] | (bytes[i + 1] << 8));
|
|
50
|
+
if (batch.length === CHARS_PER_BATCH) {
|
|
51
|
+
text += String.fromCharCode(...batch);
|
|
52
|
+
batch = [];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return batch.length > 0 ? text + String.fromCharCode(...batch) : text;
|
|
56
|
+
}
|
package/dist/core/address.d.ts
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
export declare const MAX_COLUMN = 16384;
|
|
3
3
|
/** Excel's row bound: 1 through 1048576. The other axis of {@link MAX_COLUMN}. */
|
|
4
4
|
export declare const MAX_ROW = 1048576;
|
|
5
|
+
/**
|
|
6
|
+
* The same two bounds, zero-based: the last valid *index* on each axis.
|
|
7
|
+
*
|
|
8
|
+
* BIFF12 counts from zero throughout, so its reader and its formula decoder both need these, and both
|
|
9
|
+
* were deriving them privately. Two derivations of one fact is one fewer than three, but it is still
|
|
10
|
+
* the shape where a change to a limit reaches some of its consequences. The subtraction belongs beside
|
|
11
|
+
* the number it subtracts from.
|
|
12
|
+
*/
|
|
13
|
+
export declare const MAX_COLUMN_INDEX: number;
|
|
14
|
+
export declare const MAX_ROW_INDEX: number;
|
|
15
|
+
/**
|
|
16
|
+
* Refuse a coordinate that names no position on the grid.
|
|
17
|
+
*
|
|
18
|
+
* @throws {RangeError} unless `value` is an integer within the axis's bounds.
|
|
19
|
+
*/
|
|
20
|
+
export declare function assertAxisInBounds(axis: 'row' | 'column', value: number): void;
|
|
5
21
|
/** @throws {RangeError} unless `n` is an integer in `1..MAX_COLUMN`. */
|
|
6
22
|
export declare function assertColumnInBounds(n: number): void;
|
|
7
23
|
/** @throws {RangeError} unless `n` is an integer in `1..MAX_ROW`. */
|
|
@@ -56,7 +72,19 @@ export interface RangeAddress {
|
|
|
56
72
|
*
|
|
57
73
|
* @throws {RangeError} unless `n` is an integer in `1..MAX_COLUMN`. */
|
|
58
74
|
export declare function numberToColumn(n: number): string;
|
|
59
|
-
/**
|
|
75
|
+
/**
|
|
76
|
+
* Convert column letters to a 1-based number (`"A" → 1`, `"AA" → 27`), or `undefined` when they name
|
|
77
|
+
* no column that can exist: not letters at all, or past `XFD` (`"ZZZ"` is well-formed and is column
|
|
78
|
+
* 18278, which the grid does not have). The tolerant half of the pair the module header describes,
|
|
79
|
+
* for a caller reading a file rather than a caller's own argument.
|
|
80
|
+
*/
|
|
81
|
+
export declare function tryColumnToNumber(letters: string): number | undefined;
|
|
82
|
+
/**
|
|
83
|
+
* Convert column letters to a 1-based number (`"A" → 1`, `"AA" → 27`).
|
|
84
|
+
*
|
|
85
|
+
* @throws {RangeError} if the letters are malformed or name a column past `XFD`. The two are
|
|
86
|
+
* separate messages because a caller fixes them differently.
|
|
87
|
+
*/
|
|
60
88
|
export declare function columnToNumber(letters: string): number;
|
|
61
89
|
/**
|
|
62
90
|
* One corner of a range, as its reference text. An axis the corner omits contributes nothing, so a
|
|
@@ -67,6 +95,17 @@ export declare function columnToNumber(letters: string): number;
|
|
|
67
95
|
* The unbounded counterpart to {@link encodeAddress}, which names one cell and so requires both.
|
|
68
96
|
*/
|
|
69
97
|
export declare function encodeCornerRef(col: number | undefined, row: number | undefined): string;
|
|
98
|
+
/**
|
|
99
|
+
* A bounded rectangle as its canonical `tl:br` A1 range, `"B2:D5"`. A one-cell rectangle still reads
|
|
100
|
+
* as `"B2:B2"`, which is the form Excel writes and the form every consumer of these refs parses.
|
|
101
|
+
*
|
|
102
|
+
* The rendering half of {@link boundedRect}, and it belongs beside it for the same reason: ten sites
|
|
103
|
+
* spelled `` `${encodeAddress(left, top)}:${encodeAddress(right, bottom)}` `` by hand, and the risk in
|
|
104
|
+
* that expression is not its length but its argument order. `encodeAddress` takes column first and a
|
|
105
|
+
* rectangle names its rows first, so the two orders are transposed with respect to each other at every
|
|
106
|
+
* one of those sites.
|
|
107
|
+
*/
|
|
108
|
+
export declare function encodeRect(rect: GridRect): string;
|
|
70
109
|
/**
|
|
71
110
|
* Decode a single cell/row/column reference into `{address, col, row}`. Anchoring
|
|
72
111
|
* `$` signs are accepted and dropped; an absent axis is `undefined`.
|
|
@@ -98,6 +137,19 @@ export declare function decodeCellRef(reference: string): CellPosition;
|
|
|
98
137
|
* there is nothing here".
|
|
99
138
|
*/
|
|
100
139
|
export declare function tryDecodeCellRef(reference: string): CellPosition | undefined;
|
|
140
|
+
/**
|
|
141
|
+
* Narrow a decoded range to a {@link GridRect}, or `undefined` when either axis is unbounded.
|
|
142
|
+
*
|
|
143
|
+
* A whole-column reference (`A:A`) and a whole-row one (`1:1`) are legal range references whose
|
|
144
|
+
* corners are partly absent, so every caller that needs a real rectangle has to test all four. Doing
|
|
145
|
+
* that in seven places is the other half of the convention `GridRect` already exists to state once:
|
|
146
|
+
* the shape is declared here, and so is the one narrowing that produces it.
|
|
147
|
+
*
|
|
148
|
+
* A caller wanting to say something *different* about each axis (a `Range` refuses `A:A` and `1:1`
|
|
149
|
+
* with two distinct messages) still tests them separately, and one that only cares about the axis it
|
|
150
|
+
* is splicing still tests only that one. Neither is this question.
|
|
151
|
+
*/
|
|
152
|
+
export declare function boundedRect(range: RangeAddress): GridRect | undefined;
|
|
101
153
|
/**
|
|
102
154
|
* {@link decodeRange} for a reference that came out of a file: `undefined` for anything that does
|
|
103
155
|
* not name a region that can exist. The sibling of {@link tryDecodeCellRef} on the other arity: a
|
|
@@ -114,5 +166,11 @@ export declare function tryDecodeRange(reference: string): RangeAddress | undefi
|
|
|
114
166
|
* corners coincide.
|
|
115
167
|
*/
|
|
116
168
|
export declare function decodeRange(reference: string): RangeAddress;
|
|
117
|
-
/**
|
|
169
|
+
/**
|
|
170
|
+
* Encode a 1-based `col`/`row` pair into its canonical A1 address (`"B2"`).
|
|
171
|
+
*
|
|
172
|
+
* Both axes go through the shared guard. The column already did, through `numberToColumn`; the row
|
|
173
|
+
* checked only its lower bound in a message of its own, so `encodeAddress(1, 1048577)` produced an
|
|
174
|
+
* address naming a row Excel has no reference for while `encodeAddress(16385, 1)` refused.
|
|
175
|
+
*/
|
|
118
176
|
export declare function encodeAddress(col: number, row: number): string;
|
package/dist/core/address.js
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
|
+
import { quoted } from '../errors.js';
|
|
1
2
|
export const MAX_COLUMN = 16384;
|
|
2
3
|
export const MAX_ROW = 1048576;
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
export const MAX_COLUMN_INDEX = MAX_COLUMN - 1;
|
|
5
|
+
export const MAX_ROW_INDEX = MAX_ROW - 1;
|
|
6
|
+
const AXIS_BOUND = { row: MAX_ROW, column: MAX_COLUMN };
|
|
7
|
+
export function assertAxisInBounds(axis, value) {
|
|
8
|
+
const bound = AXIS_BOUND[axis];
|
|
9
|
+
if (!Number.isInteger(value) || value < 1 || value > bound) {
|
|
10
|
+
throw new RangeError(`${axis} ${value} is out of bounds: Excel supports 1..${bound}`);
|
|
6
11
|
}
|
|
7
12
|
}
|
|
13
|
+
export function assertColumnInBounds(n) {
|
|
14
|
+
assertAxisInBounds('column', n);
|
|
15
|
+
}
|
|
8
16
|
export function assertRowInBounds(n) {
|
|
9
|
-
|
|
10
|
-
throw new RangeError(`row ${n} is out of bounds: Excel supports 1..${MAX_ROW}`);
|
|
11
|
-
}
|
|
17
|
+
assertAxisInBounds('row', n);
|
|
12
18
|
}
|
|
13
19
|
export function rectsOverlap(a, b) {
|
|
14
20
|
return a.left <= b.right && b.left <= a.right && a.top <= b.bottom && b.top <= a.bottom;
|
|
@@ -26,38 +32,43 @@ export function numberToColumn(n) {
|
|
|
26
32
|
}
|
|
27
33
|
return letters;
|
|
28
34
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
const COLUMN_LETTERS = /^[A-Z]{1,3}$/;
|
|
36
|
+
export function tryColumnToNumber(letters) {
|
|
37
|
+
if (!COLUMN_LETTERS.test(letters))
|
|
38
|
+
return undefined;
|
|
33
39
|
let n = 0;
|
|
34
40
|
for (let i = 0; i < letters.length; i++) {
|
|
35
|
-
|
|
36
|
-
if (code < 65 || code > 90) {
|
|
37
|
-
throw new RangeError(`invalid column letters: "${letters}"`);
|
|
38
|
-
}
|
|
39
|
-
n = n * 26 + (code - 64);
|
|
41
|
+
n = n * 26 + (letters.charCodeAt(i) - 64);
|
|
40
42
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
return n > MAX_COLUMN ? undefined : n;
|
|
44
|
+
}
|
|
45
|
+
export function columnToNumber(letters) {
|
|
46
|
+
const n = tryColumnToNumber(letters);
|
|
47
|
+
if (n !== undefined)
|
|
48
|
+
return n;
|
|
49
|
+
if (!COLUMN_LETTERS.test(letters)) {
|
|
50
|
+
throw new RangeError(`invalid column letters: ${quoted(letters)}`);
|
|
43
51
|
}
|
|
44
|
-
|
|
52
|
+
throw new RangeError(`column ${quoted(letters)} is out of bounds: Excel supports up to ${MAX_COLUMN} (XFD)`);
|
|
45
53
|
}
|
|
46
54
|
export function encodeCornerRef(col, row) {
|
|
47
55
|
return `${col !== undefined ? numberToColumn(col) : ''}${row !== undefined ? row : ''}`;
|
|
48
56
|
}
|
|
57
|
+
export function encodeRect(rect) {
|
|
58
|
+
return `${encodeAddress(rect.left, rect.top)}:${encodeAddress(rect.right, rect.bottom)}`;
|
|
59
|
+
}
|
|
49
60
|
function makeCellAddress(col, row) {
|
|
50
61
|
return { address: encodeCornerRef(col, row), col, row };
|
|
51
62
|
}
|
|
52
63
|
export function decodeAddress(reference) {
|
|
53
64
|
const match = SINGLE_REF.exec(reference);
|
|
54
65
|
if (!match) {
|
|
55
|
-
throw new SyntaxError(`invalid cell reference:
|
|
66
|
+
throw new SyntaxError(`invalid cell reference: ${quoted(reference)}`);
|
|
56
67
|
}
|
|
57
68
|
const letters = match[1] ?? '';
|
|
58
69
|
const digits = match[2] ?? '';
|
|
59
70
|
if (letters.length === 0 && digits.length === 0) {
|
|
60
|
-
throw new SyntaxError(`invalid cell reference:
|
|
71
|
+
throw new SyntaxError(`invalid cell reference: ${quoted(reference)}`);
|
|
61
72
|
}
|
|
62
73
|
const col = letters.length > 0 ? columnToNumber(letters) : undefined;
|
|
63
74
|
const row = digits.length > 0 ? Number.parseInt(digits, 10) : undefined;
|
|
@@ -66,7 +77,7 @@ export function decodeAddress(reference) {
|
|
|
66
77
|
export function decodeCellRef(reference) {
|
|
67
78
|
const { col, row } = decodeAddress(reference);
|
|
68
79
|
if (col === undefined || row === undefined) {
|
|
69
|
-
throw new SyntaxError(
|
|
80
|
+
throw new SyntaxError(`${quoted(reference)} is not a single-cell reference: it omits a column or row`);
|
|
70
81
|
}
|
|
71
82
|
return { col, row };
|
|
72
83
|
}
|
|
@@ -83,6 +94,13 @@ export function tryDecodeCellRef(reference) {
|
|
|
83
94
|
}
|
|
84
95
|
return rowCanExist(position.row) ? position : undefined;
|
|
85
96
|
}
|
|
97
|
+
export function boundedRect(range) {
|
|
98
|
+
const { top, left, bottom, right } = range;
|
|
99
|
+
if (top === undefined || left === undefined || bottom === undefined || right === undefined) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
return { top, left, bottom, right };
|
|
103
|
+
}
|
|
86
104
|
export function tryDecodeRange(reference) {
|
|
87
105
|
let range;
|
|
88
106
|
try {
|
|
@@ -125,8 +143,6 @@ export function decodeRange(reference) {
|
|
|
125
143
|
};
|
|
126
144
|
}
|
|
127
145
|
export function encodeAddress(col, row) {
|
|
128
|
-
|
|
129
|
-
throw new RangeError(`row ${row} is out of bounds: rows start at 1`);
|
|
130
|
-
}
|
|
146
|
+
assertRowInBounds(row);
|
|
131
147
|
return `${numberToColumn(col)}${row}`;
|
|
132
148
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type AxisSplice } from './grid-shift.ts';
|
|
1
2
|
/**
|
|
2
3
|
* A worksheet's autofilter: the filtered region plus any per-column criteria narrowing it. A bare
|
|
3
4
|
* range (no columns) is just the header-row dropdowns Excel draws; adding {@link FilterColumn}s
|
|
@@ -43,7 +44,7 @@ export interface CustomFilterPredicate {
|
|
|
43
44
|
}
|
|
44
45
|
export type CustomFilterOperator = 'equal' | 'notEqual' | 'lessThan' | 'lessThanOrEqual' | 'greaterThan' | 'greaterThanOrEqual';
|
|
45
46
|
/** Narrow a raw `operator` attribute to a known {@link CustomFilterOperator}. */
|
|
46
|
-
export declare
|
|
47
|
+
export declare const isCustomFilterOperator: (value: string) => value is CustomFilterOperator;
|
|
47
48
|
/**
|
|
48
49
|
* Validate and normalise a settable autofilter into its canonical stored form. A bare range string
|
|
49
50
|
* is the common case (dropdowns, no criteria); an {@link AutoFilter} object carries per-column
|
|
@@ -54,8 +55,8 @@ export declare function isCustomFilterOperator(value: string): value is CustomFi
|
|
|
54
55
|
*/
|
|
55
56
|
export declare function canonicalizeAutoFilter(input: string | AutoFilter): AutoFilter;
|
|
56
57
|
/**
|
|
57
|
-
* Re-anchor a filter through a splice
|
|
58
|
-
*
|
|
58
|
+
* Re-anchor a filter through a splice, or drop it (`undefined`) when the splice deleted every line
|
|
59
|
+
* it covered.
|
|
59
60
|
*
|
|
60
61
|
* A row splice only moves the range. A column splice moves its left edge too, and a criterion is
|
|
61
62
|
* addressed by its offset from that edge rather than by an absolute column, so every offset is
|
|
@@ -63,4 +64,4 @@ export declare function canonicalizeAutoFilter(input: string | AutoFilter): Auto
|
|
|
63
64
|
* Left alone, those offsets would keep their old numbers and silently re-point each filter at a
|
|
64
65
|
* neighbouring column.
|
|
65
66
|
*/
|
|
66
|
-
export declare function shiftAutoFilter(filter: AutoFilter,
|
|
67
|
+
export declare function shiftAutoFilter(filter: AutoFilter, splice: AxisSplice): AutoFilter | undefined;
|
package/dist/core/autofilter.js
CHANGED
|
@@ -1,28 +1,27 @@
|
|
|
1
|
-
import { AuthoringError } from '../errors.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
1
|
+
import { AuthoringError, quoted } from '../errors.js';
|
|
2
|
+
import { tokenSet } from '../token-set.js';
|
|
3
|
+
import { boundedRect, decodeRange, encodeRect } from './address.js';
|
|
4
|
+
import { isDeletedSpan, shiftIndex, shiftRect } from './grid-shift.js';
|
|
5
|
+
export const isCustomFilterOperator = tokenSet({
|
|
5
6
|
equal: true,
|
|
6
7
|
notEqual: true,
|
|
7
8
|
lessThan: true,
|
|
8
9
|
lessThanOrEqual: true,
|
|
9
10
|
greaterThan: true,
|
|
10
11
|
greaterThanOrEqual: true,
|
|
11
|
-
};
|
|
12
|
-
export function isCustomFilterOperator(value) {
|
|
13
|
-
return Object.hasOwn(CUSTOM_FILTER_OPERATORS, value);
|
|
14
|
-
}
|
|
12
|
+
});
|
|
15
13
|
export function canonicalizeAutoFilter(input) {
|
|
16
14
|
const ref = typeof input === 'string' ? input : input.ref;
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
const decoded = decodeRange(ref);
|
|
16
|
+
const rect = boundedRect(decoded);
|
|
17
|
+
if (rect === undefined) {
|
|
18
|
+
throw new AuthoringError(`autofilter range ${quoted(ref)} must be a bounded rectangle`);
|
|
20
19
|
}
|
|
21
20
|
if (typeof input === 'string')
|
|
22
|
-
return { ref: dimensions, columns: [] };
|
|
23
|
-
const width = right - left + 1;
|
|
21
|
+
return { ref: decoded.dimensions, columns: [] };
|
|
22
|
+
const width = rect.right - rect.left + 1;
|
|
24
23
|
return {
|
|
25
|
-
ref: dimensions,
|
|
24
|
+
ref: decoded.dimensions,
|
|
26
25
|
columns: input.columns.map((column) => canonicalizeColumn(column, width)),
|
|
27
26
|
};
|
|
28
27
|
}
|
|
@@ -30,35 +29,35 @@ function canonicalizeColumn(column, width) {
|
|
|
30
29
|
if (!Number.isInteger(column.colId) || column.colId < 0 || column.colId >= width) {
|
|
31
30
|
throw new AuthoringError(`autofilter colId ${column.colId} is outside the filter range`);
|
|
32
31
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
const criteria = column.criteria;
|
|
33
|
+
if (criteria.kind === 'values') {
|
|
34
|
+
return { colId: column.colId, criteria: { ...criteria, values: [...criteria.values] } };
|
|
35
|
+
}
|
|
36
|
+
const count = criteria.predicates.length;
|
|
37
|
+
if (count < 1 || count > 2) {
|
|
38
|
+
throw new AuthoringError(`a custom filter needs one or two predicates, got ${count}`);
|
|
38
39
|
}
|
|
39
|
-
return
|
|
40
|
+
return {
|
|
41
|
+
colId: column.colId,
|
|
42
|
+
criteria: { ...criteria, predicates: criteria.predicates.map((predicate) => ({ ...predicate })) },
|
|
43
|
+
};
|
|
40
44
|
}
|
|
41
|
-
export function shiftAutoFilter(filter,
|
|
42
|
-
const
|
|
43
|
-
if (
|
|
45
|
+
export function shiftAutoFilter(filter, splice) {
|
|
46
|
+
const rect = boundedRect(decodeRange(filter.ref));
|
|
47
|
+
if (rect === undefined)
|
|
44
48
|
return filter;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (isDeletedSpan(lo, hi, start, count))
|
|
49
|
+
const moved = shiftRect(rect, splice);
|
|
50
|
+
if (moved === undefined)
|
|
48
51
|
return undefined;
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
if (axis === 'row') {
|
|
52
|
-
const ref = `${encodeAddress(left, movedLo)}:${encodeAddress(right, movedHi)}`;
|
|
52
|
+
const ref = encodeRect(moved);
|
|
53
|
+
if (splice.axis === 'row')
|
|
53
54
|
return { ref, columns: filter.columns };
|
|
54
|
-
}
|
|
55
|
-
const ref = `${encodeAddress(movedLo, top)}:${encodeAddress(movedHi, bottom)}`;
|
|
56
55
|
const columns = [];
|
|
57
56
|
for (const column of filter.columns) {
|
|
58
|
-
const absolute = left + column.colId;
|
|
59
|
-
if (isDeletedSpan(absolute, absolute,
|
|
57
|
+
const absolute = rect.left + column.colId;
|
|
58
|
+
if (isDeletedSpan(absolute, absolute, splice))
|
|
60
59
|
continue;
|
|
61
|
-
columns.push({ ...column, colId: shiftIndex(absolute,
|
|
60
|
+
columns.push({ ...column, colId: shiftIndex(absolute, splice) - moved.left });
|
|
62
61
|
}
|
|
63
62
|
return { ref, columns };
|
|
64
63
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare abstract class AxisHandle<P extends object> {
|
|
2
|
+
/** This position's format record, or `undefined` when it has none. Never fabricates one. */
|
|
3
|
+
protected abstract propertiesOf(): P | undefined;
|
|
4
|
+
/** This position's format record, created if it does not exist yet. */
|
|
5
|
+
protected abstract ensureProperties(): P;
|
|
6
|
+
/** Remove this position's format record entirely, so nothing is left declaring the line. */
|
|
7
|
+
protected abstract dropProperties(): void;
|
|
8
|
+
protected read<K extends keyof P>(key: K): P[K] | undefined;
|
|
9
|
+
protected write<K extends keyof P>(key: K, value: P[K]): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export class AxisHandle {
|
|
2
|
+
read(key) {
|
|
3
|
+
return this.propertiesOf()?.[key];
|
|
4
|
+
}
|
|
5
|
+
write(key, value) {
|
|
6
|
+
if (value === undefined) {
|
|
7
|
+
const properties = this.propertiesOf();
|
|
8
|
+
if (properties === undefined)
|
|
9
|
+
return;
|
|
10
|
+
delete properties[key];
|
|
11
|
+
if (Object.keys(properties).length === 0)
|
|
12
|
+
this.dropProperties();
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
this.ensureProperties()[key] = value;
|
|
16
|
+
}
|
|
17
|
+
}
|
package/dist/core/cell.d.ts
CHANGED
|
@@ -138,6 +138,31 @@ export declare class Cell {
|
|
|
138
138
|
get note(): string | undefined;
|
|
139
139
|
set note(note: string | undefined);
|
|
140
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Whether a cell carries formatting of its own: any {@link CellContent} facet, which is the six shared
|
|
143
|
+
* style facets plus the quote-prefix flag and the link to a named style. Driven by
|
|
144
|
+
* {@link CELL_CONTENT_FACETS}, so a facet added to the tuple reaches every "is this cell blank"
|
|
145
|
+
* decision without anyone remembering to widen a literal.
|
|
146
|
+
*
|
|
147
|
+
* Row- and column-inherited formatting is not the cell's own and does not count. Neither does a
|
|
148
|
+
* note: it lives in the comments part, not the cell's `<c>` element, so a writer deciding whether an
|
|
149
|
+
* empty cell needs serialising asks exactly this. A caller asking whether the cell is *used* wants
|
|
150
|
+
* {@link cellCarriesContent}, which is this plus the value and the note.
|
|
151
|
+
*/
|
|
152
|
+
export declare function cellHasOwnStyle(cell: Cell): boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Whether a cell carries anything at all: a value, formatting of its own, or a note. This is the
|
|
155
|
+
* used-range test, the "carrying anything (data or its own formatting)" that `rowCount` and
|
|
156
|
+
* `columnCount` promise, and it is deliberately wider than "holds a value": someone who pre-formats
|
|
157
|
+
* an empty band has
|
|
158
|
+
* laid claim to those cells, and an append that treats them as free ground writes over the layout
|
|
159
|
+
* they just built; someone who notes an empty cell has put content in it by the note's own
|
|
160
|
+
* definition.
|
|
161
|
+
*
|
|
162
|
+
* A cell merely materialised by `getCell` and then left alone carries nothing, which is what keeps
|
|
163
|
+
* reading a far address from growing the sheet.
|
|
164
|
+
*/
|
|
165
|
+
export declare function cellCarriesContent(cell: Cell): boolean;
|
|
141
166
|
export declare function applyCellStyle(cell: Cell, style: Readonly<CellStyle>): void;
|
|
142
167
|
export declare function copyCellContent(source: CellModel, target: Cell): void;
|
|
143
168
|
export declare function cellToModel(cell: Cell): CellModel;
|
package/dist/core/cell.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { assertColumnInBounds, assertRowInBounds, encodeAddress } from './address.js';
|
|
2
2
|
import { NAMED_STYLE_ID } from './internal.js';
|
|
3
|
-
import { assignStyleFacets, } from './style.js';
|
|
3
|
+
import { assignContentFacets, assignStyleFacets, CELL_CONTENT_FACETS, } from './style.js';
|
|
4
4
|
import { cellValueToText, coerceCellValue, detectValueType, } from './value.js';
|
|
5
5
|
export class Cell {
|
|
6
6
|
row;
|
|
@@ -106,12 +106,18 @@ export class Cell {
|
|
|
106
106
|
this.#note = note;
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
+
export function cellHasOwnStyle(cell) {
|
|
110
|
+
return CELL_CONTENT_FACETS.some((facet) => cell[facet] !== undefined);
|
|
111
|
+
}
|
|
112
|
+
export function cellCarriesContent(cell) {
|
|
113
|
+
return cell.value !== null || cell.note !== undefined || cellHasOwnStyle(cell);
|
|
114
|
+
}
|
|
109
115
|
export function applyCellStyle(cell, style) {
|
|
110
116
|
assignStyleFacets(cell, style);
|
|
111
117
|
}
|
|
112
118
|
export function copyCellContent(source, target) {
|
|
113
119
|
target.value = source.value;
|
|
114
|
-
|
|
120
|
+
assignContentFacets(target, source);
|
|
115
121
|
target.note = source.note;
|
|
116
122
|
}
|
|
117
123
|
export function cellToModel(cell) {
|
|
@@ -121,6 +127,6 @@ export function cellToModel(cell) {
|
|
|
121
127
|
value: cell.value,
|
|
122
128
|
note: cell.note,
|
|
123
129
|
};
|
|
124
|
-
|
|
130
|
+
assignContentFacets(model, cell);
|
|
125
131
|
return model;
|
|
126
132
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How far a copy of one field goes.
|
|
3
|
+
*
|
|
4
|
+
* - `'value'`: assign it. Correct for a scalar, and for anything genuinely immutable.
|
|
5
|
+
* - `'record'`: `{...v}`. A flat object whose own fields are scalars.
|
|
6
|
+
* - `'values'`: `[...v]`. An array of scalars.
|
|
7
|
+
* - `'records'`: `v.map(x => ({...x}))`. An array of flat objects.
|
|
8
|
+
* - a function: the field's own clone, for a nested type that has a plan of its own.
|
|
9
|
+
*/
|
|
10
|
+
export type CloneStrategy<V> = 'value' | 'record' | 'values' | 'records' | ((value: V) => V);
|
|
11
|
+
/**
|
|
12
|
+
* One strategy per field of `T`. The `Record` is what makes a missing field a compile error.
|
|
13
|
+
*
|
|
14
|
+
* A field's strategy sees the field's type without `undefined`, because {@link cloneWith} skips an
|
|
15
|
+
* absent field rather than handing it over. Under `exactOptionalPropertyTypes` a facet declared
|
|
16
|
+
* `font?: Font | undefined` keeps that `undefined` through `Required`, so without the exclusion a
|
|
17
|
+
* nested type's own clone function would not satisfy its own field's strategy.
|
|
18
|
+
*/
|
|
19
|
+
export type ClonePlan<T> = {
|
|
20
|
+
readonly [K in keyof Required<T>]-?: CloneStrategy<Exclude<Required<T>[K], undefined>>;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Copy `source` according to `plan`, leaving a field absent when the source leaves it absent.
|
|
24
|
+
*
|
|
25
|
+
* Absent rather than `undefined`: every one of these types declares its optional fields under
|
|
26
|
+
* `exactOptionalPropertyTypes`, where a present-but-undefined key is a different shape from a missing
|
|
27
|
+
* one, and a round-trip that fabricated the first would report formatting a cell does not have.
|
|
28
|
+
*/
|
|
29
|
+
export declare function cloneWith<T extends object>(source: T, plan: ClonePlan<T>): T;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export function cloneWith(source, plan) {
|
|
2
|
+
const out = {};
|
|
3
|
+
for (const key of Object.keys(plan)) {
|
|
4
|
+
const value = source[key];
|
|
5
|
+
if (value === undefined)
|
|
6
|
+
continue;
|
|
7
|
+
out[key] = applyStrategy(value, plan[key]);
|
|
8
|
+
}
|
|
9
|
+
return out;
|
|
10
|
+
}
|
|
11
|
+
function applyStrategy(value, strategy) {
|
|
12
|
+
if (typeof strategy === 'function')
|
|
13
|
+
return strategy(value);
|
|
14
|
+
switch (strategy) {
|
|
15
|
+
case 'value':
|
|
16
|
+
return value;
|
|
17
|
+
case 'record':
|
|
18
|
+
return { ...value };
|
|
19
|
+
case 'values':
|
|
20
|
+
return [...value];
|
|
21
|
+
case 'records':
|
|
22
|
+
return value.map((entry) => ({ ...entry }));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { hex } from '../hex.js';
|
|
1
2
|
import { parseArgb } from './style.js';
|
|
2
3
|
import { DEFAULT_THEME_COLOR_SCHEME, THEME_COLOR_SLOTS } from './theme.js';
|
|
3
4
|
export const DEFAULT_INDEXED_COLORS = [
|
|
@@ -102,8 +103,5 @@ function hueToChannel(p, q, offset) {
|
|
|
102
103
|
return p;
|
|
103
104
|
}
|
|
104
105
|
function channelHex(value) {
|
|
105
|
-
return Math.round(clamp01(value) * 255)
|
|
106
|
-
.toString(16)
|
|
107
|
-
.toUpperCase()
|
|
108
|
-
.padStart(2, '0');
|
|
106
|
+
return hex(Math.round(clamp01(value) * 255), 2);
|
|
109
107
|
}
|
package/dist/core/column.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { AxisHandle } from './axis-handle.ts';
|
|
1
2
|
import type { Cell } from './cell.ts';
|
|
2
3
|
import { type AssertNever } from './internal.ts';
|
|
3
4
|
import type { Alignment, Border, Fill, Font, Protection } from './style.ts';
|
|
4
5
|
import type { CellValue } from './value.ts';
|
|
5
6
|
import type { ColumnProperties, Worksheet } from './worksheet.ts';
|
|
6
|
-
export declare class Column {
|
|
7
|
+
export declare class Column extends AxisHandle<ColumnProperties> {
|
|
7
8
|
#private;
|
|
8
9
|
/** 1-based column index. Fixed for this handle's lifetime. */
|
|
9
10
|
readonly index: number;
|
|
@@ -18,6 +19,9 @@ export declare class Column {
|
|
|
18
19
|
* is formatted, and they create the record on first write.
|
|
19
20
|
*/
|
|
20
21
|
get properties(): Readonly<ColumnProperties> | undefined;
|
|
22
|
+
protected propertiesOf(): ColumnProperties | undefined;
|
|
23
|
+
protected ensureProperties(): ColumnProperties;
|
|
24
|
+
protected dropProperties(): void;
|
|
21
25
|
/**
|
|
22
26
|
* Stable key naming this column so a keyed-object row (see {@link Worksheet.addRow}) can place a
|
|
23
27
|
* value under it by name rather than position. In-memory only: never serialized to OOXML.
|