@shbernal/ts-xlsx 1.3.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -10
- package/dist/bytes.d.ts +24 -0
- package/dist/bytes.js +34 -0
- package/dist/core/address.d.ts +72 -3
- package/dist/core/address.js +50 -10
- package/dist/core/autofilter.d.ts +13 -2
- package/dist/core/autofilter.js +35 -10
- package/dist/core/cell.d.ts +17 -16
- package/dist/core/cell.js +3 -7
- package/dist/core/color-resolution.d.ts +8 -8
- package/dist/core/color-resolution.js +7 -8
- package/dist/core/column.d.ts +8 -9
- package/dist/core/column.js +2 -4
- package/dist/core/comment-thread.d.ts +32 -23
- package/dist/core/comment-thread.js +4 -4
- package/dist/core/conditional-formatting-overlay.d.ts +6 -1
- package/dist/core/conditional-formatting-overlay.js +11 -0
- package/dist/core/conditional-formatting.d.ts +48 -8
- package/dist/core/conditional-formatting.js +88 -0
- package/dist/core/data-validation-overlay.d.ts +12 -1
- package/dist/core/data-validation-overlay.js +21 -2
- package/dist/core/data-validation.d.ts +12 -5
- package/dist/core/data-validation.js +34 -0
- package/dist/core/date.d.ts +3 -3
- package/dist/core/formula.d.ts +6 -6
- package/dist/core/grid-edits.d.ts +16 -0
- package/dist/core/grid-edits.js +29 -11
- package/dist/core/grid-shift.d.ts +19 -0
- package/dist/core/grid-shift.js +8 -0
- package/dist/core/image.d.ts +39 -2
- package/dist/core/image.js +10 -0
- package/dist/core/internal.d.ts +9 -1
- package/dist/core/limits.d.ts +4 -4
- package/dist/core/merge.d.ts +17 -12
- package/dist/core/merge.js +36 -5
- package/dist/core/page-setup.d.ts +20 -6
- package/dist/core/page-setup.js +8 -1
- package/dist/core/pivot-table.d.ts +4 -4
- package/dist/core/pivot-table.js +29 -20
- package/dist/core/preserved.d.ts +3 -3
- package/dist/core/protection.d.ts +7 -4
- package/dist/core/protection.js +20 -14
- package/dist/core/range.d.ts +16 -14
- package/dist/core/range.js +5 -5
- package/dist/core/row-input.d.ts +9 -8
- package/dist/core/row-input.js +12 -10
- package/dist/core/row.d.ts +7 -8
- package/dist/core/row.js +2 -4
- package/dist/core/style.d.ts +41 -14
- package/dist/core/style.js +82 -67
- package/dist/core/table-style.d.ts +9 -9
- package/dist/core/table-style.js +1 -1
- package/dist/core/table.d.ts +53 -51
- package/dist/core/table.js +83 -41
- package/dist/core/theme.d.ts +16 -44
- package/dist/core/theme.js +6 -148
- package/dist/core/value.d.ts +7 -7
- package/dist/core/workbook-protection.d.ts +2 -2
- package/dist/core/workbook-styles.d.ts +26 -0
- package/dist/core/workbook-styles.js +48 -0
- package/dist/core/workbook-theme.d.ts +25 -0
- package/dist/core/workbook-theme.js +49 -0
- package/dist/core/workbook-vba.d.ts +17 -0
- package/dist/core/workbook-vba.js +79 -0
- package/dist/core/workbook.d.ts +133 -87
- package/dist/core/workbook.js +74 -133
- package/dist/core/worksheet-comments.d.ts +17 -0
- package/dist/core/worksheet-comments.js +70 -0
- package/dist/core/worksheet-model.d.ts +4 -4
- package/dist/core/worksheet-model.js +1 -0
- package/dist/core/worksheet-pictures.d.ts +29 -0
- package/dist/core/worksheet-pictures.js +42 -0
- package/dist/core/worksheet.d.ts +100 -79
- package/dist/core/worksheet.js +63 -142
- package/dist/customui/errors.d.ts +1 -1
- package/dist/customui/ribbon.d.ts +3 -3
- package/dist/customui/ribbon.js +24 -23
- package/dist/entries/core.d.ts +7 -7
- package/dist/entries/core.js +1 -1
- package/dist/entries/csv.d.ts +1 -1
- package/dist/entries/node-unavailable.d.ts +15 -0
- package/dist/entries/node-unavailable.js +20 -0
- package/dist/entries/node.d.ts +1 -0
- package/dist/entries/node.js +1 -0
- package/dist/entries/vba.d.ts +1 -1
- package/dist/entries/vba.js +1 -1
- package/dist/entries/xlsx.d.ts +1 -1
- package/dist/entries/xlsx.js +1 -1
- package/dist/errors.d.ts +12 -12
- package/dist/io/csv/read.js +2 -3
- package/dist/io/csv/write.d.ts +19 -4
- package/dist/io/csv/write.js +34 -4
- package/dist/io/opc/errors.d.ts +6 -6
- package/dist/io/opc/inflate.d.ts +1 -1
- package/dist/io/opc/inflate.js +2 -12
- package/dist/io/opc/namespaces.d.ts +1 -1
- package/dist/io/opc/read-opc.d.ts +19 -3
- package/dist/io/opc/read-opc.js +14 -8
- package/dist/io/opc/read-options.d.ts +2 -2
- package/dist/io/opc/rels.d.ts +11 -0
- package/dist/io/opc/rels.js +3 -2
- package/dist/io/opc/sniff-format.d.ts +2 -2
- package/dist/io/style/xf-style.d.ts +44 -7
- package/dist/io/style/xf-style.js +27 -0
- package/dist/io/xlsb/errors.d.ts +1 -1
- package/dist/io/xlsb/formula.d.ts +4 -4
- package/dist/io/xlsb/primitives.d.ts +8 -8
- package/dist/io/xlsb/ptg-functions.d.ts +1 -1
- package/dist/io/xlsb/read-styles.js +2 -20
- package/dist/io/xlsb/read.d.ts +2 -2
- package/dist/io/xlsx/cell-accumulator.d.ts +26 -9
- package/dist/io/xlsx/cell-accumulator.js +89 -46
- package/dist/io/xlsx/cell-value.d.ts +3 -3
- package/dist/io/xlsx/cell-value.js +9 -6
- package/dist/io/xlsx/color-xml.d.ts +1 -1
- package/dist/io/xlsx/color-xml.js +18 -23
- package/dist/io/xlsx/comments.d.ts +5 -5
- package/dist/io/xlsx/comments.js +17 -8
- package/dist/io/xlsx/conditional-formatting.d.ts +4 -4
- package/dist/io/xlsx/conditional-formatting.js +64 -58
- package/dist/io/xlsx/data-validation.d.ts +3 -3
- package/dist/io/xlsx/data-validation.js +35 -33
- package/dist/io/xlsx/errors.d.ts +3 -3
- package/dist/io/xlsx/hyperlinks.d.ts +4 -2
- package/dist/io/xlsx/hyperlinks.js +10 -18
- package/dist/io/xlsx/images.d.ts +1 -1
- package/dist/io/xlsx/images.js +25 -28
- package/dist/io/xlsx/namespaces.d.ts +2 -2
- package/dist/io/xlsx/package-plan.js +5 -2
- package/dist/io/xlsx/read-pivot.js +4 -13
- package/dist/io/xlsx/read-rows.d.ts +13 -13
- package/dist/io/xlsx/read-rows.js +19 -55
- package/dist/io/xlsx/read-shared-strings.js +7 -44
- package/dist/io/xlsx/read-styles.d.ts +3 -3
- package/dist/io/xlsx/read-styles.js +42 -66
- package/dist/io/xlsx/read-worksheet.js +73 -129
- package/dist/io/xlsx/read.d.ts +4 -6
- package/dist/io/xlsx/read.js +104 -142
- package/dist/io/xlsx/rich-runs.d.ts +41 -7
- package/dist/io/xlsx/rich-runs.js +94 -30
- package/dist/io/xlsx/rich-text.d.ts +1 -1
- package/dist/io/xlsx/shared-strings.d.ts +2 -2
- package/dist/io/xlsx/sheet-properties.d.ts +1 -1
- package/dist/io/xlsx/sheet-properties.js +14 -10
- package/dist/io/xlsx/styles.d.ts +9 -22
- package/dist/io/xlsx/styles.js +65 -89
- package/dist/io/xlsx/tables.d.ts +2 -2
- package/dist/io/xlsx/tables.js +20 -25
- package/dist/io/xlsx/theme-xml.d.ts +37 -0
- package/dist/io/xlsx/theme-xml.js +145 -0
- package/dist/io/xlsx/threaded-comments.d.ts +18 -27
- package/dist/io/xlsx/threaded-comments.js +26 -38
- package/dist/io/xlsx/workbook-xml.js +14 -8
- package/dist/io/xlsx/worksheet-xml.d.ts +2 -2
- package/dist/io/xlsx/worksheet-xml.js +40 -48
- package/dist/io/xlsx/write-stream.d.ts +23 -16
- package/dist/io/xlsx/write-stream.js +13 -14
- package/dist/io/xlsx/write.d.ts +8 -7
- package/dist/io/xlsx/write.js +6 -3
- package/dist/io/xlsx/x14-ext.d.ts +1 -1
- package/dist/sha512.d.ts +2 -0
- package/dist/sha512.js +146 -0
- package/dist/vba/bytes.d.ts +11 -0
- package/dist/vba/bytes.js +29 -0
- package/dist/vba/cfb-writer.d.ts +1 -1
- package/dist/vba/cfb.d.ts +1 -1
- package/dist/vba/cfb.js +15 -51
- package/dist/vba/codepage.d.ts +2 -2
- package/dist/vba/dir-records.d.ts +53 -0
- package/dist/vba/dir-records.js +28 -0
- package/dist/vba/errors.d.ts +2 -2
- package/dist/vba/index.d.ts +2 -2
- package/dist/vba/index.js +2 -2
- package/dist/vba/ms-ovba.d.ts +1 -1
- package/dist/vba/ms-ovba.js +1 -3
- package/dist/vba/project-editor.d.ts +9 -9
- package/dist/vba/project-editor.js +6 -44
- package/dist/vba/project.d.ts +5 -5
- package/dist/vba/project.js +3 -28
- package/dist/vba/vba-encoding.d.ts +1 -1
- package/dist/xml/errors.d.ts +1 -1
- package/dist/xml/xml-read.d.ts +98 -9
- package/dist/xml/xml-read.js +70 -0
- package/dist/xml/xml.d.ts +74 -10
- package/dist/xml/xml.js +39 -7
- package/package.json +59 -36
package/dist/core/column.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 { Alignment, Border, Fill, Font, Protection } from './style.ts';
|
|
3
4
|
import type { CellValue } from './value.ts';
|
|
4
5
|
import type { ColumnProperties, Worksheet } from './worksheet.ts';
|
|
@@ -6,12 +7,12 @@ export declare class Column {
|
|
|
6
7
|
#private;
|
|
7
8
|
/** 1-based column index. Fixed for this handle's lifetime. */
|
|
8
9
|
readonly index: number;
|
|
9
|
-
/** @throws {RangeError}
|
|
10
|
+
/** @throws {RangeError} unless the index is an integer within Excel's column grid (1..16384). */
|
|
10
11
|
constructor(sheet: Worksheet, index: number);
|
|
11
|
-
/** The column's letters (`"B"`)
|
|
12
|
+
/** The column's letters (`"B"`): the spreadsheet-facing name for {@link index}. */
|
|
12
13
|
get letter(): string;
|
|
13
14
|
/**
|
|
14
|
-
* The column's format record if it has one, else `undefined
|
|
15
|
+
* The column's format record if it has one, else `undefined`: a read that never fabricates, so a
|
|
15
16
|
* serializer can ask every column it visits whether there are attributes to emit without giving
|
|
16
17
|
* each one an empty record. Read-only on purpose: {@link width} and its siblings are how a column
|
|
17
18
|
* is formatted, and they create the record on first write.
|
|
@@ -19,12 +20,12 @@ export declare class Column {
|
|
|
19
20
|
get properties(): Readonly<ColumnProperties> | undefined;
|
|
20
21
|
/**
|
|
21
22
|
* Stable key naming this column so a keyed-object row (see {@link Worksheet.addRow}) can place a
|
|
22
|
-
* value under it by name rather than position. In-memory only
|
|
23
|
+
* value under it by name rather than position. In-memory only: never serialized to OOXML.
|
|
23
24
|
*/
|
|
24
25
|
get key(): string | undefined;
|
|
25
26
|
set key(key: string | undefined);
|
|
26
27
|
/**
|
|
27
|
-
* Column width in character units
|
|
28
|
+
* Column width in character units: digits of the workbook default font's maximum digit width,
|
|
28
29
|
* so what one unit measures moves with that font. `undefined` leaves the sheet default in force.
|
|
29
30
|
*
|
|
30
31
|
* Not bounded here, for the same reason {@link Row.height} is not, and for a stronger one:
|
|
@@ -79,17 +80,15 @@ export declare class Column {
|
|
|
79
80
|
* cell holding `null`.
|
|
80
81
|
*
|
|
81
82
|
* Assigning places each value it names and leaves every other row untouched, mirroring
|
|
82
|
-
* {@link Row.values}
|
|
83
|
+
* {@link Row.values}: a hole or an explicit `undefined` skips that row, and a shorter array does
|
|
83
84
|
* not clear the tail.
|
|
84
85
|
*/
|
|
85
86
|
get values(): (CellValue | undefined)[];
|
|
86
87
|
set values(values: (CellValue | undefined)[]);
|
|
87
88
|
}
|
|
88
|
-
type AssertNever<T extends never> = T;
|
|
89
89
|
/**
|
|
90
|
-
* Compile-time proof that {@link Column} mirrors every {@link ColumnProperties} field
|
|
90
|
+
* Compile-time proof that {@link Column} mirrors every {@link ColumnProperties} field, including
|
|
91
91
|
* the six inherited `CellStyle` facets, so a seventh facet reaches this handle the moment it joins
|
|
92
92
|
* the tuple. See the counterpart on `Row` for why the mirror needs proving rather than reviewing.
|
|
93
93
|
*/
|
|
94
94
|
export type EveryColumnPropertyIsMirrored = AssertNever<Exclude<keyof ColumnProperties, keyof Column & keyof ColumnProperties>>;
|
|
95
|
-
export {};
|
package/dist/core/column.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import { encodeAddress, numberToColumn } from './address.js';
|
|
1
|
+
import { assertColumnInBounds, encodeAddress, numberToColumn } from './address.js';
|
|
2
2
|
import { INTERNAL } from './internal.js';
|
|
3
3
|
export class Column {
|
|
4
4
|
#sheet;
|
|
5
5
|
index;
|
|
6
6
|
constructor(sheet, index) {
|
|
7
|
-
|
|
8
|
-
throw new RangeError(`column ${index} is out of bounds — columns start at 1`);
|
|
9
|
-
}
|
|
7
|
+
assertColumnInBounds(index);
|
|
10
8
|
this.#sheet = sheet;
|
|
11
9
|
this.index = index;
|
|
12
10
|
}
|
|
@@ -1,47 +1,56 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A registered identity a threaded comment can point at
|
|
2
|
+
* A registered identity a threaded comment can point at: an author, or someone `@mentioned` in a
|
|
3
3
|
* message. One `<person>` of the workbook's `xl/persons/person.xml` registry.
|
|
4
4
|
*
|
|
5
5
|
* A single human legitimately has **several** entries: Excel registers a mentioned identity separately
|
|
6
6
|
* from that person's authoring identity, with the same {@link displayName} and {@link userId} but a
|
|
7
|
-
* different {@link id} and a different {@link providerId}. The id is therefore the only identity
|
|
7
|
+
* different {@link id} and a different {@link providerId}. The id is therefore the only identity;
|
|
8
8
|
* see {@link Workbook.getPerson}.
|
|
9
9
|
*/
|
|
10
10
|
export interface Person {
|
|
11
11
|
/** Brace-wrapped GUID this identity is referenced by. The only field that identifies it. */
|
|
12
12
|
readonly id: string;
|
|
13
|
-
/** The name a spreadsheet app shows
|
|
13
|
+
/** The name a spreadsheet app shows. Not unique, and not an identity. */
|
|
14
14
|
readonly displayName: string;
|
|
15
15
|
/** Identity-provider handle, `S::<email>::<tenant-guid>` for an AzureAD account. */
|
|
16
16
|
readonly userId?: string;
|
|
17
|
-
/** The provider that registered this entry
|
|
17
|
+
/** The provider that registered this entry: `AD` for a directory account, `PeoplePicker` for an
|
|
18
18
|
* identity interned by being mentioned. */
|
|
19
19
|
readonly providerId?: string;
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
|
-
* An `@mention`
|
|
23
|
-
* mention chip.
|
|
22
|
+
* An `@mention` as the file spells it: who was named, and the run of {@link Comment.text} that
|
|
23
|
+
* renders as the mention chip.
|
|
24
24
|
*
|
|
25
|
-
* The offsets are only meaningful against that exact text
|
|
25
|
+
* The offsets are only meaningful against that exact text: shift either and a spreadsheet app
|
|
26
26
|
* highlights the wrong words.
|
|
27
|
+
*
|
|
28
|
+
* This is the wire shape, shared with the codec that reads it. {@link Mention} is this plus the
|
|
29
|
+
* identity we resolved the id to, which is the one thing the file does not carry.
|
|
27
30
|
*/
|
|
28
|
-
export interface
|
|
29
|
-
/**
|
|
30
|
-
* The mentioned identity, resolved through the workbook registry. Absent when the file names an id
|
|
31
|
-
* the registry does not hold (a mention left dangling by a foreign generator); {@link personId}
|
|
32
|
-
* still says who was meant.
|
|
33
|
-
*/
|
|
34
|
-
readonly person?: Person;
|
|
31
|
+
export interface MentionRef {
|
|
35
32
|
/** The mentioned {@link Person.id} exactly as written, so a dangling mention stays diagnosable. */
|
|
36
33
|
readonly personId: string;
|
|
37
34
|
/** Excel's own id for this mention, preserved so re-emitting it does not invent a new one. */
|
|
38
35
|
readonly mentionId?: string;
|
|
39
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* 0-based character offset into {@link Comment.text} where the mention starts. Verified against
|
|
38
|
+
* desktop Excel by rendering: the chip covers exactly `[startIndex, startIndex + length)`.
|
|
39
|
+
*/
|
|
40
40
|
readonly startIndex: number;
|
|
41
41
|
/** Length of the mention in characters, **counting the leading `@`** (`@Grace Hopper` is 13). */
|
|
42
42
|
readonly length: number;
|
|
43
43
|
}
|
|
44
|
-
/**
|
|
44
|
+
/** A {@link MentionRef} with its identity resolved against the workbook's person registry. */
|
|
45
|
+
export interface Mention extends MentionRef {
|
|
46
|
+
/**
|
|
47
|
+
* The mentioned identity, resolved through the workbook registry. Absent when the file names an id
|
|
48
|
+
* the registry does not hold (a mention left dangling by a foreign generator); {@link personId}
|
|
49
|
+
* still says who was meant.
|
|
50
|
+
*/
|
|
51
|
+
readonly person?: Person;
|
|
52
|
+
}
|
|
53
|
+
/** One message of a {@link CommentThread}: what a single person wrote, once. */
|
|
45
54
|
export interface Comment {
|
|
46
55
|
/** Brace-wrapped GUID identifying this message, preserved verbatim from the file. */
|
|
47
56
|
readonly id: string;
|
|
@@ -54,7 +63,7 @@ export interface Comment {
|
|
|
54
63
|
readonly personId?: string;
|
|
55
64
|
/**
|
|
56
65
|
* When it was written, verbatim. Excel writes local wall-clock with fractional seconds and no
|
|
57
|
-
* timezone (`2026-07-24T10:56:41.72`), which is not a round-trippable instant
|
|
66
|
+
* timezone (`2026-07-24T10:56:41.72`), which is not a round-trippable instant. Keeping the string
|
|
58
67
|
* spares the reader from inventing a zone the file never stated.
|
|
59
68
|
*/
|
|
60
69
|
readonly date?: string;
|
|
@@ -67,7 +76,7 @@ export interface Comment {
|
|
|
67
76
|
* The one spelling every threaded-comment identifier must take on the wire: brace-wrapped, upper-case hex.
|
|
68
77
|
*
|
|
69
78
|
* Verified against the OOXML schema, which pins `person/@id`, a message's `id`/`personId`/`parentId`, and a
|
|
70
|
-
* mention's `mentionpersonId`/`mentionId` to exactly `\{[0-9A-F]{8}-…\}
|
|
79
|
+
* mention's `mentionpersonId`/`mentionId` to exactly `\{[0-9A-F]{8}-…\}`, so a bare GUID and a lower-case one
|
|
71
80
|
* are each rejected outright. So this normalises rather than merely checking: a caller passing
|
|
72
81
|
* `crypto.randomUUID()` gets a valid file instead of one Excel offers to repair.
|
|
73
82
|
*
|
|
@@ -82,7 +91,7 @@ export declare function commentThreadGuid(value: string, what: string): string;
|
|
|
82
91
|
* `startIndex` and `length` are `xsd:unsignedInt`, so `4294967295` validates and `4294967296` is rejected
|
|
83
92
|
* as "not a valid 'UInt32' value".
|
|
84
93
|
*
|
|
85
|
-
* Wildly beyond any real message, and that is the point
|
|
94
|
+
* Wildly beyond any real message, and that is the point: the ceiling exists so a value from a hostile
|
|
86
95
|
* part can never reach the serialiser. JavaScript spells a large enough number in exponent form
|
|
87
96
|
* (`String(1e21)` is `"1e+21"`), which is not a numeric literal any schema accepts, and one invalid
|
|
88
97
|
* attribute is enough for Excel to offer to repair the whole conversation away.
|
|
@@ -91,8 +100,8 @@ export declare const MENTION_OFFSET_MAX = 4294967295;
|
|
|
91
100
|
/**
|
|
92
101
|
* A mention offset as the wire accepts it: a whole number within {@link MENTION_OFFSET_MAX}.
|
|
93
102
|
*
|
|
94
|
-
* The authoring path alone throws. A file's own mentions are read leniently
|
|
95
|
-
* offset is dropped, keeping the message text and losing only the chip
|
|
103
|
+
* The authoring path alone throws. A file's own mentions are read leniently: one carrying an unusable
|
|
104
|
+
* offset is dropped, keeping the message text and losing only the chip, because a foreign generator's
|
|
96
105
|
* arithmetic is not something a caller can fix, whereas their own is.
|
|
97
106
|
*
|
|
98
107
|
* @throws {SyntaxError} if the value is negative, fractional, or beyond the wire's ceiling.
|
|
@@ -101,8 +110,8 @@ export declare function commentThreadOffset(value: number, what: string): number
|
|
|
101
110
|
/** A conversation anchored to one cell: what was asked, every reply, and whether it was resolved. */
|
|
102
111
|
export interface CommentThread {
|
|
103
112
|
/**
|
|
104
|
-
* A1 reference of the single cell the conversation hangs off, canonicalised
|
|
105
|
-
* a column and a row
|
|
113
|
+
* A1 reference of the single cell the conversation hangs off, canonicalised with no `$` anchors and
|
|
114
|
+
* always a column and a row, so two anchors compare as plain strings and a writer can resolve it without
|
|
106
115
|
* re-validating it.
|
|
107
116
|
*/
|
|
108
117
|
readonly ref: string;
|
|
@@ -2,16 +2,16 @@ const GUID = /^\{?([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a
|
|
|
2
2
|
export function commentThreadGuid(value, what) {
|
|
3
3
|
const match = GUID.exec(value.trim());
|
|
4
4
|
if (match === null) {
|
|
5
|
-
throw new SyntaxError(`${what} must be a GUID
|
|
6
|
-
`"{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
|
|
5
|
+
throw new SyntaxError(`${what} must be a GUID: Excel writes threaded-comment ids as ` +
|
|
6
|
+
`"{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}", but got "${value}"`);
|
|
7
7
|
}
|
|
8
8
|
return `{${match.slice(1).join('-').toUpperCase()}}`;
|
|
9
9
|
}
|
|
10
10
|
export const MENTION_OFFSET_MAX = 0xffff_ffff;
|
|
11
11
|
export function commentThreadOffset(value, what) {
|
|
12
12
|
if (!Number.isInteger(value) || value < 0 || value > MENTION_OFFSET_MAX) {
|
|
13
|
-
throw new SyntaxError(`${what} must be a whole number between 0 and ${MENTION_OFFSET_MAX}
|
|
14
|
-
`written as an unsigned 32-bit integer
|
|
13
|
+
throw new SyntaxError(`${what} must be a whole number between 0 and ${MENTION_OFFSET_MAX}: a mention's span is ` +
|
|
14
|
+
`written as an unsigned 32-bit integer, but got ${value}`);
|
|
15
15
|
}
|
|
16
16
|
return value;
|
|
17
17
|
}
|
|
@@ -2,7 +2,7 @@ import { type ConditionalFormatting } from './conditional-formatting.ts';
|
|
|
2
2
|
export declare class ConditionalFormattingOverlay {
|
|
3
3
|
#private;
|
|
4
4
|
/**
|
|
5
|
-
* Attach a conditional formatting to a target range. `formatting.ref` is an OOXML `sqref
|
|
5
|
+
* Attach a conditional formatting to a target range. `formatting.ref` is an OOXML `sqref`: one
|
|
6
6
|
* range (`"A1:A10"`), a whole column, or several space-separated areas (`"A1:C1 A3:C3"`) sharing one
|
|
7
7
|
* rule set. The block is stored once against the range, defensively copied so the getter never hands
|
|
8
8
|
* back a reference into the caller's object.
|
|
@@ -10,6 +10,11 @@ export declare class ConditionalFormattingOverlay {
|
|
|
10
10
|
add(formatting: ConditionalFormatting): void;
|
|
11
11
|
/** The conditional formattings on this sheet, each bound to its target range, in insertion order. */
|
|
12
12
|
get entries(): readonly ConditionalFormatting[];
|
|
13
|
+
/**
|
|
14
|
+
* Re-anchor every rule set through a row or column splice, so a highlight keeps covering the cells
|
|
15
|
+
* it was written for. A rule set whose every target area fell inside a deleted span goes with them.
|
|
16
|
+
*/
|
|
17
|
+
shift(axis: 'row' | 'col', start: number, count: number, delta: number): void;
|
|
13
18
|
/** Drop every conditional formatting, leaving the overlay empty. */
|
|
14
19
|
clear(): void;
|
|
15
20
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { cloneConditionalFormatting } from './conditional-formatting.js';
|
|
2
|
+
import { replaceContents } from './containers.js';
|
|
3
|
+
import { shiftSqref } from './merge.js';
|
|
2
4
|
export class ConditionalFormattingOverlay {
|
|
3
5
|
#entries = [];
|
|
4
6
|
add(formatting) {
|
|
@@ -7,6 +9,15 @@ export class ConditionalFormattingOverlay {
|
|
|
7
9
|
get entries() {
|
|
8
10
|
return this.#entries;
|
|
9
11
|
}
|
|
12
|
+
shift(axis, start, count, delta) {
|
|
13
|
+
const entries = [];
|
|
14
|
+
for (const entry of this.#entries) {
|
|
15
|
+
const ref = shiftSqref(entry.ref, axis, start, count, delta);
|
|
16
|
+
if (ref !== undefined)
|
|
17
|
+
entries.push({ ...entry, ref });
|
|
18
|
+
}
|
|
19
|
+
replaceContents(this.#entries, entries);
|
|
20
|
+
}
|
|
10
21
|
clear() {
|
|
11
22
|
this.#entries.length = 0;
|
|
12
23
|
}
|
|
@@ -1,26 +1,66 @@
|
|
|
1
1
|
import type { Color, DifferentialStyle } from './style.ts';
|
|
2
|
+
/** How a {@link CfValueObject} reads its `value`: `ST_CfvoType` verbatim. */
|
|
3
|
+
export type CfValueObjectType = 'num' | 'percent' | 'max' | 'min' | 'percentile' | 'formula';
|
|
4
|
+
/** Narrow a raw `<cfvo type>` token to a known {@link CfValueObjectType}. */
|
|
5
|
+
export declare function isCfValueObjectType(value: string): value is CfValueObjectType;
|
|
2
6
|
/**
|
|
3
|
-
* One anchor of a colour-scale, data-bar, or icon-set scale
|
|
7
|
+
* One anchor of a colour-scale, data-bar, or icon-set scale: a "conditional format value object".
|
|
4
8
|
* `type` names how `value` is read: a literal `num`, a `percent`/`percentile` of the range, a
|
|
5
9
|
* `formula`, or the range's own `min`/`max` (which carry no value).
|
|
6
10
|
*/
|
|
7
11
|
export interface CfValueObject {
|
|
8
|
-
type:
|
|
12
|
+
type: CfValueObjectType;
|
|
9
13
|
value?: number | string;
|
|
10
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* What a rule tests, as `<cfRule type>` carries it: `ST_CfType` verbatim.
|
|
17
|
+
*
|
|
18
|
+
* Closed, and stated in full rather than left as `string`, even though the library models only some
|
|
19
|
+
* of these in depth. Depth of modelling and legality are different questions: a `timePeriod` rule
|
|
20
|
+
* whose operands the library never inspects still round-trips, while a token outside this list is one
|
|
21
|
+
* Excel refuses to open, so it is refused on the way in and on the way out alike.
|
|
22
|
+
*/
|
|
23
|
+
export type ConditionalFormattingType = 'expression' | 'cellIs' | 'colorScale' | 'dataBar' | 'iconSet' | 'top10' | 'uniqueValues' | 'duplicateValues' | 'containsText' | 'notContainsText' | 'beginsWith' | 'endsWith' | 'containsBlanks' | 'notContainsBlanks' | 'containsErrors' | 'notContainsErrors' | 'timePeriod' | 'aboveAverage';
|
|
24
|
+
/** Narrow a raw `<cfRule type>` token to a known {@link ConditionalFormattingType}. */
|
|
25
|
+
export declare function isConditionalFormattingType(value: string): value is ConditionalFormattingType;
|
|
26
|
+
/**
|
|
27
|
+
* How a `cellIs` or text rule compares, as `ST_ConditionalFormattingOperator` enumerates it.
|
|
28
|
+
*
|
|
29
|
+
* Overlaps {@link import('./data-validation.ts').DataValidationOperator} in four members and diverges
|
|
30
|
+
* in the rest: this one has the text comparisons a validation has no use for, and spells "does not
|
|
31
|
+
* contain" as `notContains` where nothing else in the format does.
|
|
32
|
+
*/
|
|
33
|
+
export type ConditionalFormattingOperator = 'lessThan' | 'lessThanOrEqual' | 'equal' | 'notEqual' | 'greaterThanOrEqual' | 'greaterThan' | 'between' | 'notBetween' | 'containsText' | 'notContains' | 'beginsWith' | 'endsWith';
|
|
34
|
+
/** Narrow a raw `<cfRule operator>` token to a known {@link ConditionalFormattingOperator}. */
|
|
35
|
+
export declare function isConditionalFormattingOperator(value: string): value is ConditionalFormattingOperator;
|
|
36
|
+
/** The window a `timePeriod` rule matches against, relative to the day the sheet is recalculated. */
|
|
37
|
+
export type CfTimePeriod = 'today' | 'yesterday' | 'tomorrow' | 'last7Days' | 'thisMonth' | 'lastMonth' | 'nextMonth' | 'thisWeek' | 'lastWeek' | 'nextWeek';
|
|
38
|
+
/** Narrow a raw `<cfRule timePeriod>` token to a known {@link CfTimePeriod}. */
|
|
39
|
+
export declare function isCfTimePeriod(value: string): value is CfTimePeriod;
|
|
40
|
+
/**
|
|
41
|
+
* The named icon family an `iconSet` rule draws from, as `ST_IconSetType` enumerates it. The leading
|
|
42
|
+
* digit is the number of icons, which is also how many {@link CfValueObject} anchors the rule needs.
|
|
43
|
+
*
|
|
44
|
+
* The 2009 extension adds three more families (`3Stars`, `3Triangles`, `5Boxes`) under its own
|
|
45
|
+
* namespace. They are absent here because the classic `<iconSet>` element this list types cannot
|
|
46
|
+
* carry them; a file using one states it in the extension, which the library round-trips verbatim.
|
|
47
|
+
*/
|
|
48
|
+
export type IconSetType = '3Arrows' | '3ArrowsGray' | '3Flags' | '3TrafficLights1' | '3TrafficLights2' | '3Signs' | '3Symbols' | '3Symbols2' | '4Arrows' | '4ArrowsGray' | '4RedToBlack' | '4Rating' | '4TrafficLights' | '5Arrows' | '5ArrowsGray' | '5Rating' | '5Quarters';
|
|
49
|
+
/** Narrow a raw `<iconSet iconSet>` token to a known {@link IconSetType}. */
|
|
50
|
+
export declare function isIconSetType(value: string): value is IconSetType;
|
|
11
51
|
/**
|
|
12
52
|
* A single conditional-formatting rule. `type` is the OOXML cfRule type; the remaining fields carry
|
|
13
53
|
* the operands that type needs and are absent otherwise. A rule the library does not model in depth
|
|
14
54
|
* still preserves `type`, `priority`, `operator`, `formulae`, and `dxfId` across a round-trip.
|
|
15
55
|
*/
|
|
16
56
|
export interface ConditionalFormattingRule {
|
|
17
|
-
type:
|
|
18
|
-
/** Evaluation precedence; lower wins. Excel requires one
|
|
57
|
+
type: ConditionalFormattingType;
|
|
58
|
+
/** Evaluation precedence; lower wins. Excel requires one, so the writer supplies it when absent. */
|
|
19
59
|
priority?: number;
|
|
20
60
|
/** Halt evaluation of lower-priority rules on any cell this rule matches. */
|
|
21
61
|
stopIfTrue?: boolean;
|
|
22
62
|
/** cellIs / text comparison operator (`greaterThan`, `between`, `beginsWith`, …). */
|
|
23
|
-
operator?:
|
|
63
|
+
operator?: ConditionalFormattingOperator;
|
|
24
64
|
/** Formula operands: cellIs bounds, an expression predicate, a containsText target formula, … */
|
|
25
65
|
formulae?: (string | number)[];
|
|
26
66
|
/** The literal a containsText / beginsWith / endsWith rule searches for. */
|
|
@@ -42,7 +82,7 @@ export interface ConditionalFormattingRule {
|
|
|
42
82
|
/** A dataBar's axis colour (the zero line between positive and negative bars). An x14 property. */
|
|
43
83
|
axisColor?: Color;
|
|
44
84
|
/** An iconSet's named icon family (e.g. `3TrafficLights1`). */
|
|
45
|
-
iconSet?:
|
|
85
|
+
iconSet?: IconSetType;
|
|
46
86
|
/** top10 rank cutoff. */
|
|
47
87
|
rank?: number;
|
|
48
88
|
/** top10: the rank is a percentage rather than a count. */
|
|
@@ -56,9 +96,9 @@ export interface ConditionalFormattingRule {
|
|
|
56
96
|
/** aboveAverage: match beyond this many standard deviations. */
|
|
57
97
|
stdDev?: number;
|
|
58
98
|
/** timePeriod window (`today`, `lastWeek`, …). */
|
|
59
|
-
timePeriod?:
|
|
99
|
+
timePeriod?: CfTimePeriod;
|
|
60
100
|
}
|
|
61
|
-
/** A set of rules bound to the range(s) they cover. `ref` is an OOXML `sqref
|
|
101
|
+
/** A set of rules bound to the range(s) they cover. `ref` is an OOXML `sqref`: one or more
|
|
62
102
|
* space-separated areas (`"A1:C1 A3:C3 A5:C5"`), the shape Excel writes when one rule is applied to
|
|
63
103
|
* several non-contiguous selections at once. */
|
|
64
104
|
export interface ConditionalFormatting {
|
|
@@ -1,3 +1,91 @@
|
|
|
1
|
+
const CF_VALUE_OBJECT_TYPES = {
|
|
2
|
+
num: true,
|
|
3
|
+
percent: true,
|
|
4
|
+
max: true,
|
|
5
|
+
min: true,
|
|
6
|
+
percentile: true,
|
|
7
|
+
formula: true,
|
|
8
|
+
};
|
|
9
|
+
export function isCfValueObjectType(value) {
|
|
10
|
+
return Object.hasOwn(CF_VALUE_OBJECT_TYPES, value);
|
|
11
|
+
}
|
|
12
|
+
const CONDITIONAL_FORMATTING_TYPES = {
|
|
13
|
+
expression: true,
|
|
14
|
+
cellIs: true,
|
|
15
|
+
colorScale: true,
|
|
16
|
+
dataBar: true,
|
|
17
|
+
iconSet: true,
|
|
18
|
+
top10: true,
|
|
19
|
+
uniqueValues: true,
|
|
20
|
+
duplicateValues: true,
|
|
21
|
+
containsText: true,
|
|
22
|
+
notContainsText: true,
|
|
23
|
+
beginsWith: true,
|
|
24
|
+
endsWith: true,
|
|
25
|
+
containsBlanks: true,
|
|
26
|
+
notContainsBlanks: true,
|
|
27
|
+
containsErrors: true,
|
|
28
|
+
notContainsErrors: true,
|
|
29
|
+
timePeriod: true,
|
|
30
|
+
aboveAverage: true,
|
|
31
|
+
};
|
|
32
|
+
export function isConditionalFormattingType(value) {
|
|
33
|
+
return Object.hasOwn(CONDITIONAL_FORMATTING_TYPES, value);
|
|
34
|
+
}
|
|
35
|
+
const CONDITIONAL_FORMATTING_OPERATORS = {
|
|
36
|
+
lessThan: true,
|
|
37
|
+
lessThanOrEqual: true,
|
|
38
|
+
equal: true,
|
|
39
|
+
notEqual: true,
|
|
40
|
+
greaterThanOrEqual: true,
|
|
41
|
+
greaterThan: true,
|
|
42
|
+
between: true,
|
|
43
|
+
notBetween: true,
|
|
44
|
+
containsText: true,
|
|
45
|
+
notContains: true,
|
|
46
|
+
beginsWith: true,
|
|
47
|
+
endsWith: true,
|
|
48
|
+
};
|
|
49
|
+
export function isConditionalFormattingOperator(value) {
|
|
50
|
+
return Object.hasOwn(CONDITIONAL_FORMATTING_OPERATORS, value);
|
|
51
|
+
}
|
|
52
|
+
const CF_TIME_PERIODS = {
|
|
53
|
+
today: true,
|
|
54
|
+
yesterday: true,
|
|
55
|
+
tomorrow: true,
|
|
56
|
+
last7Days: true,
|
|
57
|
+
thisMonth: true,
|
|
58
|
+
lastMonth: true,
|
|
59
|
+
nextMonth: true,
|
|
60
|
+
thisWeek: true,
|
|
61
|
+
lastWeek: true,
|
|
62
|
+
nextWeek: true,
|
|
63
|
+
};
|
|
64
|
+
export function isCfTimePeriod(value) {
|
|
65
|
+
return Object.hasOwn(CF_TIME_PERIODS, value);
|
|
66
|
+
}
|
|
67
|
+
const ICON_SET_TYPES = {
|
|
68
|
+
'3Arrows': true,
|
|
69
|
+
'3ArrowsGray': true,
|
|
70
|
+
'3Flags': true,
|
|
71
|
+
'3TrafficLights1': true,
|
|
72
|
+
'3TrafficLights2': true,
|
|
73
|
+
'3Signs': true,
|
|
74
|
+
'3Symbols': true,
|
|
75
|
+
'3Symbols2': true,
|
|
76
|
+
'4Arrows': true,
|
|
77
|
+
'4ArrowsGray': true,
|
|
78
|
+
'4RedToBlack': true,
|
|
79
|
+
'4Rating': true,
|
|
80
|
+
'4TrafficLights': true,
|
|
81
|
+
'5Arrows': true,
|
|
82
|
+
'5ArrowsGray': true,
|
|
83
|
+
'5Rating': true,
|
|
84
|
+
'5Quarters': true,
|
|
85
|
+
};
|
|
86
|
+
export function isIconSetType(value) {
|
|
87
|
+
return Object.hasOwn(ICON_SET_TYPES, value);
|
|
88
|
+
}
|
|
1
89
|
export function cloneConditionalFormatting(cf) {
|
|
2
90
|
return { ref: cf.ref, rules: cf.rules.map(cloneRule) };
|
|
3
91
|
}
|
|
@@ -8,9 +8,14 @@ export declare class DataValidationOverlay {
|
|
|
8
8
|
* through {@link at}.
|
|
9
9
|
*
|
|
10
10
|
* Pass `{extended: true}` to mark a rule that belongs in the 2009 extension form
|
|
11
|
-
* (`<x14:dataValidation>`)
|
|
11
|
+
* (`<x14:dataValidation>`), the carrier Excel uses for a list source on another sheet and other
|
|
12
12
|
* shapes the standard element cannot express. The reader sets it for a rule found in that form so a
|
|
13
13
|
* round-trip writes it back there instead of silently corrupting the cross-sheet reference.
|
|
14
|
+
*
|
|
15
|
+
* @throws {AuthoringError} when `sqref` names no area at all. A rule attached to nothing covers no
|
|
16
|
+
* cell and is written back as the same unreadable text, so it is a mistake worth surfacing at the
|
|
17
|
+
* call. The reader does not reach this: it drops such an entry at its own boundary, where a foreign
|
|
18
|
+
* file's malformed attribute is supposed to be dropped.
|
|
14
19
|
*/
|
|
15
20
|
add(sqref: string, rule: DataValidation, options?: {
|
|
16
21
|
extended?: boolean;
|
|
@@ -23,6 +28,12 @@ export declare class DataValidationOverlay {
|
|
|
23
28
|
* validations.
|
|
24
29
|
*/
|
|
25
30
|
at(col: number, row: number): DataValidation | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Re-anchor every rule through a row or column splice, so a dropdown stays on the cells it was
|
|
33
|
+
* attached to rather than on whatever moved into their place. A rule whose every target area fell
|
|
34
|
+
* inside a deleted span is dropped with them.
|
|
35
|
+
*/
|
|
36
|
+
shift(axis: 'row' | 'col', start: number, count: number, delta: number): void;
|
|
26
37
|
/** Drop every validation, leaving the overlay empty. */
|
|
27
38
|
clear(): void;
|
|
28
39
|
}
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
+
import { AuthoringError } from '../errors.js';
|
|
2
|
+
import { replaceContents } from './containers.js';
|
|
1
3
|
import { cloneDataValidation, } from './data-validation.js';
|
|
2
|
-
import { decodeSqrefRects } from './merge.js';
|
|
4
|
+
import { decodeSqrefRects, shiftSqref } from './merge.js';
|
|
3
5
|
export class DataValidationOverlay {
|
|
4
6
|
#entries = [];
|
|
5
7
|
#rects = [];
|
|
6
8
|
add(sqref, rule, options = {}) {
|
|
9
|
+
const rects = decodeSqrefRects(sqref);
|
|
10
|
+
if (rects.length === 0) {
|
|
11
|
+
throw new AuthoringError(`data validation range "${sqref}" names no cells`);
|
|
12
|
+
}
|
|
7
13
|
const stored = cloneDataValidation(rule);
|
|
8
14
|
const entry = { sqref, rule: stored };
|
|
9
15
|
if (options.extended)
|
|
10
16
|
entry.extended = true;
|
|
11
17
|
this.#entries.push(entry);
|
|
12
|
-
this.#rects.push({ rects
|
|
18
|
+
this.#rects.push({ rects, rule: stored });
|
|
13
19
|
}
|
|
14
20
|
get entries() {
|
|
15
21
|
return this.#entries;
|
|
@@ -24,6 +30,19 @@ export class DataValidationOverlay {
|
|
|
24
30
|
}
|
|
25
31
|
return undefined;
|
|
26
32
|
}
|
|
33
|
+
shift(axis, start, count, delta) {
|
|
34
|
+
const entries = [];
|
|
35
|
+
const rects = [];
|
|
36
|
+
for (const entry of this.#entries) {
|
|
37
|
+
const sqref = shiftSqref(entry.sqref, axis, start, count, delta);
|
|
38
|
+
if (sqref === undefined)
|
|
39
|
+
continue;
|
|
40
|
+
entries.push({ ...entry, sqref });
|
|
41
|
+
rects.push({ rects: decodeSqrefRects(sqref), rule: entry.rule });
|
|
42
|
+
}
|
|
43
|
+
replaceContents(this.#entries, entries);
|
|
44
|
+
replaceContents(this.#rects, rects);
|
|
45
|
+
}
|
|
27
46
|
clear() {
|
|
28
47
|
this.#entries.length = 0;
|
|
29
48
|
this.#rects.length = 0;
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
/** The kind of constraint a validation enforces. `list` is a dropdown; `custom` is an arbitrary
|
|
2
|
-
* boolean formula;
|
|
3
|
-
|
|
2
|
+
* boolean formula; `none` constrains nothing and exists only to carry the rule's messages; the rest
|
|
3
|
+
* bound a typed value (`whole`/`decimal`/`date`/`time`/`textLength`). */
|
|
4
|
+
export type DataValidationType = 'none' | 'list' | 'whole' | 'decimal' | 'date' | 'time' | 'textLength' | 'custom';
|
|
5
|
+
/** Narrow a raw `<dataValidation type>` token to a known {@link DataValidationType}. */
|
|
6
|
+
export declare function isDataValidationType(value: string): value is DataValidationType;
|
|
4
7
|
/** How a typed validation compares its operand(s). Absent on a `list`/`custom` rule; defaults to
|
|
5
8
|
* `between` on a typed rule (the value Excel omits from the XML). */
|
|
6
9
|
export type DataValidationOperator = 'between' | 'notBetween' | 'equal' | 'notEqual' | 'greaterThan' | 'lessThan' | 'greaterThanOrEqual' | 'lessThanOrEqual';
|
|
10
|
+
/** Narrow a raw `<dataValidation operator>` token to a known {@link DataValidationOperator}. */
|
|
11
|
+
export declare function isDataValidationOperator(value: string): value is DataValidationOperator;
|
|
7
12
|
/** How Excel reacts to input that fails the rule. */
|
|
8
13
|
export type DataValidationErrorStyle = 'stop' | 'warning' | 'information';
|
|
9
|
-
/**
|
|
14
|
+
/** Narrow a raw `<dataValidation errorStyle>` token to a known {@link DataValidationErrorStyle}. */
|
|
15
|
+
export declare function isDataValidationErrorStyle(value: string): value is DataValidationErrorStyle;
|
|
16
|
+
/** One validation rule. `formulae` holds the operand(s), `formula1` then optional `formula2`: a
|
|
10
17
|
* numeric literal is stored as a number, while a cell reference, defined name, or list source keeps
|
|
11
18
|
* its verbatim string. */
|
|
12
19
|
export interface DataValidation {
|
|
@@ -22,9 +29,9 @@ export interface DataValidation {
|
|
|
22
29
|
prompt?: string;
|
|
23
30
|
promptTitle?: string;
|
|
24
31
|
}
|
|
25
|
-
/** A validation bound to the range(s) it covers. `sqref` is an OOXML `sqref
|
|
32
|
+
/** A validation bound to the range(s) it covers. `sqref` is an OOXML `sqref`: one or more
|
|
26
33
|
* space-separated ranges. `extended` marks a rule stored in the 2009 extension form
|
|
27
|
-
* (`<x14:dataValidation>` inside the worksheet `<extLst>`)
|
|
34
|
+
* (`<x14:dataValidation>` inside the worksheet `<extLst>`), Excel's carrier for validations a
|
|
28
35
|
* legacy `<dataValidation>` cannot express, such as a list source on another sheet. The flag is how
|
|
29
36
|
* a rule read from that form remembers to be written back to it, rather than downgraded to the
|
|
30
37
|
* standard element (which would corrupt a cross-sheet reference). */
|
|
@@ -1,3 +1,37 @@
|
|
|
1
|
+
const DATA_VALIDATION_TYPES = {
|
|
2
|
+
none: true,
|
|
3
|
+
list: true,
|
|
4
|
+
whole: true,
|
|
5
|
+
decimal: true,
|
|
6
|
+
date: true,
|
|
7
|
+
time: true,
|
|
8
|
+
textLength: true,
|
|
9
|
+
custom: true,
|
|
10
|
+
};
|
|
11
|
+
export function isDataValidationType(value) {
|
|
12
|
+
return Object.hasOwn(DATA_VALIDATION_TYPES, value);
|
|
13
|
+
}
|
|
14
|
+
const DATA_VALIDATION_OPERATORS = {
|
|
15
|
+
between: true,
|
|
16
|
+
notBetween: true,
|
|
17
|
+
equal: true,
|
|
18
|
+
notEqual: true,
|
|
19
|
+
greaterThan: true,
|
|
20
|
+
lessThan: true,
|
|
21
|
+
greaterThanOrEqual: true,
|
|
22
|
+
lessThanOrEqual: true,
|
|
23
|
+
};
|
|
24
|
+
export function isDataValidationOperator(value) {
|
|
25
|
+
return Object.hasOwn(DATA_VALIDATION_OPERATORS, value);
|
|
26
|
+
}
|
|
27
|
+
const DATA_VALIDATION_ERROR_STYLES = {
|
|
28
|
+
stop: true,
|
|
29
|
+
warning: true,
|
|
30
|
+
information: true,
|
|
31
|
+
};
|
|
32
|
+
export function isDataValidationErrorStyle(value) {
|
|
33
|
+
return Object.hasOwn(DATA_VALIDATION_ERROR_STYLES, value);
|
|
34
|
+
}
|
|
1
35
|
export function cloneDataValidation(rule) {
|
|
2
36
|
return {
|
|
3
37
|
...rule,
|
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
|
*/
|