@shbernal/ts-xlsx 1.3.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/address.d.ts +49 -2
- package/dist/core/address.js +31 -3
- package/dist/core/autofilter.d.ts +2 -2
- package/dist/core/cell.d.ts +17 -16
- package/dist/core/cell.js +3 -7
- package/dist/core/color-resolution.d.ts +7 -7
- package/dist/core/column.d.ts +8 -9
- package/dist/core/column.js +2 -4
- package/dist/core/comment-thread.d.ts +32 -23
- package/dist/core/comment-thread.js +4 -4
- package/dist/core/conditional-formatting-overlay.d.ts +1 -1
- package/dist/core/conditional-formatting.d.ts +3 -3
- package/dist/core/data-validation-overlay.d.ts +1 -1
- package/dist/core/data-validation.d.ts +3 -3
- package/dist/core/date.d.ts +3 -3
- package/dist/core/formula.d.ts +6 -6
- package/dist/core/grid-edits.js +3 -3
- package/dist/core/image.d.ts +37 -2
- package/dist/core/image.js +6 -0
- package/dist/core/internal.d.ts +9 -1
- package/dist/core/limits.d.ts +4 -4
- package/dist/core/merge.d.ts +6 -12
- package/dist/core/merge.js +0 -3
- package/dist/core/page-setup.d.ts +4 -4
- package/dist/core/pivot-table.d.ts +2 -4
- package/dist/core/pivot-table.js +5 -5
- package/dist/core/preserved.d.ts +3 -3
- package/dist/core/protection.d.ts +4 -4
- package/dist/core/range.d.ts +16 -14
- package/dist/core/range.js +5 -5
- package/dist/core/row-input.d.ts +2 -8
- package/dist/core/row-input.js +2 -2
- package/dist/core/row.d.ts +7 -8
- package/dist/core/row.js +2 -4
- package/dist/core/style.d.ts +14 -14
- package/dist/core/table-style.d.ts +9 -9
- package/dist/core/table-style.js +1 -1
- package/dist/core/table.d.ts +30 -42
- package/dist/core/table.js +16 -10
- package/dist/core/theme.d.ts +13 -43
- package/dist/core/theme.js +2 -148
- package/dist/core/value.d.ts +7 -7
- package/dist/core/workbook-protection.d.ts +2 -2
- package/dist/core/workbook-styles.d.ts +26 -0
- package/dist/core/workbook-styles.js +48 -0
- package/dist/core/workbook-theme.d.ts +25 -0
- package/dist/core/workbook-theme.js +49 -0
- package/dist/core/workbook-vba.d.ts +17 -0
- package/dist/core/workbook-vba.js +79 -0
- package/dist/core/workbook.d.ts +131 -85
- package/dist/core/workbook.js +74 -133
- package/dist/core/worksheet-comments.d.ts +9 -0
- package/dist/core/worksheet-comments.js +52 -0
- package/dist/core/worksheet-model.d.ts +4 -4
- package/dist/core/worksheet-model.js +1 -0
- package/dist/core/worksheet-pictures.d.ts +29 -0
- package/dist/core/worksheet-pictures.js +42 -0
- package/dist/core/worksheet.d.ts +85 -77
- package/dist/core/worksheet.js +36 -95
- package/dist/customui/errors.d.ts +1 -1
- package/dist/customui/ribbon.d.ts +3 -3
- package/dist/entries/core.d.ts +4 -4
- package/dist/entries/core.js +1 -1
- package/dist/entries/vba.d.ts +1 -1
- package/dist/entries/vba.js +1 -1
- package/dist/entries/xlsx.d.ts +1 -0
- package/dist/entries/xlsx.js +1 -0
- package/dist/errors.d.ts +12 -12
- package/dist/io/csv/read.js +1 -2
- package/dist/io/csv/write.d.ts +8 -3
- package/dist/io/csv/write.js +17 -2
- package/dist/io/opc/errors.d.ts +6 -6
- package/dist/io/opc/inflate.d.ts +1 -1
- package/dist/io/opc/namespaces.d.ts +1 -1
- package/dist/io/opc/read-opc.d.ts +19 -3
- package/dist/io/opc/read-opc.js +14 -8
- package/dist/io/opc/read-options.d.ts +2 -2
- package/dist/io/opc/sniff-format.d.ts +2 -2
- package/dist/io/style/xf-style.d.ts +38 -6
- package/dist/io/style/xf-style.js +22 -0
- package/dist/io/xlsb/errors.d.ts +1 -1
- package/dist/io/xlsb/formula.d.ts +4 -4
- package/dist/io/xlsb/primitives.d.ts +8 -8
- package/dist/io/xlsb/ptg-functions.d.ts +1 -1
- package/dist/io/xlsb/read-styles.js +2 -20
- package/dist/io/xlsb/read.d.ts +2 -2
- package/dist/io/xlsx/cell-accumulator.d.ts +25 -6
- package/dist/io/xlsx/cell-accumulator.js +111 -30
- package/dist/io/xlsx/cell-value.d.ts +2 -2
- package/dist/io/xlsx/cell-value.js +3 -3
- package/dist/io/xlsx/color-xml.js +11 -17
- package/dist/io/xlsx/comments.d.ts +5 -5
- package/dist/io/xlsx/comments.js +13 -6
- package/dist/io/xlsx/conditional-formatting.d.ts +3 -3
- package/dist/io/xlsx/conditional-formatting.js +7 -16
- package/dist/io/xlsx/data-validation.d.ts +2 -2
- package/dist/io/xlsx/data-validation.js +1 -1
- package/dist/io/xlsx/errors.d.ts +3 -3
- package/dist/io/xlsx/hyperlinks.d.ts +4 -2
- package/dist/io/xlsx/hyperlinks.js +5 -5
- package/dist/io/xlsx/images.d.ts +1 -1
- package/dist/io/xlsx/images.js +8 -8
- package/dist/io/xlsx/namespaces.d.ts +2 -2
- package/dist/io/xlsx/package-plan.js +5 -2
- package/dist/io/xlsx/read-pivot.js +2 -5
- package/dist/io/xlsx/read-rows.d.ts +13 -13
- package/dist/io/xlsx/read-rows.js +19 -55
- package/dist/io/xlsx/read-shared-strings.js +7 -5
- package/dist/io/xlsx/read-styles.d.ts +3 -3
- package/dist/io/xlsx/read-styles.js +40 -65
- package/dist/io/xlsx/read-worksheet.js +61 -115
- package/dist/io/xlsx/read.d.ts +3 -5
- package/dist/io/xlsx/read.js +61 -69
- package/dist/io/xlsx/rich-runs.d.ts +1 -1
- package/dist/io/xlsx/rich-runs.js +1 -1
- package/dist/io/xlsx/rich-text.d.ts +1 -1
- package/dist/io/xlsx/shared-strings.d.ts +2 -2
- package/dist/io/xlsx/sheet-properties.js +2 -2
- package/dist/io/xlsx/styles.d.ts +8 -9
- package/dist/io/xlsx/styles.js +4 -3
- package/dist/io/xlsx/tables.d.ts +2 -2
- package/dist/io/xlsx/tables.js +8 -13
- package/dist/io/xlsx/theme-xml.d.ts +37 -0
- package/dist/io/xlsx/theme-xml.js +142 -0
- package/dist/io/xlsx/threaded-comments.d.ts +18 -27
- package/dist/io/xlsx/threaded-comments.js +9 -21
- package/dist/io/xlsx/worksheet-xml.d.ts +2 -2
- package/dist/io/xlsx/worksheet-xml.js +7 -12
- package/dist/io/xlsx/write-stream.d.ts +15 -15
- package/dist/io/xlsx/write-stream.js +3 -3
- package/dist/io/xlsx/write.d.ts +8 -7
- package/dist/io/xlsx/write.js +6 -3
- package/dist/io/xlsx/x14-ext.d.ts +1 -1
- package/dist/vba/bytes.d.ts +12 -0
- package/dist/vba/bytes.js +40 -0
- package/dist/vba/cfb-writer.d.ts +1 -1
- package/dist/vba/cfb.d.ts +1 -1
- package/dist/vba/cfb.js +15 -51
- package/dist/vba/codepage.d.ts +2 -2
- package/dist/vba/errors.d.ts +2 -2
- package/dist/vba/index.d.ts +2 -2
- package/dist/vba/index.js +2 -2
- package/dist/vba/ms-ovba.d.ts +1 -1
- package/dist/vba/ms-ovba.js +1 -3
- package/dist/vba/project-editor.d.ts +9 -9
- package/dist/vba/project-editor.js +2 -11
- package/dist/vba/project.d.ts +5 -5
- package/dist/vba/project.js +1 -10
- package/dist/vba/vba-encoding.d.ts +1 -1
- package/dist/xml/errors.d.ts +1 -1
- package/dist/xml/xml-read.d.ts +38 -9
- package/dist/xml/xml-read.js +23 -0
- package/dist/xml/xml.d.ts +31 -9
- package/dist/xml/xml.js +23 -3
- package/package.json +41 -35
package/dist/core/date.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The number format applied to a `Date` cell that carries no explicit format of its own,
|
|
3
|
-
* so the value renders
|
|
3
|
+
* so the value renders, and reads back, as a date rather than a bare serial number.
|
|
4
4
|
*/
|
|
5
5
|
export declare const DEFAULT_DATE_NUMFMT = "yyyy-mm-dd";
|
|
6
6
|
/**
|
|
@@ -17,8 +17,8 @@ export declare function dateToSerial(date: Date): number;
|
|
|
17
17
|
export declare function serialToDate(serial: number): Date;
|
|
18
18
|
/**
|
|
19
19
|
* Whether a number-format code renders its value as a date or time. A format is a date
|
|
20
|
-
* format when, once its non-formatting sections are removed
|
|
21
|
-
* condition directives, quoted literals, and escaped characters
|
|
20
|
+
* format when, once its non-formatting sections are removed (bracketed color/locale/
|
|
21
|
+
* condition directives, quoted literals, and escaped characters) any of the date/time
|
|
22
22
|
* placeholder letters (`y m d h s`) remain. So `"$"#,##0.00` and `0.00%` are not dates
|
|
23
23
|
* while `yyyy-mm-dd`, `dd/mm/yyyy`, and `[$-409]mmmm d, yyyy` are.
|
|
24
24
|
*/
|
package/dist/core/formula.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Quote a sheet name for use in a reference exactly when Excel would: a name that is not a plain
|
|
3
|
-
* identifier
|
|
3
|
+
* identifier, or that would read as a cell address, is wrapped in single quotes with its internal
|
|
4
4
|
* quotes doubled, and a simple name is left bare. Shared by everything that *builds* a qualified
|
|
5
5
|
* reference: the `_FilterDatabase` name the writer derives from an autofilter, and the `.xlsb`
|
|
6
6
|
* reader's Ptg decoder, which has only a sheet index to work from and must spell the prefix itself.
|
|
7
7
|
*
|
|
8
8
|
* `last` names the far end of a 3-D span (`Data:More!A1`). A span is quoted as a whole or not at all,
|
|
9
|
-
* because the quotes delimit the sheet *reference* rather than either name
|
|
9
|
+
* because the quotes delimit the sheet *reference* rather than either name, so one awkward endpoint
|
|
10
10
|
* puts both inside the quotes.
|
|
11
11
|
*/
|
|
12
12
|
export declare function quoteSheetName(name: string, last?: string): string;
|
|
@@ -14,7 +14,7 @@ export declare function quoteSheetName(name: string, last?: string): string;
|
|
|
14
14
|
* Prefix every modern function called by its plain name with `_xlfn.` so Excel accepts the stored
|
|
15
15
|
* formula. Names already prefixed are left alone (never doubled), unknown/legacy functions pass
|
|
16
16
|
* through untouched, and opaque regions (string literals, sheet names, structured references) are
|
|
17
|
-
* preserved verbatim. No other rewriting occurs
|
|
17
|
+
* preserved verbatim. No other rewriting occurs: in particular no `@` implicit-intersection operator
|
|
18
18
|
* is ever introduced.
|
|
19
19
|
*/
|
|
20
20
|
export declare function mangleFunctions(formula: string): string;
|
|
@@ -25,8 +25,8 @@ export declare function mangleFunctions(formula: string): string;
|
|
|
25
25
|
*/
|
|
26
26
|
export declare function unmangleFunctions(formula: string): string;
|
|
27
27
|
/**
|
|
28
|
-
* Prefix every LET/LAMBDA parameter identifier with `_xlpm
|
|
29
|
-
* reference within the binding call's parentheses
|
|
28
|
+
* Prefix every LET/LAMBDA parameter identifier with `_xlpm.`, at its declaration and at each
|
|
29
|
+
* reference within the binding call's parentheses, so Excel accepts the stored formula. The prefix
|
|
30
30
|
* is lexically scoped: a name is only rewritten inside the call that binds it, opaque regions are
|
|
31
31
|
* copied verbatim, and a lambda-valued parameter used as a call (`f(…)`) is prefixed too. Formulas
|
|
32
32
|
* with no LET/LAMBDA pass through unchanged.
|
|
@@ -34,7 +34,7 @@ export declare function unmangleFunctions(formula: string): string;
|
|
|
34
34
|
export declare function mangleParams(formula: string): string;
|
|
35
35
|
/**
|
|
36
36
|
* Mangle a model formula into its on-disk form: LET/LAMBDA parameter names first (`_xlpm.`), then the
|
|
37
|
-
* modern-function prefix (`_xlfn.`). Ordering matters
|
|
37
|
+
* modern-function prefix (`_xlfn.`). Ordering matters: parameter mangling reads the plain LET/LAMBDA
|
|
38
38
|
* names before the function pass qualifies them. The inverse for both prefixes is unmangleFunctions.
|
|
39
39
|
*/
|
|
40
40
|
export declare function mangleFormula(formula: string): string;
|
package/dist/core/grid-edits.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { decodeRange, encodeAddress, tryDecodeCellRef } from './address.js';
|
|
2
2
|
import { Cell, copyCellContent } from './cell.js';
|
|
3
3
|
import { replaceContents } from './containers.js';
|
|
4
4
|
import { isOneCellAnchor } from './image.js';
|
|
@@ -95,8 +95,8 @@ export class GridEdits {
|
|
|
95
95
|
const value = cell.value;
|
|
96
96
|
if (!isSharedFormulaValue(value))
|
|
97
97
|
continue;
|
|
98
|
-
const master =
|
|
99
|
-
if (master
|
|
98
|
+
const master = tryDecodeCellRef(value.sharedFormula);
|
|
99
|
+
if (master === undefined)
|
|
100
100
|
continue;
|
|
101
101
|
const anchored = axis === 'row'
|
|
102
102
|
? encodeAddress(master.col, shiftIndex(master.row, start, count, delta))
|
package/dist/core/image.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export declare const PX_TO_EMU = 9525;
|
|
|
17
17
|
* them; `oneCell` moves but keeps its size; `absolute` is pinned to the page and does neither. Excel
|
|
18
18
|
* defaults to `oneCell` when the attribute is omitted. */
|
|
19
19
|
export type ImageEditAs = 'oneCell' | 'twoCell' | 'absolute';
|
|
20
|
-
/** A fixed image size in EMUs
|
|
20
|
+
/** A fixed image size in EMUs: the extent of a one-cell anchor, which pixel dimensions convert into
|
|
21
21
|
* via {@link PX_TO_EMU}. */
|
|
22
22
|
export interface Extent {
|
|
23
23
|
readonly cx: number;
|
|
@@ -63,7 +63,7 @@ export interface AnchoredImage {
|
|
|
63
63
|
}
|
|
64
64
|
/** A picture's bytes and its file kind, as held in the workbook's media registry. */
|
|
65
65
|
export interface WorkbookImage {
|
|
66
|
-
/** Lower-case file extension without a dot
|
|
66
|
+
/** Lower-case file extension without a dot: `"png"`, `"jpeg"`, `"gif"`. Drives the media part's
|
|
67
67
|
* name and content type. */
|
|
68
68
|
readonly extension: string;
|
|
69
69
|
readonly data: Uint8Array;
|
|
@@ -74,3 +74,38 @@ export interface WorkbookImage {
|
|
|
74
74
|
* leading run of alphanumerics; a missing or all-punctuation hint falls back to sniffing the bytes'
|
|
75
75
|
* magic number, so the package is always well-formed. */
|
|
76
76
|
export declare function normalizeImageExtension(extension: string | undefined, data: Uint8Array): string;
|
|
77
|
+
/**
|
|
78
|
+
* An anchored image in workbook-independent form: the picture's own bytes rather than a media id
|
|
79
|
+
* into one particular workbook's registry.
|
|
80
|
+
*
|
|
81
|
+
* An {@link AnchoredImage} means nothing away from that registry: its `imageId` is an index, and
|
|
82
|
+
* the same index names a different picture (or none) in the next workbook. Attaching the picture
|
|
83
|
+
* itself is what lets an anchor cross that boundary, which is why the transfer form carries bytes
|
|
84
|
+
* where the stored form carries an id.
|
|
85
|
+
*/
|
|
86
|
+
export interface PortableImage {
|
|
87
|
+
readonly image: WorkbookImage;
|
|
88
|
+
readonly anchor: ImageAnchor;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Every picture a worksheet shows, in the workbook-independent form of {@link PortableImage}: the
|
|
92
|
+
* images anchored to the grid, in the order they were added, and the background tiled behind it.
|
|
93
|
+
* {@link Workbook.exportImages} produces one, {@link Workbook.importImages} applies one.
|
|
94
|
+
*/
|
|
95
|
+
export interface WorksheetImages {
|
|
96
|
+
readonly anchored: readonly PortableImage[];
|
|
97
|
+
readonly background: WorkbookImage | undefined;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* The id under which `image` is already registered in `media`, or `undefined` if it is not.
|
|
101
|
+
*
|
|
102
|
+
* Content-addressed rather than reference-addressed: two byte-identical pictures are one picture,
|
|
103
|
+
* however they reached the registry. This is what keeps repeated imports from growing the media
|
|
104
|
+
* list without bound (the same logo carried onto twenty sheets registers once), and it is why the
|
|
105
|
+
* comparison is over bytes rather than object identity, which a picture arriving from another
|
|
106
|
+
* workbook would never satisfy.
|
|
107
|
+
*
|
|
108
|
+
* The length check comes first and short-circuits, so pictures of different sizes never reach the
|
|
109
|
+
* byte loop; only same-extension, same-length candidates are compared in full.
|
|
110
|
+
*/
|
|
111
|
+
export declare function findRegisteredImage(media: readonly WorkbookImage[], image: WorkbookImage): number | undefined;
|
package/dist/core/image.js
CHANGED
|
@@ -38,3 +38,9 @@ export function normalizeImageExtension(extension, data) {
|
|
|
38
38
|
}
|
|
39
39
|
return sniffImageExtension(data);
|
|
40
40
|
}
|
|
41
|
+
export function findRegisteredImage(media, image) {
|
|
42
|
+
const index = media.findIndex((held) => held.extension === image.extension &&
|
|
43
|
+
held.data.length === image.data.length &&
|
|
44
|
+
held.data.every((byte, i) => byte === image.data[i]));
|
|
45
|
+
return index === -1 ? undefined : index;
|
|
46
|
+
}
|
package/dist/core/internal.d.ts
CHANGED
|
@@ -4,8 +4,16 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export declare const INTERNAL: unique symbol;
|
|
6
6
|
/**
|
|
7
|
-
* Keys a `Cell`'s link to a named cell style
|
|
7
|
+
* Keys a `Cell`'s link to a named cell style, its OOXML `xfId`. A single hidden property rather than
|
|
8
8
|
* a channel object, so it stays a prototype accessor: cells are the one model class allocated in the
|
|
9
9
|
* millions, and a per-instance internals object would be a real cost for state most cells never carry.
|
|
10
10
|
*/
|
|
11
11
|
export declare const NAMED_STYLE_ID: unique symbol;
|
|
12
|
+
/**
|
|
13
|
+
* The exhaustiveness proof the mirror types are built on: instantiate it with a `keyof` difference
|
|
14
|
+
* that should be empty. An unmirrored field leaves that difference non-`never`, which does not
|
|
15
|
+
* satisfy the constraint, so the build fails naming the field that was missed: a type error at the
|
|
16
|
+
* declaration rather than a silent hole discovered by a round trip. `Row`, `Column` and
|
|
17
|
+
* `WORKSHEET_MODEL_FACETS` each carry one of these proofs; this is the mechanism all three use.
|
|
18
|
+
*/
|
|
19
|
+
export type AssertNever<T extends never> = T;
|
package/dist/core/limits.d.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* shown.
|
|
5
5
|
*
|
|
6
6
|
* A file may state more, and stating more loses the value rather than the file. Excel opens such a
|
|
7
|
-
* package without complaint and silently clamps the row
|
|
8
|
-
*
|
|
7
|
+
* package without complaint and silently clamps the row to 409.6, a tick *above* what it lets you
|
|
8
|
+
* assign, being 8192 twentieths of a point and so the width of the field it is read into, then
|
|
9
9
|
* writes 409.6 back on its next save. Check against this constant to keep a stated height from
|
|
10
10
|
* quietly becoming a different one.
|
|
11
11
|
*/
|
|
@@ -16,12 +16,12 @@ export declare const MAX_ROW_HEIGHT = 409.5;
|
|
|
16
16
|
*
|
|
17
17
|
* It is also the weaker of the two ceilings: it binds assignment only, and not a file at all.
|
|
18
18
|
* Excel honours a `width` of 1000 read from a package, renders the column at it, and round-trips
|
|
19
|
-
* it verbatim through its own save
|
|
19
|
+
* it verbatim through its own save, where an over-limit row height is clamped away. So a width
|
|
20
20
|
* above this is a column no Excel user could have produced by dragging, not a value at risk.
|
|
21
21
|
*
|
|
22
22
|
* Character units, not points or pixels: a width is a count of digits of the default font's
|
|
23
23
|
* *maximum digit width*, which is why there is no companion `DEFAULT_COLUMN_WIDTH` constant here.
|
|
24
|
-
* The width a column takes when it states none is a function of that font
|
|
24
|
+
* The width a column takes when it states none is a function of that font: the familiar 8.43 holds
|
|
25
25
|
* for Calibri 11 and not for a workbook whose normal style says otherwise (Excel reports 8.09 for
|
|
26
26
|
* Aptos Narrow 11). `sheet.properties.defaultColWidth` is what a file declares, and
|
|
27
27
|
* docs/knowledge/specs/default-font-must-not-be-assumed-for-column-widths.md is why assuming a
|
package/dist/core/merge.d.ts
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
|
+
import { type GridRect } from './address.ts';
|
|
1
2
|
import type { Cell } from './cell.ts';
|
|
2
|
-
/** A merged region as
|
|
3
|
-
export
|
|
4
|
-
readonly top: number;
|
|
5
|
-
readonly left: number;
|
|
6
|
-
readonly bottom: number;
|
|
7
|
-
readonly right: number;
|
|
8
|
-
}
|
|
9
|
-
/** Whether two inclusive grid rectangles share at least one cell. */
|
|
10
|
-
export declare function rectsOverlap(a: MergeRect, b: MergeRect): boolean;
|
|
3
|
+
/** A merged region, as the {@link GridRect} every range-shaped thing in the library is. */
|
|
4
|
+
export type MergeRect = GridRect;
|
|
11
5
|
/**
|
|
12
6
|
* Resolve a position to the master (top-left) of the merged region covering it, or to itself when no
|
|
13
7
|
* region does. First covering region wins; `Worksheet.mergeCells` rejects overlaps, so at most one
|
|
14
|
-
* region ever applies. Only fully-bounded rects participate
|
|
8
|
+
* region ever applies. Only fully-bounded rects participate: an unbounded whole-row/column merge
|
|
15
9
|
* carries no rect and so resolves nothing.
|
|
16
10
|
*/
|
|
17
11
|
export declare function masterOf(rects: readonly MergeRect[], row: number, col: number): {
|
|
@@ -20,12 +14,12 @@ export declare function masterOf(rects: readonly MergeRect[], row: number, col:
|
|
|
20
14
|
};
|
|
21
15
|
/**
|
|
22
16
|
* Drop any value already sitting in a merge's covered non-anchor cells, keeping only the top-left
|
|
23
|
-
* anchor
|
|
17
|
+
* anchor, the collapse Excel performs on merge. A leftover covered value would serialise as a
|
|
24
18
|
* populated `<c>` under the range's `<mergeCell>` ref, the geometry that trips Excel's repair prompt.
|
|
25
19
|
* Styles are untouched: a border spanning the merged region rides the covered cells.
|
|
26
20
|
*/
|
|
27
21
|
export declare function clearCoveredValues(rows: Map<number, Map<number, Cell>>, rect: MergeRect): void;
|
|
28
22
|
/** Decode an OOXML `sqref` (one or more space-separated ranges) into containment rectangles. A whole
|
|
29
23
|
* column or row leaves one axis unbounded, so its missing edges open to `Infinity` rather than
|
|
30
|
-
* clamping
|
|
24
|
+
* clamping: a cell anywhere down the column still resolves inside it. */
|
|
31
25
|
export declare function decodeSqrefRects(sqref: string): MergeRect[];
|
package/dist/core/merge.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
import { decodeRange } from './address.js';
|
|
2
|
-
export function rectsOverlap(a, b) {
|
|
3
|
-
return a.left <= b.right && b.left <= a.right && a.top <= b.bottom && b.top <= a.bottom;
|
|
4
|
-
}
|
|
5
2
|
export function masterOf(rects, row, col) {
|
|
6
3
|
for (const rect of rects) {
|
|
7
4
|
if (row >= rect.top && row <= rect.bottom && col >= rect.left && col <= rect.right) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* `<pageSetUpPr>` flag (a `<sheetPr>` child) that switches Excel from fixed-zoom to fit-to-page
|
|
4
4
|
* scaling, while the rest are `<pageSetup>` attributes. Excel honours `scale` only when `fitToPage`
|
|
5
5
|
* is off and the `fitToWidth`/`fitToHeight` page counts only when it is on, but the model carries
|
|
6
|
-
* whatever the author set
|
|
6
|
+
* whatever the author set: an unset field is omitted so a round-trip never fabricates one. An
|
|
7
7
|
* empty object emits neither element.
|
|
8
8
|
*/
|
|
9
9
|
export interface PageSetup {
|
|
@@ -21,7 +21,7 @@ export interface PageSetup {
|
|
|
21
21
|
pageOrder?: 'downThenOver' | 'overThenDown';
|
|
22
22
|
/**
|
|
23
23
|
* Paper size as Excel's 1-based enumeration index (e.g. `9` = A4, `1` = US Letter). Carried as an
|
|
24
|
-
* opaque integer
|
|
24
|
+
* opaque integer: the model does not map it to physical dimensions, only preserves whatever the
|
|
25
25
|
* author or source file set.
|
|
26
26
|
*/
|
|
27
27
|
paperSize?: number;
|
|
@@ -35,7 +35,7 @@ export interface PageSetup {
|
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
37
|
* Print-toggle flags from the `<printOptions>` element. Each maps to a boolean OOXML attribute that
|
|
38
|
-
* defaults false
|
|
38
|
+
* defaults false, except `gridLinesSet`, which defaults true and gates whether `gridLines` is
|
|
39
39
|
* honoured. The model stores only what the source or caller set, so an unset flag is omitted and a
|
|
40
40
|
* round-trip never fabricates one; an empty object emits no element at all.
|
|
41
41
|
*/
|
|
@@ -54,7 +54,7 @@ export interface PrintOptions {
|
|
|
54
54
|
/**
|
|
55
55
|
* A manual page break (`<brk>`). For a row break, `id` is the row the layout splits *before*; for a
|
|
56
56
|
* column break it is the column. `max` bounds the break's extent across the other axis (Excel writes
|
|
57
|
-
* the last row/column index) and `man` marks it author-set rather than automatic
|
|
57
|
+
* the last row/column index) and `man` marks it author-set rather than automatic. The model preserves
|
|
58
58
|
* whatever the source carried so a round-trip reproduces the break's span exactly.
|
|
59
59
|
*/
|
|
60
60
|
export interface PageBreak {
|
|
@@ -3,12 +3,10 @@ import type { Worksheet } from './worksheet.ts';
|
|
|
3
3
|
* names verbatim, so a metric doubles as its `<dataField subtotal="…">` value. Excel performs the
|
|
4
4
|
* aggregation itself on refresh; the writer only records which function to apply. */
|
|
5
5
|
export type PivotMetric = 'sum' | 'count' | 'countNums' | 'average' | 'max' | 'min' | 'product' | 'stdDev' | 'stdDevp' | 'var' | 'varp';
|
|
6
|
-
/** Narrow a raw `subtotal` attribute (or any string) to a known {@link PivotMetric}. */
|
|
7
|
-
export declare function isPivotMetric(value: string): value is PivotMetric;
|
|
8
6
|
/** Map an OOXML `<dataField subtotal="…">` value back to its metric. The attribute is absent for
|
|
9
7
|
* `sum` (Excel's implicit default), so `undefined` reads as `sum`; an unrecognised value also reads
|
|
10
|
-
* as `sum` rather than throwing, because reconstructing an existing file is a lenient operation
|
|
11
|
-
*
|
|
8
|
+
* as `sum` rather than throwing, because reconstructing an existing file is a lenient operation.
|
|
9
|
+
* The strict rejection of unknown metrics belongs on the authoring path, not the read path. */
|
|
12
10
|
export declare function pivotMetricFromSubtotal(subtotal: string | undefined): PivotMetric;
|
|
13
11
|
/** One field in a loaded pivot's cache catalogue, in declared order; the pivot refers to it by index. */
|
|
14
12
|
export interface ParsedPivotField {
|
package/dist/core/pivot-table.js
CHANGED
|
@@ -14,7 +14,7 @@ const PIVOT_METRICS = new Set([
|
|
|
14
14
|
'var',
|
|
15
15
|
'varp',
|
|
16
16
|
]);
|
|
17
|
-
|
|
17
|
+
function isPivotMetric(value) {
|
|
18
18
|
return PIVOT_METRICS.has(value);
|
|
19
19
|
}
|
|
20
20
|
export function pivotMetricFromSubtotal(subtotal) {
|
|
@@ -35,7 +35,7 @@ export class PivotTable {
|
|
|
35
35
|
constructor(options) {
|
|
36
36
|
const metric = options.metric ?? 'sum';
|
|
37
37
|
if (!PIVOT_METRICS.has(metric)) {
|
|
38
|
-
throw new AuthoringError(`unsupported pivot metric "${metric}"
|
|
38
|
+
throw new AuthoringError(`unsupported pivot metric "${metric}": expected one of ${[...PIVOT_METRICS].join(', ')}`);
|
|
39
39
|
}
|
|
40
40
|
this.metric = metric;
|
|
41
41
|
const source = options.source;
|
|
@@ -110,7 +110,7 @@ export class PivotTable {
|
|
|
110
110
|
records.push(fields.map((_field, fieldIndex) => {
|
|
111
111
|
const scalar = scalarsForField(columnScalars, fieldIndex)[row];
|
|
112
112
|
if (scalar === undefined) {
|
|
113
|
-
throw new InternalError(`pivot record row ${row} is out of range for field ${fieldIndex}
|
|
113
|
+
throw new InternalError(`pivot record row ${row} is out of range for field ${fieldIndex}: every column was ` +
|
|
114
114
|
'scanned for the same dataRowCount above, so this index is always in range');
|
|
115
115
|
}
|
|
116
116
|
const catalogue = catalogues[fieldIndex];
|
|
@@ -127,7 +127,7 @@ export class PivotTable {
|
|
|
127
127
|
get valueFieldName() {
|
|
128
128
|
const field = this.cacheFields[this.valueField];
|
|
129
129
|
if (field === undefined) {
|
|
130
|
-
throw new InternalError(`pivot valueField index ${this.valueField} is out of range
|
|
130
|
+
throw new InternalError(`pivot valueField index ${this.valueField} is out of range: resolve() validated it against ` +
|
|
131
131
|
'the same fields array cacheFields was built from');
|
|
132
132
|
}
|
|
133
133
|
return field.name;
|
|
@@ -136,7 +136,7 @@ export class PivotTable {
|
|
|
136
136
|
function scalarsForField(columnScalars, fieldIndex) {
|
|
137
137
|
const scalars = columnScalars[fieldIndex];
|
|
138
138
|
if (scalars === undefined) {
|
|
139
|
-
throw new InternalError(`pivot field index ${fieldIndex} is out of range for columnScalars
|
|
139
|
+
throw new InternalError(`pivot field index ${fieldIndex} is out of range for columnScalars: it was built from the same fields array`);
|
|
140
140
|
}
|
|
141
141
|
return scalars;
|
|
142
142
|
}
|
package/dist/core/preserved.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* One outbound relationship of a {@link PreservedPart}: the id it carries inside its own rels part,
|
|
3
3
|
* the relationship Type URI, and its target. An internal relationship's `targetPath` is the resolved
|
|
4
4
|
* package path of the part it points at (the writer re-numbers and rewires it); an `external`
|
|
5
|
-
* relationship's `targetPath` is the raw `Target` verbatim (a linked workbook's path or URL)
|
|
5
|
+
* relationship's `targetPath` is the raw `Target` verbatim (a linked workbook's path or URL). It is
|
|
6
6
|
* outside the package, so it is emitted unchanged with `TargetMode="External"` and never remapped.
|
|
7
7
|
* Preserving external relationships is what keeps an `externalLink` part's pointer to its source
|
|
8
8
|
* workbook alive, so a round-trip does not orphan the `[n]` external references formulas resolve through.
|
|
@@ -26,7 +26,7 @@ export interface PreservedPart {
|
|
|
26
26
|
readonly rels: readonly PreservedRelationship[];
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
|
-
* A worksheet-level reference to package content the model does not model
|
|
29
|
+
* A worksheet-level reference to package content the model does not model, preserved verbatim across
|
|
30
30
|
* a round-trip instead of being silently dropped. `element` is the worksheet child that wires the
|
|
31
31
|
* reference (`<drawing>` for a vector-shape drawing, `<legacyDrawingHF>` for a header/footer image),
|
|
32
32
|
* or `undefined` when the sheet wires it by relationship alone (a pivot table or slicer Excel
|
|
@@ -43,7 +43,7 @@ export interface PreservedWorksheetReference {
|
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
45
45
|
* A package-root reference to content the model does not model, wired from the package's own
|
|
46
|
-
* `_rels/.rels` rather than the workbook part's rels
|
|
46
|
+
* `_rels/.rels` rather than the workbook part's rels: the ribbon-customisation parts
|
|
47
47
|
* (`customUI/customUI14.xml`), custom document properties (`docProps/custom.xml`), a thumbnail, and
|
|
48
48
|
* anything else hung off the root. The writer regenerates the root rels for the parts it models
|
|
49
49
|
* (workbook, core/app properties), so these would be dropped unless captured here and re-declared.
|
|
@@ -33,7 +33,7 @@ export interface SheetProtectionOptions extends SheetProtectionFlags {
|
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
35
35
|
* A password-derived credential, in OOXML's agile form: the hash algorithm, the salted
|
|
36
|
-
* iterated hash of the password, the salt, and the iteration count
|
|
36
|
+
* iterated hash of the password, the salt, and the iteration count: everything a consumer
|
|
37
37
|
* needs to verify a supplied password without the password ever being stored.
|
|
38
38
|
*/
|
|
39
39
|
export interface SheetProtectionCredential {
|
|
@@ -50,8 +50,8 @@ export interface SheetProtection {
|
|
|
50
50
|
/**
|
|
51
51
|
* The OOXML encoding table for the protection flags: each `<sheetProtection>` attribute paired
|
|
52
52
|
* with whether that operation is *forbidden by default* once a sheet is protected. Both directions
|
|
53
|
-
* key off this one list
|
|
54
|
-
* equal to the default)
|
|
53
|
+
* key off this one list. The writer turns an author allow-flag into an attribute (omitting values
|
|
54
|
+
* equal to the default) and the reader turns an attribute back into an allow-flag, so serialization
|
|
55
55
|
* and deserialization can never fall out of step. Most editing operations default to forbidden
|
|
56
56
|
* under protection; selecting cells and the object/scenario operations default to permitted.
|
|
57
57
|
*/
|
|
@@ -61,7 +61,7 @@ export declare const SHEET_PROTECTION_FLAGS: readonly {
|
|
|
61
61
|
}[];
|
|
62
62
|
/**
|
|
63
63
|
* Derive a fresh {@link SheetProtectionCredential} for a password. Each call generates a new
|
|
64
|
-
* random salt, so protecting two sheets with the same password yields different credentials
|
|
64
|
+
* random salt, so protecting two sheets with the same password yields different credentials:
|
|
65
65
|
* the salt is real randomness, not a stub.
|
|
66
66
|
*/
|
|
67
67
|
export declare function deriveCredential(password: string, spinCount?: number): SheetProtectionCredential;
|
package/dist/core/range.d.ts
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
|
+
import { type GridRect } from './address.ts';
|
|
1
2
|
import { type Cell } from './cell.ts';
|
|
2
3
|
import { type Alignment, type Border, type CellStyle, type Fill, type Font, type Protection } from './style.ts';
|
|
3
4
|
import type { Worksheet } from './worksheet.ts';
|
|
4
5
|
/**
|
|
5
6
|
* A rectangular block of a worksheet's cells: `sheet.getRange('B2:D5')`.
|
|
6
7
|
*
|
|
7
|
-
* Cheap and stateless
|
|
8
|
+
* Cheap and stateless: constructing one creates no cells and does not extend the used range.
|
|
8
9
|
* {@link addresses} walks the block without materialising anything; {@link cells} reports only what
|
|
9
10
|
* already exists.
|
|
10
11
|
*
|
|
11
12
|
* Bounds are **inclusive first/last**, never start-and-count. That is the convention every
|
|
12
13
|
* range-shaped accessor in this library follows, so the three axes cannot disagree about what a
|
|
13
|
-
* pair of numbers means
|
|
14
|
+
* pair of numbers means; the handle is declared to satisfy {@link GridRect}, which is that
|
|
15
|
+
* convention written down once.
|
|
14
16
|
*/
|
|
15
|
-
export declare class Range {
|
|
17
|
+
export declare class Range implements GridRect {
|
|
16
18
|
#private;
|
|
17
19
|
/** 1-based row of the block's top edge. Fixed for this handle's lifetime. */
|
|
18
20
|
readonly top: number;
|
|
@@ -23,7 +25,7 @@ export declare class Range {
|
|
|
23
25
|
/** 1-based column of the block's right edge, inclusive. */
|
|
24
26
|
readonly right: number;
|
|
25
27
|
/**
|
|
26
|
-
* Build a handle from inclusive corners, in any order
|
|
28
|
+
* Build a handle from inclusive corners, in any order: `(5, 4, 2, 2)` and `(2, 2, 5, 4)` name the
|
|
27
29
|
* same block, exactly as `D5:B2` and `B2:D5` do. Prefer {@link Worksheet.getRange}.
|
|
28
30
|
*
|
|
29
31
|
* @throws {RangeError} if a corner is not a positive integer or falls outside the sheet's bounds.
|
|
@@ -31,30 +33,30 @@ export declare class Range {
|
|
|
31
33
|
constructor(sheet: Worksheet, top: number, left: number, bottom: number, right: number);
|
|
32
34
|
/** The worksheet this block belongs to. */
|
|
33
35
|
get sheet(): Worksheet;
|
|
34
|
-
/** Canonical `tl:br` A1 form
|
|
36
|
+
/** Canonical `tl:br` A1 form, `"B2:D5"`. A one-cell block still reads as `"B2:B2"`. */
|
|
35
37
|
get address(): string;
|
|
36
38
|
/** Rows spanned, inclusive of both edges. */
|
|
37
39
|
get rowCount(): number;
|
|
38
40
|
/** Columns spanned, inclusive of both edges. */
|
|
39
41
|
get columnCount(): number;
|
|
40
|
-
/** Cells the block covers
|
|
42
|
+
/** Cells the block covers: `rowCount * columnCount`, whether or not they exist yet. */
|
|
41
43
|
get cellCount(): number;
|
|
42
44
|
/** Whether a 1-based position falls inside the block. */
|
|
43
45
|
contains(row: number, col: number): boolean;
|
|
44
46
|
/**
|
|
45
47
|
* Every address the block covers, row-major (`B2`, `C2`, `D2`, `B3`, …). Materialises nothing, so
|
|
46
|
-
* this is the cheap way to walk a large block
|
|
48
|
+
* this is the cheap way to walk a large block, and, being a generator, it can be abandoned
|
|
47
49
|
* part-way without having built the whole list.
|
|
48
50
|
*/
|
|
49
51
|
addresses(): IterableIterator<string>;
|
|
50
52
|
/**
|
|
51
53
|
* The block's **materialised** cells, row-major. Sparse: a position nothing has ever written to is
|
|
52
54
|
* simply absent, which is what distinguishes "never written" from a cell holding `null`. Reading
|
|
53
|
-
* this creates nothing
|
|
55
|
+
* this creates nothing, mirroring {@link Column.cells}.
|
|
54
56
|
*/
|
|
55
57
|
get cells(): readonly Cell[];
|
|
56
58
|
/**
|
|
57
|
-
* The block's style, facet by facet
|
|
59
|
+
* The block's style, facet by facet: the counterpart of {@link Cell.style} over a rectangle, with
|
|
58
60
|
* the same semantics in both directions.
|
|
59
61
|
*
|
|
60
62
|
* **Reading** reports a facet only when *every* position in the block carries a structurally
|
|
@@ -62,13 +64,13 @@ export declare class Range {
|
|
|
62
64
|
* through this handle therefore reads back what was written; a block whose cells disagree says so
|
|
63
65
|
* rather than picking a corner's answer and passing it off as the whole.
|
|
64
66
|
*
|
|
65
|
-
* **Writing** lays each facet the payload names onto every cell, leaving facets it omits
|
|
66
|
-
*
|
|
67
|
-
* it. Use {@link clearStyle} first for a wholesale replace.
|
|
67
|
+
* **Writing** lays each facet the payload names onto every cell, leaving facets it omits
|
|
68
|
+
* untouched, exactly what `cell.style = {...}` does, so this composes with prior styling instead
|
|
69
|
+
* of clearing it. Use {@link clearStyle} first for a wholesale replace.
|
|
68
70
|
*
|
|
69
71
|
* Writing **materialises** every position in the block, because a styled-but-valueless cell is the
|
|
70
72
|
* only way an empty cell renders with a fill: skipping the holes would leave gaps in a header band.
|
|
71
|
-
* The cost is bounded by construction
|
|
73
|
+
* The cost is bounded by construction: a range is always a bounded rectangle, and whole-axis
|
|
72
74
|
* styling belongs to {@link Worksheet.getColumn}/{@link Worksheet.getRow} instead. {@link cellCount}
|
|
73
75
|
* is the exact number of cells a write will create.
|
|
74
76
|
*/
|
|
@@ -77,7 +79,7 @@ export declare class Range {
|
|
|
77
79
|
/**
|
|
78
80
|
* Strip every style facet from every cell in the block, leaving values untouched. Assigning
|
|
79
81
|
* {@link style} composes, so this is how a wholesale replace is said: `clearStyle()` then assign.
|
|
80
|
-
* Materialises nothing
|
|
82
|
+
* Materialises nothing: a cell that does not exist carries no style to clear.
|
|
81
83
|
*/
|
|
82
84
|
clearStyle(): void;
|
|
83
85
|
/** Fill applied to every cell in the block; `undefined` when they do not all agree. */
|
package/dist/core/range.js
CHANGED
|
@@ -154,22 +154,22 @@ function facetKey(value) {
|
|
|
154
154
|
}
|
|
155
155
|
function checkBound(axis, value, max) {
|
|
156
156
|
if (!Number.isInteger(value) || value < 1) {
|
|
157
|
-
throw new RangeError(`${axis} ${value} is out of bounds
|
|
157
|
+
throw new RangeError(`${axis} ${value} is out of bounds: ${axis}s start at 1`);
|
|
158
158
|
}
|
|
159
159
|
if (value > max) {
|
|
160
|
-
throw new RangeError(`${axis} ${value} is out of bounds
|
|
160
|
+
throw new RangeError(`${axis} ${value} is out of bounds: the sheet ends at ${max}`);
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
export function rangeFrom(sheet, reference) {
|
|
164
164
|
const { top, left, bottom, right, sheetName, dimensions } = decodeRange(reference);
|
|
165
165
|
if (sheetName !== undefined && sheetName.toLowerCase() !== sheet.name.toLowerCase()) {
|
|
166
|
-
throw new SyntaxError(`"${reference}" names worksheet "${sheetName}", not "${sheet.name}"
|
|
166
|
+
throw new SyntaxError(`"${reference}" names worksheet "${sheetName}", not "${sheet.name}": a range belongs to the sheet it came from`);
|
|
167
167
|
}
|
|
168
168
|
if (top === undefined || bottom === undefined) {
|
|
169
|
-
throw new SyntaxError(`"${reference}" spans whole columns (${dimensions})
|
|
169
|
+
throw new SyntaxError(`"${reference}" spans whole columns (${dimensions}): style them through getColumn(n), which says the same thing in one attribute instead of ${MAX_ROW} cells`);
|
|
170
170
|
}
|
|
171
171
|
if (left === undefined || right === undefined) {
|
|
172
|
-
throw new SyntaxError(`"${reference}" spans whole rows (${dimensions})
|
|
172
|
+
throw new SyntaxError(`"${reference}" spans whole rows (${dimensions}): style them through getRow(n), which says the same thing in one attribute instead of ${MAX_COLUMN} cells`);
|
|
173
173
|
}
|
|
174
174
|
return new Range(sheet, top, left, bottom, right);
|
|
175
175
|
}
|
package/dist/core/row-input.d.ts
CHANGED
|
@@ -7,8 +7,8 @@ import type { ColumnProperties, RowInput } from './worksheet.ts';
|
|
|
7
7
|
* untouched; a keyed object maps each value under the column carrying the matching key.
|
|
8
8
|
*
|
|
9
9
|
* `Array.isArray`, not `instanceof Array`: a row built in another realm (a vm context, a browser
|
|
10
|
-
* iframe) is still an array but fails the identity check, and would then be walked as a keyed
|
|
11
|
-
* placing nothing.
|
|
10
|
+
* iframe) is still an array but fails the identity check, and would then be walked as a keyed
|
|
11
|
+
* object, placing nothing.
|
|
12
12
|
*/
|
|
13
13
|
export declare function rowPlacements(values: RowInput, columns: ReadonlyMap<number, ColumnProperties>): Array<[number, CellValue]>;
|
|
14
14
|
/**
|
|
@@ -16,9 +16,3 @@ export declare function rowPlacements(values: RowInput, columns: ReadonlyMap<num
|
|
|
16
16
|
* keyed by column. The grid-edit machinery then splices this map into place.
|
|
17
17
|
*/
|
|
18
18
|
export declare function buildRowCells(number: number, values: RowInput, columns: ReadonlyMap<number, ColumnProperties>): Map<number, Cell>;
|
|
19
|
-
/**
|
|
20
|
-
* The 1-based index of the column carrying `key` (see {@link ColumnProperties.key}).
|
|
21
|
-
*
|
|
22
|
-
* @throws {AuthoringError} if no column declares that key.
|
|
23
|
-
*/
|
|
24
|
-
export declare function columnIndexByKey(columns: ReadonlyMap<number, ColumnProperties>, key: string): number;
|
package/dist/core/row-input.js
CHANGED
|
@@ -20,10 +20,10 @@ export function buildRowCells(number, values, columns) {
|
|
|
20
20
|
}
|
|
21
21
|
return row;
|
|
22
22
|
}
|
|
23
|
-
|
|
23
|
+
function columnIndexByKey(columns, key) {
|
|
24
24
|
for (const [index, properties] of columns) {
|
|
25
25
|
if (properties.key === key)
|
|
26
26
|
return index;
|
|
27
27
|
}
|
|
28
|
-
throw new AuthoringError(`no column is keyed ${JSON.stringify(key)}
|
|
28
|
+
throw new AuthoringError(`no column is keyed ${JSON.stringify(key)}: set getColumn(n).key first`);
|
|
29
29
|
}
|
package/dist/core/row.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Cell } from './cell.ts';
|
|
2
|
+
import { type AssertNever } from './internal.ts';
|
|
2
3
|
import type { Fill } from './style.ts';
|
|
3
4
|
import type { CellValue } from './value.ts';
|
|
4
5
|
import type { RowProperties, Worksheet } from './worksheet.ts';
|
|
@@ -6,10 +7,10 @@ export declare class Row {
|
|
|
6
7
|
#private;
|
|
7
8
|
/** 1-based row number. Fixed for this handle's lifetime. */
|
|
8
9
|
readonly number: number;
|
|
9
|
-
/** @throws {RangeError}
|
|
10
|
+
/** @throws {RangeError} unless the number is an integer within Excel's row grid (1..1048576). */
|
|
10
11
|
constructor(sheet: Worksheet, number: number);
|
|
11
12
|
/**
|
|
12
|
-
* The row's format record if it has one, else `undefined
|
|
13
|
+
* The row's format record if it has one, else `undefined`: a read that never fabricates, so a
|
|
13
14
|
* serializer can ask every row it visits whether there are attributes to emit without giving each
|
|
14
15
|
* one an empty record. Read-only on purpose: {@link height} and its siblings are how a row is
|
|
15
16
|
* formatted, and they create the record on first write.
|
|
@@ -21,7 +22,7 @@ export declare class Row {
|
|
|
21
22
|
* Not bounded here, deliberately: {@link MAX_ROW_HEIGHT} is what Excel accepts *being set*, but
|
|
22
23
|
* the schema puts no ceiling on `ht` and this setter is also how the reader loads a foreign
|
|
23
24
|
* file, so refusing a taller row would mean refusing a file Excel opens clean. Check against the
|
|
24
|
-
* constant when authoring
|
|
25
|
+
* constant when authoring: Excel silently clamps a taller row on read, so a height above it is
|
|
25
26
|
* one you state and do not get.
|
|
26
27
|
*/
|
|
27
28
|
get height(): number | undefined;
|
|
@@ -51,7 +52,7 @@ export declare class Row {
|
|
|
51
52
|
getCell(column: number | string): Cell;
|
|
52
53
|
/**
|
|
53
54
|
* The row's materialised cells in ascending column order. Sparse: a column never written to has
|
|
54
|
-
* no cell here, and the array is a fresh snapshot of *which* cells exist
|
|
55
|
+
* no cell here, and the array is a fresh snapshot of *which* cells exist; the cells themselves
|
|
55
56
|
* are the live ones.
|
|
56
57
|
*/
|
|
57
58
|
get cells(): readonly Cell[];
|
|
@@ -60,16 +61,15 @@ export declare class Row {
|
|
|
60
61
|
* a column with no cell is a hole, which is what distinguishes "never written" from a cell
|
|
61
62
|
* holding `null`.
|
|
62
63
|
*
|
|
63
|
-
* Assigning places each value it names and leaves every other column untouched
|
|
64
|
+
* Assigning places each value it names and leaves every other column untouched: a hole or an
|
|
64
65
|
* explicit `undefined` skips that column, and a shorter array does not clear the tail. These are
|
|
65
66
|
* {@link Worksheet.addRow}'s rules, deliberately: `values` is that same row shape addressed by
|
|
66
|
-
* number rather than appended. To *replace* a row, including clearing what it held, splice it
|
|
67
|
+
* number rather than appended. To *replace* a row, including clearing what it held, splice it:
|
|
67
68
|
* `sheet.spliceRows(n, 1, values)`.
|
|
68
69
|
*/
|
|
69
70
|
get values(): (CellValue | undefined)[];
|
|
70
71
|
set values(values: (CellValue | undefined)[]);
|
|
71
72
|
}
|
|
72
|
-
type AssertNever<T extends never> = T;
|
|
73
73
|
/**
|
|
74
74
|
* Compile-time proof that {@link Row} mirrors every {@link RowProperties} field. A field added to
|
|
75
75
|
* the record without an accessor here resolves this to that field's name, which does not satisfy
|
|
@@ -78,4 +78,3 @@ type AssertNever<T extends never> = T;
|
|
|
78
78
|
* would simply never mention it.
|
|
79
79
|
*/
|
|
80
80
|
export type EveryRowPropertyIsMirrored = AssertNever<Exclude<keyof RowProperties, keyof Row & keyof RowProperties>>;
|
|
81
|
-
export {};
|
package/dist/core/row.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import { columnToNumber, encodeAddress } from './address.js';
|
|
1
|
+
import { assertRowInBounds, columnToNumber, encodeAddress } from './address.js';
|
|
2
2
|
import { INTERNAL } from './internal.js';
|
|
3
3
|
export class Row {
|
|
4
4
|
#sheet;
|
|
5
5
|
number;
|
|
6
6
|
constructor(sheet, number) {
|
|
7
|
-
|
|
8
|
-
throw new RangeError(`row ${number} is out of bounds — rows start at 1`);
|
|
9
|
-
}
|
|
7
|
+
assertRowInBounds(number);
|
|
10
8
|
this.#sheet = sheet;
|
|
11
9
|
this.number = number;
|
|
12
10
|
}
|