@shbernal/ts-xlsx 1.0.2 → 1.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 +6 -0
- package/dist/core/autofilter.js +2 -2
- package/dist/core/cell.d.ts +10 -0
- package/dist/core/cell.js +16 -4
- package/dist/core/color-resolution.js +1 -1
- package/dist/core/column.d.ts +9 -1
- package/dist/core/column.js +11 -3
- package/dist/core/conditional-formatting-overlay.js +1 -1
- package/dist/core/data-validation-overlay.js +2 -2
- package/dist/core/formula.js +2 -2
- package/dist/core/grid-edits.js +5 -5
- package/dist/core/limits.d.ts +30 -0
- package/dist/core/limits.js +47 -0
- package/dist/core/merge.js +1 -1
- package/dist/core/pivot-table.js +7 -3
- package/dist/core/range.js +8 -4
- package/dist/core/row.d.ts +9 -1
- package/dist/core/row.js +11 -3
- package/dist/core/table-style.d.ts +2 -2
- package/dist/core/table-style.js +2 -2
- package/dist/core/table.js +2 -2
- package/dist/core/text-metrics.d.ts +20 -0
- package/dist/core/text-metrics.js +50 -0
- package/dist/core/theme.d.ts +1 -1
- package/dist/core/theme.js +1 -1
- package/dist/core/value.d.ts +50 -10
- package/dist/core/value.js +76 -0
- package/dist/core/workbook-protection.d.ts +1 -1
- package/dist/core/workbook.d.ts +24 -11
- package/dist/core/workbook.js +45 -22
- package/dist/core/worksheet-model.d.ts +1 -1
- package/dist/core/worksheet-model.js +5 -5
- package/dist/core/worksheet.d.ts +24 -2
- package/dist/core/worksheet.js +49 -21
- package/dist/customui/errors.js +1 -1
- package/dist/customui/index.js +2 -2
- package/dist/customui/ribbon.d.ts +1 -1
- package/dist/customui/ribbon.js +3 -3
- package/dist/entries/core.d.ts +3 -1
- package/dist/entries/core.js +16 -14
- package/dist/entries/csv.js +2 -2
- package/dist/entries/customui.js +1 -1
- package/dist/entries/errors.js +7 -7
- package/dist/entries/vba.js +2 -2
- package/dist/entries/xlsb.js +1 -1
- package/dist/entries/xlsx.js +5 -5
- package/dist/index.js +7 -7
- package/dist/io/csv/read.js +2 -2
- package/dist/io/csv/write.js +12 -24
- package/dist/io/opc/errors.js +1 -1
- package/dist/io/opc/inflate.d.ts +1 -1
- package/dist/io/opc/inflate.js +2 -2
- package/dist/io/opc/read-opc.js +2 -2
- package/dist/io/opc/rels.js +2 -2
- package/dist/io/opc/sniff-format.js +2 -2
- package/dist/io/style/xf-style.js +2 -2
- package/dist/io/xlsb/errors.js +1 -1
- package/dist/io/xlsb/formula.js +4 -4
- package/dist/io/xlsb/primitives.js +2 -2
- package/dist/io/xlsb/read-shared-strings.js +3 -3
- package/dist/io/xlsb/read-styles.js +5 -5
- package/dist/io/xlsb/read-worksheet.js +9 -9
- package/dist/io/xlsb/read.d.ts +1 -1
- package/dist/io/xlsb/read.js +15 -15
- package/dist/io/xlsb/record-stream.js +1 -1
- package/dist/io/xlsx/cell-accumulator.js +6 -6
- package/dist/io/xlsx/cell-value.js +4 -4
- package/dist/io/xlsx/comments.js +4 -4
- package/dist/io/xlsx/conditional-formatting.js +5 -5
- package/dist/io/xlsx/data-validation.js +4 -4
- package/dist/io/xlsx/edit-vba.js +4 -4
- package/dist/io/xlsx/errors.js +1 -1
- package/dist/io/xlsx/hyperlinks.js +4 -4
- package/dist/io/xlsx/images.js +6 -6
- package/dist/io/xlsx/package-plan.js +3 -3
- package/dist/io/xlsx/pivot-read.js +2 -2
- package/dist/io/xlsx/pivot.js +4 -4
- package/dist/io/xlsx/read-rows.d.ts +3 -3
- package/dist/io/xlsx/read-rows.js +12 -12
- package/dist/io/xlsx/read-styles.js +4 -4
- package/dist/io/xlsx/read-worksheet.js +8 -8
- package/dist/io/xlsx/read.d.ts +1 -1
- package/dist/io/xlsx/read.js +28 -28
- package/dist/io/xlsx/relationships.d.ts +6 -6
- package/dist/io/xlsx/relationships.js +2 -2
- package/dist/io/xlsx/rich-runs.js +1 -1
- package/dist/io/xlsx/rich-text.js +2 -2
- package/dist/io/xlsx/shared-formulas.js +3 -3
- package/dist/io/xlsx/shared-strings-read.js +2 -2
- package/dist/io/xlsx/shared-strings.js +3 -3
- package/dist/io/xlsx/sheet-properties.js +4 -4
- package/dist/io/xlsx/styles.js +6 -6
- package/dist/io/xlsx/tables.js +5 -5
- package/dist/io/xlsx/threaded-comments.js +5 -5
- package/dist/io/xlsx/workbook-xml.js +9 -9
- package/dist/io/xlsx/worksheet-xml.js +18 -18
- package/dist/io/xlsx/write-stream.d.ts +1 -1
- package/dist/io/xlsx/write-stream.js +7 -7
- package/dist/io/xlsx/write.d.ts +3 -3
- package/dist/io/xlsx/write.js +20 -20
- package/dist/io/xlsx/x14-ext.js +1 -1
- package/dist/vba/cfb-writer.js +1 -1
- package/dist/vba/cfb.js +1 -1
- package/dist/vba/codepage.js +1 -1
- package/dist/vba/errors.js +1 -1
- package/dist/vba/index.js +5 -5
- package/dist/vba/ms-ovba.js +1 -1
- package/dist/vba/project-editor.js +7 -7
- package/dist/vba/project.js +4 -4
- package/dist/vba/vba-encoding.js +1 -1
- package/dist/xml/errors.js +1 -1
- package/dist/xml/xml-read.js +1 -1
- package/dist/xml/xml.js +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# ts-xlsx
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@shbernal/ts-xlsx)
|
|
4
|
+
[](https://www.npmjs.com/package/@shbernal/ts-xlsx)
|
|
5
|
+
[](https://www.npmjs.com/package/@shbernal/ts-xlsx)
|
|
6
|
+
[](https://github.com/shbernal/ts-xlsx/actions/workflows/build.yml)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
3
9
|
A TypeScript-first library for reading and writing spreadsheet documents
|
|
4
10
|
(`.xlsx` / OOXML, and CSV) — synchronous, `Uint8Array`-native, and dependency-lean.
|
|
5
11
|
|
package/dist/core/autofilter.js
CHANGED
package/dist/core/cell.d.ts
CHANGED
|
@@ -22,6 +22,16 @@ export declare class Cell {
|
|
|
22
22
|
set value(value: CellValue | undefined);
|
|
23
23
|
/** The observable {@link ValueType} of the current value. */
|
|
24
24
|
get type(): ValueType;
|
|
25
|
+
/**
|
|
26
|
+
* The cell's value as plain text ({@link cellValueToText}), `""` when it is empty — so a reader
|
|
27
|
+
* that only wants strings never has to narrow the value union itself.
|
|
28
|
+
*
|
|
29
|
+
* Read-only, because text is a *rendering* of the value and not a second place to store one:
|
|
30
|
+
* writing `"3"` here could only mean the string `"3"`, which is exactly `value = '3'` and reads
|
|
31
|
+
* nothing like it. The number format is not applied either — the style is not the cell's value,
|
|
32
|
+
* so a currency cell's text carries no currency sign.
|
|
33
|
+
*/
|
|
34
|
+
get text(): string;
|
|
25
35
|
/**
|
|
26
36
|
* Assign rich text whose runs **inherit this cell's font**, so a run needs to state only what it
|
|
27
37
|
* changes: `setRichText([{text: 'Note:', font: {bold: true}}, {text: ' the rest'}])` keeps the
|
package/dist/core/cell.js
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
// *numbers* (legacy shipped a type declaration calling them strings, which broke
|
|
5
5
|
// strict consumers). The value is the only mutable state here; assigning it routes
|
|
6
6
|
// through the value model so the cell's `type` is always consistent with what it holds.
|
|
7
|
-
import { encodeAddress } from
|
|
8
|
-
import { NAMED_STYLE_ID } from
|
|
9
|
-
import { assignStyleFacets, } from
|
|
10
|
-
import { coerceCellValue, detectValueType, } from
|
|
7
|
+
import { encodeAddress } from './address.js';
|
|
8
|
+
import { NAMED_STYLE_ID } from './internal.js';
|
|
9
|
+
import { assignStyleFacets, } from './style.js';
|
|
10
|
+
import { cellValueToText, coerceCellValue, detectValueType, } from './value.js';
|
|
11
11
|
/**
|
|
12
12
|
* A single cell owns its value and every style facet outright. Each facet below — fill, number format,
|
|
13
13
|
* font, border, alignment, protection, quote-prefix, and note — is held in the cell's own field and
|
|
@@ -54,6 +54,18 @@ export class Cell {
|
|
|
54
54
|
get type() {
|
|
55
55
|
return detectValueType(this.#value);
|
|
56
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* The cell's value as plain text ({@link cellValueToText}), `""` when it is empty — so a reader
|
|
59
|
+
* that only wants strings never has to narrow the value union itself.
|
|
60
|
+
*
|
|
61
|
+
* Read-only, because text is a *rendering* of the value and not a second place to store one:
|
|
62
|
+
* writing `"3"` here could only mean the string `"3"`, which is exactly `value = '3'` and reads
|
|
63
|
+
* nothing like it. The number format is not applied either — the style is not the cell's value,
|
|
64
|
+
* so a currency cell's text carries no currency sign.
|
|
65
|
+
*/
|
|
66
|
+
get text() {
|
|
67
|
+
return cellValueToText(this.#value);
|
|
68
|
+
}
|
|
57
69
|
/**
|
|
58
70
|
* Assign rich text whose runs **inherit this cell's font**, so a run needs to state only what it
|
|
59
71
|
* changes: `setRichText([{text: 'Note:', font: {bold: true}}, {text: ' the rest'}])` keeps the
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// keeps the encoding its file used, so a round-trip re-emits `theme="4" tint="0.4"` rather than
|
|
10
10
|
// rewriting every cell as a literal ARGB — which would bloat the styles table, break the link to the
|
|
11
11
|
// theme (recolouring the workbook would stop working), and change what the file means.
|
|
12
|
-
import { DEFAULT_THEME_COLOR_SCHEME, THEME_COLOR_SLOTS } from
|
|
12
|
+
import { DEFAULT_THEME_COLOR_SCHEME, THEME_COLOR_SLOTS } from './theme.js';
|
|
13
13
|
/**
|
|
14
14
|
* The built-in indexed colour palette (ECMA-376 §18.8.27), by index. Entries 0–7 duplicate 8–15 —
|
|
15
15
|
* redundancy the spec preserves for backwards compatibility with the legacy formats this palette came
|
package/dist/core/column.d.ts
CHANGED
|
@@ -23,7 +23,15 @@ export declare class Column {
|
|
|
23
23
|
*/
|
|
24
24
|
get key(): string | undefined;
|
|
25
25
|
set key(key: string | undefined);
|
|
26
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Column width in character units — digits of the workbook default font's maximum digit width,
|
|
28
|
+
* so what one unit measures moves with that font. `undefined` leaves the sheet default in force.
|
|
29
|
+
*
|
|
30
|
+
* Not bounded here, for the same reason {@link Row.height} is not, and for a stronger one:
|
|
31
|
+
* {@link MAX_COLUMN_WIDTH} bounds what Excel accepts being set, not what a file may hold. Excel
|
|
32
|
+
* reads a wider column back unchanged and re-saves it verbatim, so a bound here would refuse a
|
|
33
|
+
* width Excel itself preserves.
|
|
34
|
+
*/
|
|
27
35
|
get width(): number | undefined;
|
|
28
36
|
set width(width: number | undefined);
|
|
29
37
|
/** Whether the column is hidden. */
|
package/dist/core/column.js
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
// A column carries more than a row does: besides the geometry (width, visibility, outline) it holds
|
|
8
8
|
// the six `CellStyle` facets as *defaults* for its cells, which is why the mirror below is twice the
|
|
9
9
|
// length of the row's.
|
|
10
|
-
import { encodeAddress, numberToColumn } from
|
|
11
|
-
import { INTERNAL } from
|
|
10
|
+
import { encodeAddress, numberToColumn } from './address.js';
|
|
11
|
+
import { INTERNAL } from './internal.js';
|
|
12
12
|
export class Column {
|
|
13
13
|
#sheet;
|
|
14
14
|
/** 1-based column index. Fixed for this handle's lifetime. */
|
|
@@ -44,7 +44,15 @@ export class Column {
|
|
|
44
44
|
set key(key) {
|
|
45
45
|
this.#write('key', key);
|
|
46
46
|
}
|
|
47
|
-
/**
|
|
47
|
+
/**
|
|
48
|
+
* Column width in character units — digits of the workbook default font's maximum digit width,
|
|
49
|
+
* so what one unit measures moves with that font. `undefined` leaves the sheet default in force.
|
|
50
|
+
*
|
|
51
|
+
* Not bounded here, for the same reason {@link Row.height} is not, and for a stronger one:
|
|
52
|
+
* {@link MAX_COLUMN_WIDTH} bounds what Excel accepts being set, not what a file may hold. Excel
|
|
53
|
+
* reads a wider column back unchanged and re-saves it verbatim, so a bound here would refuse a
|
|
54
|
+
* width Excel itself preserves.
|
|
55
|
+
*/
|
|
48
56
|
get width() {
|
|
49
57
|
return this.#read('width');
|
|
50
58
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// The conditional-formatting overlay a Worksheet owns: an insertion-ordered, defensively-copied list
|
|
2
2
|
// of range-bound rule sets. Kept as its own class, the sibling to {@link DataValidationOverlay}, so
|
|
3
3
|
// Worksheet delegates the collection's storage and cloning rather than managing the array itself.
|
|
4
|
-
import { cloneConditionalFormatting } from
|
|
4
|
+
import { cloneConditionalFormatting } from './conditional-formatting.js';
|
|
5
5
|
export class ConditionalFormattingOverlay {
|
|
6
6
|
#entries = [];
|
|
7
7
|
/**
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
// as its own class — the sibling to {@link GridEdits} that owns splice arithmetic — rather than inline
|
|
4
4
|
// on Worksheet, since a validation's storage (a rule plus its decoded ranges) is a self-contained unit
|
|
5
5
|
// Worksheet only ever adds to, reads, or clears wholesale.
|
|
6
|
-
import { cloneDataValidation, } from
|
|
7
|
-
import { decodeSqrefRects } from
|
|
6
|
+
import { cloneDataValidation, } from './data-validation.js';
|
|
7
|
+
import { decodeSqrefRects } from './merge.js';
|
|
8
8
|
export class DataValidationOverlay {
|
|
9
9
|
#entries = [];
|
|
10
10
|
#rects = [];
|
package/dist/core/formula.js
CHANGED
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
// verbatim and hands each code run between them to a transform. `mangleParams` is the deliberate
|
|
21
21
|
// exception: LET/LAMBDA parameter scope opens and closes at paren boundaries, state `scanFormula`'s
|
|
22
22
|
// per-run transform cannot carry, so it runs its own forward walk — still deferring to `skipOpaque`.
|
|
23
|
-
import { columnToNumber, numberToColumn } from
|
|
24
|
-
import { MODERN_FUNCTIONS } from
|
|
23
|
+
import { columnToNumber, numberToColumn } from './address.js';
|
|
24
|
+
import { MODERN_FUNCTIONS } from './modern-functions.js';
|
|
25
25
|
const XLFN = '_xlfn.';
|
|
26
26
|
const XLPM = '_xlpm.';
|
|
27
27
|
/**
|
package/dist/core/grid-edits.js
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
// mechanics: it holds the sheet's storage containers by reference and mutates them in place, and
|
|
5
5
|
// touches none of the public cell API. Worksheet builds the cells an insert introduces, then hands
|
|
6
6
|
// the pre-built rows (or the raw column values) here for the shift.
|
|
7
|
-
import { decodeAddress, decodeRange, encodeAddress } from
|
|
8
|
-
import { Cell, copyCellContent } from
|
|
9
|
-
import { replaceContents } from
|
|
10
|
-
import { isOneCellAnchor } from
|
|
11
|
-
import { isSharedFormulaValue } from
|
|
7
|
+
import { decodeAddress, decodeRange, encodeAddress } from './address.js';
|
|
8
|
+
import { Cell, copyCellContent } from './cell.js';
|
|
9
|
+
import { replaceContents } from './containers.js';
|
|
10
|
+
import { isOneCellAnchor } from './image.js';
|
|
11
|
+
import { isSharedFormulaValue } from './value.js';
|
|
12
12
|
// The shift rule shared by every re-anchoring pass: a coordinate before the edit stays put, one at or
|
|
13
13
|
// after the edited span shifts by `delta`, and one inside a deleted span clamps to the cut line (`start`).
|
|
14
14
|
function shiftIndex(v, start, count, delta) {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The tallest row Excel accepts being set to, in points: it refuses 409.6 and takes 409.5. A row
|
|
3
|
+
* asked to hold more wrapped text than this cannot grow to fit it, and the overflow is simply not
|
|
4
|
+
* shown.
|
|
5
|
+
*
|
|
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 — to 409.6, a tick *above* what it lets
|
|
8
|
+
* you assign, being 8192 twentieths of a point and so the width of the field it is read into — and
|
|
9
|
+
* writes 409.6 back on its next save. Check against this constant to keep a stated height from
|
|
10
|
+
* quietly becoming a different one.
|
|
11
|
+
*/
|
|
12
|
+
export declare const MAX_ROW_HEIGHT = 409.5;
|
|
13
|
+
/**
|
|
14
|
+
* The widest column Excel accepts being set to, in character units of the workbook's default font.
|
|
15
|
+
* Excel refuses 255.4, so unlike the row-height ceiling this one is exactly integral.
|
|
16
|
+
*
|
|
17
|
+
* It is also the weaker of the two ceilings: it binds assignment only, and not a file at all.
|
|
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 — where an over-limit row height is clamped away. So a width
|
|
20
|
+
* above this is a column no Excel user could have produced by dragging, not a value at risk.
|
|
21
|
+
*
|
|
22
|
+
* Character units, not points or pixels: a width is a count of digits of the default font's
|
|
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 — the familiar 8.43 holds
|
|
25
|
+
* for Calibri 11 and not for a workbook whose normal style says otherwise (Excel reports 8.09 for
|
|
26
|
+
* Aptos Narrow 11). `sheet.properties.defaultColWidth` is what a file declares, and
|
|
27
|
+
* docs/knowledge/specs/default-font-must-not-be-assumed-for-column-widths.md is why assuming a
|
|
28
|
+
* value for it is a bug rather than a shortcut.
|
|
29
|
+
*/
|
|
30
|
+
export declare const MAX_COLUMN_WIDTH = 255;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Excel's limits on the grid's *geometry* — the other half of the bounds `address.ts` states.
|
|
2
|
+
//
|
|
3
|
+
// `MAX_ROW`/`MAX_COLUMN` bound where a cell can be; these bound how big a line can be *set*. The
|
|
4
|
+
// difference that matters is who enforces them: the addressing bounds are structural (a reference
|
|
5
|
+
// past XFD is not a reference), so the model refuses them outright, while these are limits on
|
|
6
|
+
// *assignment* in Excel's own UI and object model. They are not limits on what a package may
|
|
7
|
+
// carry. The schema types `ht` and `width` as a bare `xsd:double` with no ceiling on either, and
|
|
8
|
+
// Excel opens an over-limit file clean — no repair prompt, no repair log — so a reader that threw
|
|
9
|
+
// on one would refuse a file Excel accepts. Nothing here is enforced, therefore, on either the
|
|
10
|
+
// read or the write path; these are for a caller that wants the size it states to be the size
|
|
11
|
+
// Excel uses, and the doc comments on `Row.height`/`Column.width` point here for that reason.
|
|
12
|
+
//
|
|
13
|
+
// What Excel does with an over-limit file is not symmetric, and the difference is why only one of
|
|
14
|
+
// these two numbers describes a value that survives: a row is silently clamped, a column is not.
|
|
15
|
+
// Both ceilings and both file behaviours were measured rather than quoted — Microsoft's own
|
|
16
|
+
// specifications page rounds the row-height ceiling to "409 points", and Excel takes 409.5. See
|
|
17
|
+
// docs/knowledge/specs/grid-geometry-limits-are-excels-not-the-schemas.md for the probes.
|
|
18
|
+
/**
|
|
19
|
+
* The tallest row Excel accepts being set to, in points: it refuses 409.6 and takes 409.5. A row
|
|
20
|
+
* asked to hold more wrapped text than this cannot grow to fit it, and the overflow is simply not
|
|
21
|
+
* shown.
|
|
22
|
+
*
|
|
23
|
+
* A file may state more, and stating more loses the value rather than the file. Excel opens such a
|
|
24
|
+
* package without complaint and silently clamps the row — to 409.6, a tick *above* what it lets
|
|
25
|
+
* you assign, being 8192 twentieths of a point and so the width of the field it is read into — and
|
|
26
|
+
* writes 409.6 back on its next save. Check against this constant to keep a stated height from
|
|
27
|
+
* quietly becoming a different one.
|
|
28
|
+
*/
|
|
29
|
+
export const MAX_ROW_HEIGHT = 409.5;
|
|
30
|
+
/**
|
|
31
|
+
* The widest column Excel accepts being set to, in character units of the workbook's default font.
|
|
32
|
+
* Excel refuses 255.4, so unlike the row-height ceiling this one is exactly integral.
|
|
33
|
+
*
|
|
34
|
+
* It is also the weaker of the two ceilings: it binds assignment only, and not a file at all.
|
|
35
|
+
* Excel honours a `width` of 1000 read from a package, renders the column at it, and round-trips
|
|
36
|
+
* it verbatim through its own save — where an over-limit row height is clamped away. So a width
|
|
37
|
+
* above this is a column no Excel user could have produced by dragging, not a value at risk.
|
|
38
|
+
*
|
|
39
|
+
* Character units, not points or pixels: a width is a count of digits of the default font's
|
|
40
|
+
* *maximum digit width*, which is why there is no companion `DEFAULT_COLUMN_WIDTH` constant here.
|
|
41
|
+
* The width a column takes when it states none is a function of that font — the familiar 8.43 holds
|
|
42
|
+
* for Calibri 11 and not for a workbook whose normal style says otherwise (Excel reports 8.09 for
|
|
43
|
+
* Aptos Narrow 11). `sheet.properties.defaultColWidth` is what a file declares, and
|
|
44
|
+
* docs/knowledge/specs/default-font-must-not-be-assumed-for-column-widths.md is why assuming a
|
|
45
|
+
* value for it is a bug rather than a shortcut.
|
|
46
|
+
*/
|
|
47
|
+
export const MAX_COLUMN_WIDTH = 255;
|
package/dist/core/merge.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Inclusive grid rectangles and the geometry a worksheet uses to reason about merged regions and the
|
|
2
2
|
// `sqref` ranges that overlays (data validations, conditional formats) apply to: overlap detection and
|
|
3
3
|
// decoding an OOXML `sqref` into containment rectangles.
|
|
4
|
-
import { decodeRange } from
|
|
4
|
+
import { decodeRange } from './address.js';
|
|
5
5
|
/** Whether two inclusive grid rectangles share at least one cell. */
|
|
6
6
|
export function rectsOverlap(a, b) {
|
|
7
7
|
return a.left <= b.right && b.left <= a.right && a.top <= b.bottom && b.top <= a.bottom;
|
package/dist/core/pivot-table.js
CHANGED
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
//
|
|
10
10
|
// The source data is captured when the pivot is added — the model reads the source sheet's cells
|
|
11
11
|
// once, here, so the pivot is a stable snapshot independent of later edits to the source.
|
|
12
|
-
import { AuthoringError, InternalError } from
|
|
13
|
-
import { encodeAddress } from
|
|
14
|
-
import { isErrorValue, isFormulaValue, isHyperlinkValue, isRichTextValue, isSharedFormulaValue, richTextToPlain, } from
|
|
12
|
+
import { AuthoringError, InternalError } from '../errors.js';
|
|
13
|
+
import { encodeAddress } from './address.js';
|
|
14
|
+
import { isErrorValue, isFormulaValue, isHyperlinkValue, isRichTextValue, isSharedFormulaValue, richTextToPlain, } from './value.js';
|
|
15
15
|
const PIVOT_METRICS = new Set([
|
|
16
16
|
'sum',
|
|
17
17
|
'count',
|
|
@@ -216,6 +216,10 @@ function textOf(item) {
|
|
|
216
216
|
* Reduce any cell value to the scalar a pivot cache can hold: a number, a string, or a blank. Only
|
|
217
217
|
* finite numbers stay numeric (a NaN would corrupt the cache); every other kind is flattened to its
|
|
218
218
|
* displayed text so hostile or exotic source content can never throw or leak an object into the XML.
|
|
219
|
+
*
|
|
220
|
+
* Deliberately not `cellValueToText`, close as the two look: this classifies rather than renders
|
|
221
|
+
* (a number must reach the cache *as a number*), and its no-throw promise is the opposite of that
|
|
222
|
+
* function's, which rejects a value outside the union rather than quietly caching a blank.
|
|
219
223
|
*/
|
|
220
224
|
function scalarOf(value) {
|
|
221
225
|
if (value === null)
|
package/dist/core/range.js
CHANGED
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
// million cells, whereas OOXML expresses it natively as a single `<col style>` or `<row s>` — which
|
|
10
10
|
// is what `getColumn`/`getRow` already write, in constant space. Refusing them is what lets a range
|
|
11
11
|
// materialise its cells eagerly without a cost cliff hiding behind an innocuous-looking call.
|
|
12
|
-
import { decodeRange, encodeAddress, MAX_COLUMN, MAX_ROW } from
|
|
13
|
-
import { applyCellStyle } from
|
|
14
|
-
import { CELL_STYLE_FACETS, } from
|
|
12
|
+
import { decodeRange, encodeAddress, MAX_COLUMN, MAX_ROW } from './address.js';
|
|
13
|
+
import { applyCellStyle } from './cell.js';
|
|
14
|
+
import { CELL_STYLE_FACETS, } from './style.js';
|
|
15
15
|
/**
|
|
16
16
|
* A rectangular block of a worksheet's cells: `sheet.getRange('B2:D5')`.
|
|
17
17
|
*
|
|
@@ -242,9 +242,13 @@ function setFacet(cell, facet, value) {
|
|
|
242
242
|
// order their keys were written in. Sound here and nowhere near a general deep-equal: every facet is
|
|
243
243
|
// a plain data record of strings, numbers, booleans and nested records — no functions, no cycles, no
|
|
244
244
|
// class instances — which is exactly the shape JSON round-trips faithfully.
|
|
245
|
+
//
|
|
246
|
+
// `undefined` needs a sentinel because `JSON.stringify` answers it with `undefined` rather than a
|
|
247
|
+
// string. NUL is the one that cannot collide: a defined value stringifies to `"`, `{`, `[`, a digit,
|
|
248
|
+
// or a bare `true`/`false`/`null`, and a NUL *inside* a string comes back as a six-char escape.
|
|
245
249
|
function facetKey(value) {
|
|
246
250
|
if (value === undefined)
|
|
247
|
-
return '
|
|
251
|
+
return '\u0000';
|
|
248
252
|
return JSON.stringify(value, (_key, inner) => inner !== null && typeof inner === 'object' && !Array.isArray(inner)
|
|
249
253
|
? Object.fromEntries(Object.entries(inner).sort(([a], [b]) => (a < b ? -1 : 1)))
|
|
250
254
|
: inner);
|
package/dist/core/row.d.ts
CHANGED
|
@@ -15,7 +15,15 @@ export declare class Row {
|
|
|
15
15
|
* formatted, and they create the record on first write.
|
|
16
16
|
*/
|
|
17
17
|
get properties(): Readonly<RowProperties> | undefined;
|
|
18
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* Row height in points; `undefined` leaves the sheet default in force.
|
|
20
|
+
*
|
|
21
|
+
* Not bounded here, deliberately: {@link MAX_ROW_HEIGHT} is what Excel accepts *being set*, but
|
|
22
|
+
* the schema puts no ceiling on `ht` and this setter is also how the reader loads a foreign
|
|
23
|
+
* file, so refusing a taller row would mean refusing a file Excel opens clean. Check against the
|
|
24
|
+
* constant when authoring — Excel silently clamps a taller row on read, so a height above it is
|
|
25
|
+
* one you state and do not get.
|
|
26
|
+
*/
|
|
19
27
|
get height(): number | undefined;
|
|
20
28
|
set height(height: number | undefined);
|
|
21
29
|
/** Whether the row is hidden. */
|
package/dist/core/row.js
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
//
|
|
13
13
|
// Formatting is created on write, never on read. Asking for `sheet.getRow(500)` costs nothing and
|
|
14
14
|
// does not extend the used range; assigning `height` is what materialises the record.
|
|
15
|
-
import { columnToNumber, encodeAddress } from
|
|
16
|
-
import { INTERNAL } from
|
|
15
|
+
import { columnToNumber, encodeAddress } from './address.js';
|
|
16
|
+
import { INTERNAL } from './internal.js';
|
|
17
17
|
export class Row {
|
|
18
18
|
#sheet;
|
|
19
19
|
/** 1-based row number. Fixed for this handle's lifetime. */
|
|
@@ -35,7 +35,15 @@ export class Row {
|
|
|
35
35
|
get properties() {
|
|
36
36
|
return this.#sheet[INTERNAL].rowPropertiesOf(this.number);
|
|
37
37
|
}
|
|
38
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* Row height in points; `undefined` leaves the sheet default in force.
|
|
40
|
+
*
|
|
41
|
+
* Not bounded here, deliberately: {@link MAX_ROW_HEIGHT} is what Excel accepts *being set*, but
|
|
42
|
+
* the schema puts no ceiling on `ht` and this setter is also how the reader loads a foreign
|
|
43
|
+
* file, so refusing a taller row would mean refusing a file Excel opens clean. Check against the
|
|
44
|
+
* constant when authoring — Excel silently clamps a taller row on read, so a height above it is
|
|
45
|
+
* one you state and do not get.
|
|
46
|
+
*/
|
|
39
47
|
get height() {
|
|
40
48
|
return this.#read('height');
|
|
41
49
|
}
|
|
@@ -8,7 +8,7 @@ import type { DifferentialStyle } from './style.ts';
|
|
|
8
8
|
* the style's own `table`/`pivot` flags, not the element names — so the type carries all of them
|
|
9
9
|
* rather than splitting into two enumerations that a caller would have to choose between up front.
|
|
10
10
|
*/
|
|
11
|
-
export declare const TABLE_STYLE_ELEMENT_TYPES: readonly [
|
|
11
|
+
export declare const TABLE_STYLE_ELEMENT_TYPES: readonly ['wholeTable', 'headerRow', 'totalRow', 'firstColumn', 'lastColumn', 'firstRowStripe', 'secondRowStripe', 'firstColumnStripe', 'secondColumnStripe', 'firstHeaderCell', 'lastHeaderCell', 'firstTotalCell', 'lastTotalCell', 'firstSubtotalColumn', 'secondSubtotalColumn', 'thirdSubtotalColumn', 'firstSubtotalRow', 'secondSubtotalRow', 'thirdSubtotalRow', 'blankRow', 'firstColumnSubheading', 'secondColumnSubheading', 'thirdColumnSubheading', 'firstRowSubheading', 'secondRowSubheading', 'thirdRowSubheading', 'pageFieldLabels', 'pageFieldValues'];
|
|
12
12
|
/** One region of a table or pivot that a table style can format. */
|
|
13
13
|
export type TableStyleElementType = (typeof TABLE_STYLE_ELEMENT_TYPES)[number];
|
|
14
14
|
/** The four element types banded across several rows or columns — the only ones {@link TableStyleElement.size} means anything on. */
|
|
@@ -61,7 +61,7 @@ export interface TableStyle {
|
|
|
61
61
|
* `size` outside a stripe is ignored — neither shows up as a repair prompt or a schema error, so the
|
|
62
62
|
* only place to catch them is the call that made them.
|
|
63
63
|
*
|
|
64
|
-
* @throws {
|
|
64
|
+
* @throws {AuthoringError} if the name is empty, or a non-stripe element carries a `size`, or a `size` is not
|
|
65
65
|
* a positive integer.
|
|
66
66
|
*/
|
|
67
67
|
export declare function checkTableStyle(style: TableStyle): void;
|
package/dist/core/table-style.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// gallery ("TableStyleMedium2" and its sixty siblings) is exactly this shape; a workbook that declares
|
|
6
6
|
// its own joins the gallery for that file, and a table reaches it by name through
|
|
7
7
|
// `TableStyleInfo.name`.
|
|
8
|
-
import { AuthoringError } from
|
|
8
|
+
import { AuthoringError } from '../errors.js';
|
|
9
9
|
/**
|
|
10
10
|
* The regions a table style can format (`ST_TableStyleType`).
|
|
11
11
|
*
|
|
@@ -63,7 +63,7 @@ export function isTableStyleElementType(value) {
|
|
|
63
63
|
* `size` outside a stripe is ignored — neither shows up as a repair prompt or a schema error, so the
|
|
64
64
|
* only place to catch them is the call that made them.
|
|
65
65
|
*
|
|
66
|
-
* @throws {
|
|
66
|
+
* @throws {AuthoringError} if the name is empty, or a non-stripe element carries a `size`, or a `size` is not
|
|
67
67
|
* a positive integer.
|
|
68
68
|
*/
|
|
69
69
|
export function checkTableStyle(style) {
|
package/dist/core/table.js
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
// only), a headerless table (data rows only), or a totals-bearing table. The writer is
|
|
7
7
|
// the OOXML gatekeeper for serialization; this model owns the invariants Excel enforces
|
|
8
8
|
// on the *shape* itself: a legal name, at least one column, and at least one row.
|
|
9
|
-
import { AuthoringError } from
|
|
10
|
-
import { decodeAddress, encodeAddress } from
|
|
9
|
+
import { AuthoringError } from '../errors.js';
|
|
10
|
+
import { decodeAddress, encodeAddress } from './address.js';
|
|
11
11
|
/** Copy a style, keeping only its defined fields off the literal so `exactOptionalPropertyTypes`
|
|
12
12
|
* never sees a fabricated `key: undefined` — an absent attribute must stay absent across a copy.
|
|
13
13
|
*
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The number of lines `text` occupies when wrapped at `width` character units - the width unit a
|
|
3
|
+
* column states, so `estimateWrappedLines(cell, sheet.getColumn(2).width ?? 8.43)` is the shape of
|
|
4
|
+
* the call.
|
|
5
|
+
*
|
|
6
|
+
* A hard break opens a line of its own and what follows wraps independently, matching how Excel
|
|
7
|
+
* lays a wrapped cell out. The empty string is one line, not zero: a cell always occupies its row.
|
|
8
|
+
*
|
|
9
|
+
* An estimate, and only ever that. It counts characters, so it is exact for a monospaced face that
|
|
10
|
+
* wraps mid-word and approximate for every other - a run of `W`s wraps sooner on screen than this
|
|
11
|
+
* predicts, a run of `i`s later. Against Excel it reads a shade *low*, because Excel breaks at word
|
|
12
|
+
* boundaries and its usable width is about 0.64 character units under the stated one: measured at
|
|
13
|
+
* 5 lines where Excel laid out 6, 25 where Excel laid out 26. This exists so that a writer can
|
|
14
|
+
* state *a* height rather than leave one to the application that opens the file, and being within a
|
|
15
|
+
* line of the truth is what that needs.
|
|
16
|
+
*
|
|
17
|
+
* @throws {RangeError} if `width` is not a positive finite number - a column of zero width wraps
|
|
18
|
+
* nothing, and silently answering `Infinity` or `NaN` would put that straight into a row height.
|
|
19
|
+
*/
|
|
20
|
+
export declare function estimateWrappedLines(text: string, width: number): number;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// How many lines a wrapped cell takes - the one measurement a writer needs and the format does
|
|
2
|
+
// not record.
|
|
3
|
+
//
|
|
4
|
+
// A row that states no height records no geometry, so the height is whoever opens the file's
|
|
5
|
+
// answer. Excel Desktop's answer is an auto-fit computed on open - promptly and correctly, but
|
|
6
|
+
// saturating at MAX_ROW_HEIGHT, so past ~28 lines it stops answering the question - and no answer
|
|
7
|
+
// at all is what a consumer that does not implement that auto-fit gets, this library's reader
|
|
8
|
+
// included. Stating a height is how the geometry stops depending on the reader, and to state one
|
|
9
|
+
// you have to know the line count. Measured in
|
|
10
|
+
// docs/knowledge/specs/rows-with-no-stated-height-are-autofitted-on-open.md, which also buries the
|
|
11
|
+
// claim this comment used to make, that such a sheet opens with blank unpainted bands. It does not.
|
|
12
|
+
//
|
|
13
|
+
// This counts *characters against a character-unit width*. It does not measure glyphs, and it is
|
|
14
|
+
// not the deferred font-metric question that
|
|
15
|
+
// docs/knowledge/specs/default-font-must-not-be-assumed-for-column-widths.md leaves open: a column
|
|
16
|
+
// width is already expressed in character units, so counting characters is dimensionally honest
|
|
17
|
+
// and needs no metric table. It is also, for the same reason, an approximation for any
|
|
18
|
+
// proportional face - `WWW` and `iii` are one character unit each here and are not on screen.
|
|
19
|
+
/**
|
|
20
|
+
* The number of lines `text` occupies when wrapped at `width` character units - the width unit a
|
|
21
|
+
* column states, so `estimateWrappedLines(cell, sheet.getColumn(2).width ?? 8.43)` is the shape of
|
|
22
|
+
* the call.
|
|
23
|
+
*
|
|
24
|
+
* A hard break opens a line of its own and what follows wraps independently, matching how Excel
|
|
25
|
+
* lays a wrapped cell out. The empty string is one line, not zero: a cell always occupies its row.
|
|
26
|
+
*
|
|
27
|
+
* An estimate, and only ever that. It counts characters, so it is exact for a monospaced face that
|
|
28
|
+
* wraps mid-word and approximate for every other - a run of `W`s wraps sooner on screen than this
|
|
29
|
+
* predicts, a run of `i`s later. Against Excel it reads a shade *low*, because Excel breaks at word
|
|
30
|
+
* boundaries and its usable width is about 0.64 character units under the stated one: measured at
|
|
31
|
+
* 5 lines where Excel laid out 6, 25 where Excel laid out 26. This exists so that a writer can
|
|
32
|
+
* state *a* height rather than leave one to the application that opens the file, and being within a
|
|
33
|
+
* line of the truth is what that needs.
|
|
34
|
+
*
|
|
35
|
+
* @throws {RangeError} if `width` is not a positive finite number - a column of zero width wraps
|
|
36
|
+
* nothing, and silently answering `Infinity` or `NaN` would put that straight into a row height.
|
|
37
|
+
*/
|
|
38
|
+
export function estimateWrappedLines(text, width) {
|
|
39
|
+
if (!Number.isFinite(width) || width <= 0) {
|
|
40
|
+
throw new RangeError(`wrap width ${width} is not a positive finite number of character units`);
|
|
41
|
+
}
|
|
42
|
+
let lines = 0;
|
|
43
|
+
// A lone \r is not a break Excel writes, but a value assembled by a caller on Windows may carry
|
|
44
|
+
// one; counting it as a break costs nothing and mis-counting it as a character would show up as
|
|
45
|
+
// a row one line short.
|
|
46
|
+
for (const segment of text.split(/\r\n?|\n/)) {
|
|
47
|
+
lines += Math.max(1, Math.ceil(segment.length / width));
|
|
48
|
+
}
|
|
49
|
+
return lines;
|
|
50
|
+
}
|
package/dist/core/theme.d.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* `test/corpus/fixtures/excel-oracle/theme-color-index-order.json`. The stylesheet's own default font
|
|
13
13
|
* is the everyday witness: it carries `<color theme="1"/>` and renders black, which is `dk1`.
|
|
14
14
|
*/
|
|
15
|
-
export declare const THEME_COLOR_SLOTS: readonly [
|
|
15
|
+
export declare const THEME_COLOR_SLOTS: readonly ['lt1', 'dk1', 'lt2', 'dk2', 'accent1', 'accent2', 'accent3', 'accent4', 'accent5', 'accent6', 'hlink', 'folHlink'];
|
|
16
16
|
/** One slot of a theme's colour scheme. */
|
|
17
17
|
export type ThemeColorSlot = (typeof THEME_COLOR_SLOTS)[number];
|
|
18
18
|
/**
|
package/dist/core/theme.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// module reads just the `<a:clrScheme>` out of it, because that is the only piece a colour reference
|
|
5
5
|
// needs. Everything else in a theme (the format scheme's gradients, line and effect styles) is
|
|
6
6
|
// nobody's business here.
|
|
7
|
-
import { AuthoringError } from
|
|
7
|
+
import { AuthoringError } from '../errors.js';
|
|
8
8
|
/**
|
|
9
9
|
* The twelve colour-scheme slots **in the order a `theme="n"` attribute indexes them**.
|
|
10
10
|
*
|
package/dist/core/value.d.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import type { Font } from './style.ts';
|
|
2
2
|
/** The observable kind of a cell's value. Both formula shapes report as `Formula`. */
|
|
3
3
|
export declare const ValueType: {
|
|
4
|
-
readonly Null:
|
|
5
|
-
readonly Number:
|
|
6
|
-
readonly String:
|
|
7
|
-
readonly Boolean:
|
|
8
|
-
readonly Date:
|
|
9
|
-
readonly Error:
|
|
10
|
-
readonly Formula:
|
|
11
|
-
readonly RichText:
|
|
12
|
-
readonly Hyperlink:
|
|
4
|
+
readonly Null: 'null';
|
|
5
|
+
readonly Number: 'number';
|
|
6
|
+
readonly String: 'string';
|
|
7
|
+
readonly Boolean: 'boolean';
|
|
8
|
+
readonly Date: 'date';
|
|
9
|
+
readonly Error: 'error';
|
|
10
|
+
readonly Formula: 'formula';
|
|
11
|
+
readonly RichText: 'richText';
|
|
12
|
+
readonly Hyperlink: 'hyperlink';
|
|
13
13
|
};
|
|
14
14
|
export type ValueType = (typeof ValueType)[keyof typeof ValueType];
|
|
15
15
|
/** The canonical Excel error literals a cell (or formula result) can carry. */
|
|
16
|
-
export declare const ERROR_CODES: readonly [
|
|
16
|
+
export declare const ERROR_CODES: readonly ['#N/A', '#REF!', '#NAME?', '#DIV/0!', '#NULL!', '#VALUE!', '#NUM!', '#SPILL!', '#CALC!', '#GETTING_DATA'];
|
|
17
17
|
export type ErrorCode = (typeof ERROR_CODES)[number];
|
|
18
18
|
/** An in-cell error, e.g. `{error: '#REF!'}`. */
|
|
19
19
|
export interface ErrorValue {
|
|
@@ -81,11 +81,32 @@ export interface DataTableFormulaValue {
|
|
|
81
81
|
}
|
|
82
82
|
/** Everything a cell's value can be. `null` is the empty cell. */
|
|
83
83
|
export type CellValue = null | number | string | boolean | Date | ErrorValue | FormulaValue | SharedFormulaValue | DataTableFormulaValue | RichTextValue | HyperlinkValue;
|
|
84
|
+
/**
|
|
85
|
+
* Whether a value is an in-cell error ({@link ErrorValue}). The narrowing counterpart of
|
|
86
|
+
* `detectValueType(value) === ValueType.Error`: use this one when the branch goes on to read
|
|
87
|
+
* `.error`, and {@link detectValueType} when it dispatches over all nine kinds at once.
|
|
88
|
+
*/
|
|
84
89
|
export declare function isErrorValue(value: CellValue): value is ErrorValue;
|
|
90
|
+
/**
|
|
91
|
+
* Whether a value is a cell's own formula ({@link FormulaValue}) — a master, or a formula
|
|
92
|
+
* belonging to no shared group. A shared-formula clone is **not** one of these; see
|
|
93
|
+
* {@link isSharedFormulaValue}. Both report as `ValueType.Formula`, so a caller that means "any
|
|
94
|
+
* formula-shaped cell" wants {@link detectValueType}, not this.
|
|
95
|
+
*/
|
|
85
96
|
export declare function isFormulaValue(value: CellValue): value is FormulaValue;
|
|
97
|
+
/** Whether a value is a clone participating in a shared formula ({@link SharedFormulaValue}). */
|
|
86
98
|
export declare function isSharedFormulaValue(value: CellValue): value is SharedFormulaValue;
|
|
99
|
+
/** Whether a value is a What-If-Analysis data-table formula ({@link DataTableFormulaValue}). */
|
|
87
100
|
export declare function isDataTableFormulaValue(value: CellValue): value is DataTableFormulaValue;
|
|
101
|
+
/**
|
|
102
|
+
* Whether a value is composed of formatted runs ({@link RichTextValue}). This is the test to
|
|
103
|
+
* make before {@link richTextToPlain}, which accepts nothing else.
|
|
104
|
+
*/
|
|
88
105
|
export declare function isRichTextValue(value: CellValue): value is RichTextValue;
|
|
106
|
+
/**
|
|
107
|
+
* Whether a value is a hyperlink ({@link HyperlinkValue}). Note that its `text` is itself either
|
|
108
|
+
* a string or a {@link RichTextValue}, so reading the label out means one more narrowing.
|
|
109
|
+
*/
|
|
89
110
|
export declare function isHyperlinkValue(value: CellValue): value is HyperlinkValue;
|
|
90
111
|
/**
|
|
91
112
|
* Flatten a rich-text value to its plain text by concatenating every run's text in order. This is the
|
|
@@ -93,6 +114,25 @@ export declare function isHyperlinkValue(value: CellValue): value is HyperlinkVa
|
|
|
93
114
|
* the string a rich cell reads as when its formatting is discarded.
|
|
94
115
|
*/
|
|
95
116
|
export declare function richTextToPlain(value: RichTextValue): string;
|
|
117
|
+
/**
|
|
118
|
+
* The plain text of any cell value — total over {@link CellValue}, so a caller reading a sheet
|
|
119
|
+
* whose cells it did not write never has to switch on the union itself.
|
|
120
|
+
*
|
|
121
|
+
* This is the *value's* text, not the cell's *display* text: a number renders as JavaScript
|
|
122
|
+
* renders it, with no number format applied (`0.1 + 0.2` is `"0.30000000000000004"`, a currency
|
|
123
|
+
* cell has no currency sign), because the format lives on the style and this function is given
|
|
124
|
+
* only the value. What each kind yields:
|
|
125
|
+
*
|
|
126
|
+
* - the empty cell (`null`) and an invalid `Date` → `""`, the two ways a cell has no text
|
|
127
|
+
* - a boolean → `"TRUE"` / `"FALSE"`, Excel's own literals rather than JavaScript's
|
|
128
|
+
* - a `Date` → a full ISO-8601 timestamp
|
|
129
|
+
* - an error → its literal, e.g. `"#REF!"` — the same string the grid shows
|
|
130
|
+
* - rich text → every run concatenated ({@link richTextToPlain})
|
|
131
|
+
* - a hyperlink → its label, never its destination
|
|
132
|
+
* - any of the three formula kinds → the text of the *cached result*, and `""` when the cell
|
|
133
|
+
* carries no cached result: the formula source is not text the sheet ever displayed
|
|
134
|
+
*/
|
|
135
|
+
export declare function cellValueToText(value: CellValue): string;
|
|
96
136
|
/**
|
|
97
137
|
* Classify a value into its observable {@link ValueType}. This is total over
|
|
98
138
|
* {@link CellValue}: every legal value has exactly one type. A `Date` is a date even
|