@shbernal/ts-xlsx 2.1.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/bytes.d.ts +7 -0
- package/dist/bytes.js +22 -0
- package/dist/core/address.d.ts +60 -2
- package/dist/core/address.js +40 -24
- package/dist/core/autofilter.d.ts +5 -4
- package/dist/core/autofilter.js +34 -35
- package/dist/core/axis-handle.d.ts +10 -0
- package/dist/core/axis-handle.js +17 -0
- package/dist/core/cell.d.ts +25 -0
- package/dist/core/cell.js +9 -3
- package/dist/core/clone.d.ts +29 -0
- package/dist/core/clone.js +24 -0
- package/dist/core/color-resolution.js +2 -4
- package/dist/core/column.d.ts +5 -1
- package/dist/core/column.js +34 -35
- package/dist/core/comment-thread.js +2 -1
- package/dist/core/conditional-formatting-overlay.d.ts +2 -1
- package/dist/core/conditional-formatting-overlay.js +2 -2
- package/dist/core/conditional-formatting.d.ts +14 -6
- package/dist/core/conditional-formatting.js +45 -43
- package/dist/core/containers.d.ts +12 -0
- package/dist/core/containers.js +5 -0
- package/dist/core/data-validation-overlay.d.ts +2 -1
- package/dist/core/data-validation-overlay.js +4 -4
- package/dist/core/data-validation.d.ts +9 -3
- package/dist/core/data-validation.js +21 -18
- package/dist/core/date-format.d.ts +20 -0
- package/dist/core/date-format.js +160 -0
- package/dist/core/date.d.ts +43 -8
- package/dist/core/date.js +18 -2
- package/dist/core/formula.d.ts +26 -0
- package/dist/core/formula.js +20 -4
- package/dist/core/grid-edits.d.ts +2 -3
- package/dist/core/grid-edits.js +69 -70
- package/dist/core/grid-shift.d.ts +58 -9
- package/dist/core/grid-shift.js +26 -4
- package/dist/core/image.d.ts +14 -10
- package/dist/core/image.js +9 -9
- package/dist/core/internal.d.ts +8 -2
- package/dist/core/limits.d.ts +23 -0
- package/dist/core/limits.js +4 -0
- package/dist/core/merge-index.d.ts +31 -0
- package/dist/core/merge-index.js +60 -0
- package/dist/core/merge.d.ts +5 -14
- package/dist/core/merge.js +18 -27
- package/dist/core/page-setup.d.ts +72 -2
- package/dist/core/page-setup.js +34 -8
- package/dist/core/pivot-table.d.ts +1 -1
- package/dist/core/pivot-table.js +67 -53
- package/dist/core/protection.js +2 -11
- package/dist/core/range.js +34 -30
- package/dist/core/row-input.js +2 -2
- package/dist/core/row.d.ts +5 -1
- package/dist/core/row.js +22 -23
- package/dist/core/style.d.ts +134 -75
- package/dist/core/style.js +112 -53
- package/dist/core/table-style.d.ts +1 -1
- package/dist/core/table-style.js +4 -4
- package/dist/core/table.d.ts +28 -10
- package/dist/core/table.js +54 -39
- package/dist/core/theme.js +6 -5
- package/dist/core/used-extent.d.ts +44 -0
- package/dist/core/used-extent.js +102 -0
- package/dist/core/value.d.ts +9 -0
- package/dist/core/value.js +36 -34
- package/dist/core/workbook-media.d.ts +34 -0
- package/dist/core/workbook-media.js +44 -0
- package/dist/core/workbook-styles.d.ts +67 -1
- package/dist/core/workbook-vba.js +3 -2
- package/dist/core/workbook.d.ts +23 -2
- package/dist/core/workbook.js +24 -40
- package/dist/core/worksheet-comments.d.ts +2 -1
- package/dist/core/worksheet-comments.js +20 -13
- package/dist/core/worksheet-merges.d.ts +44 -0
- package/dist/core/worksheet-merges.js +59 -0
- package/dist/core/worksheet-model.d.ts +9 -1
- package/dist/core/worksheet-model.js +24 -9
- package/dist/core/worksheet.d.ts +72 -12
- package/dist/core/worksheet.js +68 -70
- package/dist/customui/ribbon.js +6 -7
- package/dist/entries/core.d.ts +18 -13
- package/dist/entries/core.js +12 -6
- package/dist/entries/xlsx.d.ts +1 -1
- package/dist/errors.d.ts +64 -0
- package/dist/errors.js +22 -0
- package/dist/hex.d.ts +8 -0
- package/dist/hex.js +3 -0
- package/dist/io/csv/delimiter.d.ts +9 -0
- package/dist/io/csv/delimiter.js +6 -0
- package/dist/io/csv/read.js +11 -4
- package/dist/io/csv/write.d.ts +9 -2
- package/dist/io/csv/write.js +9 -38
- package/dist/io/opc/inflate.js +15 -1
- package/dist/io/opc/namespaces.d.ts +16 -0
- package/dist/io/opc/namespaces.js +4 -0
- package/dist/io/opc/part-paths.d.ts +10 -0
- package/dist/io/opc/part-paths.js +16 -1
- package/dist/io/opc/read-opc.d.ts +69 -10
- package/dist/io/opc/read-opc.js +49 -55
- package/dist/io/opc/read-options.d.ts +5 -1
- package/dist/io/opc/rels.d.ts +1 -6
- package/dist/io/opc/rels.js +1 -4
- package/dist/io/opc/sniff-format.d.ts +3 -3
- package/dist/io/opc/sniff-format.js +2 -2
- package/dist/io/style/xf-style.d.ts +48 -2
- package/dist/io/style/xf-style.js +14 -0
- package/dist/io/xlsb/formula.d.ts +2 -2
- package/dist/io/xlsb/formula.js +49 -34
- package/dist/io/xlsb/primitives.js +8 -14
- package/dist/io/xlsb/ptg-functions.d.ts +19 -10
- package/dist/io/xlsb/ptg-functions.js +385 -596
- package/dist/io/xlsb/read-styles.js +50 -83
- package/dist/io/xlsb/read-worksheet.d.ts +20 -1
- package/dist/io/xlsb/read-worksheet.js +73 -89
- package/dist/io/xlsb/read.d.ts +6 -3
- package/dist/io/xlsb/read.js +47 -29
- package/dist/io/xlsb/record-stream.d.ts +30 -0
- package/dist/io/xlsb/record-stream.js +20 -0
- package/dist/io/xlsb/record-types.d.ts +1 -5
- package/dist/io/xlsb/record-types.js +1 -5
- package/dist/io/xlsx/cell-accumulator.d.ts +9 -2
- package/dist/io/xlsx/cell-accumulator.js +32 -9
- package/dist/io/xlsx/cell-style-resolution.d.ts +25 -0
- package/dist/io/xlsx/cell-style-resolution.js +29 -0
- package/dist/io/xlsx/cell-value.d.ts +5 -3
- package/dist/io/xlsx/cell-value.js +13 -15
- package/dist/io/xlsx/color-xml.js +3 -2
- package/dist/io/xlsx/column-budget.d.ts +26 -0
- package/dist/io/xlsx/column-budget.js +22 -0
- package/dist/io/xlsx/comments.d.ts +6 -2
- package/dist/io/xlsx/comments.js +36 -31
- package/dist/io/xlsx/conditional-formatting.d.ts +9 -5
- package/dist/io/xlsx/conditional-formatting.js +51 -46
- package/dist/io/xlsx/data-validation.d.ts +9 -7
- package/dist/io/xlsx/data-validation.js +38 -35
- package/dist/io/xlsx/edit-vba.d.ts +7 -2
- package/dist/io/xlsx/edit-vba.js +15 -29
- package/dist/io/xlsx/font-xml.d.ts +7 -0
- package/dist/io/xlsx/font-xml.js +104 -0
- package/dist/io/xlsx/hyperlinks.d.ts +41 -7
- package/dist/io/xlsx/hyperlinks.js +40 -28
- package/dist/io/xlsx/images.js +24 -25
- package/dist/io/xlsx/namespaces.d.ts +16 -0
- package/dist/io/xlsx/namespaces.js +7 -0
- package/dist/io/xlsx/package-plan.d.ts +23 -3
- package/dist/io/xlsx/package-plan.js +66 -25
- package/dist/io/xlsx/part-names.d.ts +41 -0
- package/dist/io/xlsx/part-names.js +46 -0
- package/dist/io/xlsx/pivot.js +8 -7
- package/dist/io/xlsx/read-parts.d.ts +59 -0
- package/dist/io/xlsx/read-parts.js +252 -0
- package/dist/io/xlsx/read-pivot.js +3 -1
- package/dist/io/xlsx/read-repair.d.ts +26 -0
- package/dist/io/xlsx/read-repair.js +39 -0
- package/dist/io/xlsx/{rich-runs.d.ts → read-rich-runs.d.ts} +1 -1
- package/dist/io/xlsx/{rich-runs.js → read-rich-runs.js} +7 -3
- package/dist/io/xlsx/read-rows.d.ts +18 -5
- package/dist/io/xlsx/read-rows.js +50 -37
- package/dist/io/xlsx/read-shared-strings.js +5 -3
- package/dist/io/xlsx/read-styles.d.ts +1 -6
- package/dist/io/xlsx/read-styles.js +65 -109
- package/dist/io/xlsx/read-workbook-xml.d.ts +36 -0
- package/dist/io/xlsx/read-workbook-xml.js +170 -0
- package/dist/io/xlsx/read-worksheet.d.ts +11 -1
- package/dist/io/xlsx/read-worksheet.js +51 -193
- package/dist/io/xlsx/read.d.ts +5 -13
- package/dist/io/xlsx/read.js +111 -436
- package/dist/io/xlsx/rich-text.js +1 -1
- package/dist/io/xlsx/row-position.d.ts +18 -0
- package/dist/io/xlsx/row-position.js +11 -0
- package/dist/io/xlsx/row-xml.d.ts +128 -0
- package/dist/io/xlsx/row-xml.js +203 -0
- package/dist/io/xlsx/shared-formulas.js +2 -2
- package/dist/io/xlsx/sheet-properties.d.ts +10 -1
- package/dist/io/xlsx/sheet-properties.js +166 -37
- package/dist/io/xlsx/style-elements.d.ts +43 -0
- package/dist/io/xlsx/style-elements.js +156 -0
- package/dist/io/xlsx/styles.d.ts +12 -3
- package/dist/io/xlsx/styles.js +5 -204
- package/dist/io/xlsx/tables.js +11 -14
- package/dist/io/xlsx/theme-xml.d.ts +26 -4
- package/dist/io/xlsx/theme-xml.js +107 -69
- package/dist/io/xlsx/threaded-comments.d.ts +8 -10
- package/dist/io/xlsx/threaded-comments.js +3 -1
- package/dist/io/xlsx/workbook-xml.d.ts +54 -4
- package/dist/io/xlsx/workbook-xml.js +84 -57
- package/dist/io/xlsx/worksheet-xml.d.ts +23 -70
- package/dist/io/xlsx/worksheet-xml.js +59 -242
- package/dist/io/xlsx/write-stream.d.ts +71 -16
- package/dist/io/xlsx/write-stream.js +79 -41
- package/dist/io/xlsx/write.d.ts +6 -2
- package/dist/io/xlsx/write.js +217 -153
- package/dist/rel-type.d.ts +16 -0
- package/dist/rel-type.js +6 -0
- package/dist/token-set.d.ts +28 -0
- package/dist/token-set.js +7 -0
- package/dist/vba/bytes.d.ts +14 -5
- package/dist/vba/bytes.js +16 -6
- package/dist/vba/cfb-format.d.ts +32 -0
- package/dist/vba/cfb-format.js +13 -0
- package/dist/vba/cfb-writer.d.ts +9 -0
- package/dist/vba/cfb-writer.js +28 -25
- package/dist/vba/cfb.d.ts +13 -1
- package/dist/vba/cfb.js +73 -57
- package/dist/vba/codepage.js +2 -1
- package/dist/vba/errors.d.ts +7 -0
- package/dist/vba/ms-ovba.js +79 -23
- package/dist/vba/project-editor.js +35 -40
- package/dist/vba/project.d.ts +11 -1
- package/dist/vba/project.js +40 -21
- package/dist/vba/vba-encoding.js +5 -6
- package/dist/xml/xml-attrs.d.ts +37 -0
- package/dist/xml/xml-attrs.js +30 -0
- package/dist/xml/xml-chars.d.ts +40 -0
- package/dist/xml/xml-chars.js +12 -0
- package/dist/xml/xml-namespaces.d.ts +31 -0
- package/dist/xml/xml-namespaces.js +50 -0
- package/dist/xml/xml-read.d.ts +128 -81
- package/dist/xml/xml-read.js +161 -178
- package/dist/xml/xml-scan.d.ts +78 -0
- package/dist/xml/xml-scan.js +180 -0
- package/dist/xml/xml.d.ts +29 -28
- package/dist/xml/xml.js +24 -24
- package/package.json +13 -9
package/dist/core/workbook.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { type CustomUiDocument } from '../customui/index.ts';
|
|
2
2
|
import { type VbaLibraryReference, type VbaProject, type VbaProjectSignature } from '../vba/index.ts';
|
|
3
3
|
import { type Person } from './comment-thread.ts';
|
|
4
|
-
import
|
|
4
|
+
import type { DateEpoch } from './date.ts';
|
|
5
|
+
import type { WorkbookImage, WorksheetImages } from './image.ts';
|
|
5
6
|
import { INTERNAL } from './internal.ts';
|
|
6
7
|
import type { PreservedPart, PreservedRootReference } from './preserved.ts';
|
|
7
|
-
import type { Color, Font
|
|
8
|
+
import type { Color, Font } from './style.ts';
|
|
8
9
|
import { type TableStyle } from './table-style.ts';
|
|
9
10
|
import { type ThemeColorScheme, type ThemeFontScheme, type ThemeOverrides } from './theme.ts';
|
|
10
11
|
import type { WorkbookProtection } from './workbook-protection.ts';
|
|
12
|
+
import { type NamedCellStyle, type TableStyleTable } from './workbook-styles.ts';
|
|
11
13
|
import { type DeclaredThemeSchemes } from './workbook-theme.ts';
|
|
12
14
|
import { type Visibility, Worksheet, type WorksheetState } from './worksheet.ts';
|
|
13
15
|
/**
|
|
@@ -155,6 +157,25 @@ export declare class Workbook {
|
|
|
155
157
|
* workbook whose cached results are authoritative stays unmarked.
|
|
156
158
|
*/
|
|
157
159
|
fullCalcOnLoad: boolean;
|
|
160
|
+
/**
|
|
161
|
+
* Which date system this workbook's serials count in: `1900` (the Windows default) or `1904` (the
|
|
162
|
+
* `date1904` flag of `<workbookPr>`, Excel for Macintosh's original). It governs every conversion
|
|
163
|
+
* between a `Date` and the number a cell actually stores, in both directions, so setting it after
|
|
164
|
+
* cells hold dates changes what those cells mean rather than converting them.
|
|
165
|
+
*
|
|
166
|
+
* Read from the file and written back, because dropping it is not a cosmetic loss: the serials stay
|
|
167
|
+
* as they were and the consumer re-reads them under the other system, so the workbook silently
|
|
168
|
+
* changes meaning by four years and a day.
|
|
169
|
+
*/
|
|
170
|
+
dateEpoch: DateEpoch;
|
|
171
|
+
/**
|
|
172
|
+
* The workbook's VBA identity (`<workbookPr codeName>`), the name a macro means by `ThisWorkbook`.
|
|
173
|
+
* Undefined for a workbook with no VBA project, which is what Excel writes for one.
|
|
174
|
+
*
|
|
175
|
+
* Preserved rather than modeled: nothing here reads it, but a `.xlsm` whose code name is dropped on
|
|
176
|
+
* a round trip has had the binding between its macros and its document cut.
|
|
177
|
+
*/
|
|
178
|
+
codeName?: string;
|
|
158
179
|
/**
|
|
159
180
|
* Workbook-level structure/window protection: the OOXML `<workbookProtection>` element. Absent by
|
|
160
181
|
* default (an unprotected workbook). Set it to lock the workbook shell, or leave it as read from a
|
package/dist/core/workbook.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { isCustomUiRelType, parseCustomUi } from '../customui/index.js';
|
|
2
|
-
import { AuthoringError } from '../errors.js';
|
|
2
|
+
import { AuthoringError, quoted } from '../errors.js';
|
|
3
3
|
import { addVbaReference, removeVbaModule, } from '../vba/index.js';
|
|
4
4
|
import { commentThreadGuid } from './comment-thread.js';
|
|
5
|
-
import { findRegisteredImage, normalizeImageExtension, } from './image.js';
|
|
6
5
|
import { INTERNAL } from './internal.js';
|
|
6
|
+
import { INVALID_SHEET_NAME_CHARS, MAX_SHEET_NAME_LENGTH } from './limits.js';
|
|
7
7
|
import { checkTableStyle } from './table-style.js';
|
|
8
8
|
import { OFFICE_BODY_FACE, THEME_COLOR_SLOTS, } from './theme.js';
|
|
9
|
+
import { WorkbookMedia } from './workbook-media.js';
|
|
9
10
|
import { WorkbookStyleTables } from './workbook-styles.js';
|
|
10
11
|
import { WorkbookTheme } from './workbook-theme.js';
|
|
11
12
|
import { WorkbookVbaProject } from './workbook-vba.js';
|
|
@@ -17,16 +18,16 @@ export const DEFAULT_WORKBOOK_VIEW = {
|
|
|
17
18
|
height: 12220,
|
|
18
19
|
activeTab: 0,
|
|
19
20
|
};
|
|
20
|
-
const MAX_SHEET_NAME_LENGTH = 31;
|
|
21
|
-
const INVALID_SHEET_NAME_CHARS = /[*?:\\/[\]]/;
|
|
22
21
|
export class Workbook {
|
|
23
22
|
properties = {};
|
|
24
23
|
view = { ...DEFAULT_WORKBOOK_VIEW };
|
|
25
24
|
fullCalcOnLoad = false;
|
|
25
|
+
dateEpoch = 1900;
|
|
26
|
+
codeName;
|
|
26
27
|
protection = undefined;
|
|
27
28
|
#worksheets = [];
|
|
28
29
|
#nextSheetId = 1;
|
|
29
|
-
#media =
|
|
30
|
+
#media = new WorkbookMedia();
|
|
30
31
|
#definedNames = [];
|
|
31
32
|
#styles = new WorkbookStyleTables();
|
|
32
33
|
#theme = new WorkbookTheme(() => this.#styles.indexedPalette());
|
|
@@ -37,7 +38,7 @@ export class Workbook {
|
|
|
37
38
|
}
|
|
38
39
|
get activeTabIndex() {
|
|
39
40
|
const { activeTab } = this.view;
|
|
40
|
-
return Number.isInteger(activeTab) && activeTab
|
|
41
|
+
return Number.isInteger(activeTab) && activeTab >= 0 && activeTab < this.#worksheets.length
|
|
41
42
|
? activeTab
|
|
42
43
|
: 0;
|
|
43
44
|
}
|
|
@@ -180,31 +181,22 @@ export class Workbook {
|
|
|
180
181
|
return this.#persons.get(id);
|
|
181
182
|
}
|
|
182
183
|
addImage(options) {
|
|
183
|
-
this.#media.
|
|
184
|
-
extension: normalizeImageExtension(options.extension, options.buffer),
|
|
185
|
-
data: options.buffer,
|
|
186
|
-
});
|
|
187
|
-
return this.#media.length - 1;
|
|
184
|
+
return this.#media.register(options.extension, options.buffer);
|
|
188
185
|
}
|
|
189
186
|
get media() {
|
|
190
|
-
return this.#media;
|
|
187
|
+
return this.#media.all;
|
|
191
188
|
}
|
|
192
189
|
getImage(id) {
|
|
193
|
-
return this.#media
|
|
190
|
+
return this.#media.get(id);
|
|
194
191
|
}
|
|
195
192
|
exportImages(sheet) {
|
|
196
|
-
const resolve = (id) => {
|
|
197
|
-
const image = this.#media[id];
|
|
198
|
-
if (image === undefined) {
|
|
199
|
-
throw new AuthoringError(`worksheet "${sheet.name}" shows image id ${id}, which is not registered on this ` +
|
|
200
|
-
"workbook: a sheet's images can only be exported by the workbook that holds them");
|
|
201
|
-
}
|
|
202
|
-
return image;
|
|
203
|
-
};
|
|
204
193
|
const background = sheet.backgroundImageId;
|
|
205
194
|
return {
|
|
206
|
-
anchored: sheet.images.map(({ imageId, anchor }) => ({
|
|
207
|
-
|
|
195
|
+
anchored: sheet.images.map(({ imageId, anchor }) => ({
|
|
196
|
+
image: this.#media.require(imageId, sheet.name),
|
|
197
|
+
anchor,
|
|
198
|
+
})),
|
|
199
|
+
background: background === undefined ? undefined : this.#media.require(background, sheet.name),
|
|
208
200
|
};
|
|
209
201
|
}
|
|
210
202
|
importImages(sheet, images) {
|
|
@@ -212,20 +204,12 @@ export class Workbook {
|
|
|
212
204
|
sheet.removeImage(id);
|
|
213
205
|
sheet.removeBackgroundImage();
|
|
214
206
|
for (const { image, anchor } of images.anchored) {
|
|
215
|
-
sheet.addImageAnchor(this.#
|
|
207
|
+
sheet.addImageAnchor(this.#media.registerExisting(image), anchor);
|
|
216
208
|
}
|
|
217
209
|
if (images.background !== undefined) {
|
|
218
|
-
sheet.addBackgroundImage(this.#
|
|
210
|
+
sheet.addBackgroundImage(this.#media.registerExisting(images.background));
|
|
219
211
|
}
|
|
220
212
|
}
|
|
221
|
-
#registerImage(image) {
|
|
222
|
-
const candidate = {
|
|
223
|
-
extension: normalizeImageExtension(image.extension, image.data),
|
|
224
|
-
data: image.data,
|
|
225
|
-
};
|
|
226
|
-
return (findRegisteredImage(this.#media, candidate) ??
|
|
227
|
-
this.addImage({ buffer: candidate.data, extension: candidate.extension }));
|
|
228
|
-
}
|
|
229
213
|
get definedNames() {
|
|
230
214
|
return this.#definedNames;
|
|
231
215
|
}
|
|
@@ -234,7 +218,7 @@ export class Workbook {
|
|
|
234
218
|
throw new AuthoringError('a defined name cannot be empty');
|
|
235
219
|
}
|
|
236
220
|
if (definedName.scope !== undefined && this.getWorksheet(definedName.scope) === undefined) {
|
|
237
|
-
throw new AuthoringError(`defined name
|
|
221
|
+
throw new AuthoringError(`defined name ${quoted(definedName.name)} is scoped to unknown worksheet ${quoted(definedName.scope)}`);
|
|
238
222
|
}
|
|
239
223
|
this.#definedNames.push(definedName);
|
|
240
224
|
}
|
|
@@ -255,11 +239,11 @@ export class Workbook {
|
|
|
255
239
|
const sheet = this.getWorksheet(nameOrId);
|
|
256
240
|
if (sheet !== undefined)
|
|
257
241
|
return sheet;
|
|
258
|
-
const wanted = typeof nameOrId === 'number' ? `id ${nameOrId}` :
|
|
242
|
+
const wanted = typeof nameOrId === 'number' ? `id ${nameOrId}` : quoted(nameOrId);
|
|
259
243
|
if (this.#worksheets.length === 0) {
|
|
260
244
|
throw new AuthoringError(`no worksheet ${wanted}: this workbook has no worksheets`);
|
|
261
245
|
}
|
|
262
|
-
const have = this.#worksheets.map((sheet) =>
|
|
246
|
+
const have = this.#worksheets.map((sheet) => quoted(sheet.name)).join(', ');
|
|
263
247
|
throw new AuthoringError(`no worksheet ${wanted}; this workbook has ${have}`);
|
|
264
248
|
}
|
|
265
249
|
#assertValidSheetName(name) {
|
|
@@ -267,16 +251,16 @@ export class Workbook {
|
|
|
267
251
|
throw new AuthoringError('worksheet name cannot be empty');
|
|
268
252
|
}
|
|
269
253
|
if (name.length > MAX_SHEET_NAME_LENGTH) {
|
|
270
|
-
throw new AuthoringError(`worksheet name
|
|
254
|
+
throw new AuthoringError(`worksheet name ${quoted(name)} exceeds the ${MAX_SHEET_NAME_LENGTH}-character limit`);
|
|
271
255
|
}
|
|
272
256
|
if (INVALID_SHEET_NAME_CHARS.test(name)) {
|
|
273
|
-
throw new AuthoringError(`worksheet name
|
|
257
|
+
throw new AuthoringError(`worksheet name ${quoted(name)} contains a character Excel forbids (* ? : \\ / [ ])`);
|
|
274
258
|
}
|
|
275
259
|
if (name.startsWith("'") || name.endsWith("'")) {
|
|
276
|
-
throw new AuthoringError(`worksheet name
|
|
260
|
+
throw new AuthoringError(`worksheet name ${quoted(name)} cannot start or end with an apostrophe`);
|
|
277
261
|
}
|
|
278
262
|
if (this.getWorksheet(name) !== undefined) {
|
|
279
|
-
throw new AuthoringError(`a worksheet named
|
|
263
|
+
throw new AuthoringError(`a worksheet named ${quoted(name)} already exists (names are case-insensitive)`);
|
|
280
264
|
}
|
|
281
265
|
}
|
|
282
266
|
[INTERNAL] = {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type CommentThread } from './comment-thread.ts';
|
|
2
|
+
import { type AxisSplice } from './grid-shift.ts';
|
|
2
3
|
export declare class WorksheetComments {
|
|
3
4
|
#private;
|
|
4
5
|
constructor(sheetName: () => string);
|
|
@@ -12,6 +13,6 @@ export declare class WorksheetComments {
|
|
|
12
13
|
* the cell, so a thread left behind would put a note on one cell and its conversation on another,
|
|
13
14
|
* a pairing the writer emits and Excel refuses.
|
|
14
15
|
*/
|
|
15
|
-
shift(
|
|
16
|
+
shift(splice: AxisSplice): void;
|
|
16
17
|
restore(threads: readonly CommentThread[]): void;
|
|
17
18
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { quoted } from '../errors.js';
|
|
1
2
|
import { decodeCellRef, encodeAddress } from './address.js';
|
|
2
3
|
import { commentThreadGuid, commentThreadOffset } from './comment-thread.js';
|
|
3
4
|
import { replaceContents } from './containers.js';
|
|
4
|
-
import {
|
|
5
|
+
import { shiftPoint } from './grid-shift.js';
|
|
5
6
|
export class WorksheetComments {
|
|
6
7
|
#sheetName;
|
|
7
8
|
#threads = [];
|
|
9
|
+
#takenIds = new Set();
|
|
8
10
|
constructor(sheetName) {
|
|
9
11
|
this.#sheetName = sheetName;
|
|
10
12
|
}
|
|
@@ -12,14 +14,14 @@ export class WorksheetComments {
|
|
|
12
14
|
return this.#threads;
|
|
13
15
|
}
|
|
14
16
|
add(thread) {
|
|
15
|
-
const
|
|
17
|
+
const claimed = new Set();
|
|
16
18
|
const comments = thread.comments.map((comment) => {
|
|
17
19
|
const id = commentThreadGuid(comment.id, 'a comment id');
|
|
18
|
-
if (
|
|
19
|
-
throw new SyntaxError(`a comment id must be unique within a sheet, but
|
|
20
|
+
if (this.#takenIds.has(id) || claimed.has(id)) {
|
|
21
|
+
throw new SyntaxError(`a comment id must be unique within a sheet, but ${quoted(id)} is already used on ${quoted(this.#sheetName())}: ` +
|
|
20
22
|
'a reply and the legacy fallback comment both find their thread by it');
|
|
21
23
|
}
|
|
22
|
-
|
|
24
|
+
claimed.add(id);
|
|
23
25
|
return {
|
|
24
26
|
...comment,
|
|
25
27
|
id,
|
|
@@ -38,30 +40,35 @@ export class WorksheetComments {
|
|
|
38
40
|
};
|
|
39
41
|
});
|
|
40
42
|
this.#threads.push({ ...thread, ref: anchorRef(thread.ref), comments });
|
|
43
|
+
for (const id of claimed)
|
|
44
|
+
this.#takenIds.add(id);
|
|
41
45
|
}
|
|
42
46
|
at(reference) {
|
|
43
47
|
const anchor = anchorRef(reference);
|
|
44
48
|
return this.#threads.find((thread) => thread.ref === anchor);
|
|
45
49
|
}
|
|
46
|
-
shift(
|
|
50
|
+
shift(splice) {
|
|
47
51
|
const survivors = [];
|
|
48
52
|
for (const thread of this.#threads) {
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
if (
|
|
53
|
+
const anchor = decodeCellRef(thread.ref);
|
|
54
|
+
const moved = shiftPoint(anchor, splice);
|
|
55
|
+
if (moved === undefined)
|
|
52
56
|
continue;
|
|
53
|
-
|
|
54
|
-
if (moved === line) {
|
|
57
|
+
if (moved.col === anchor.col && moved.row === anchor.row) {
|
|
55
58
|
survivors.push(thread);
|
|
56
59
|
continue;
|
|
57
60
|
}
|
|
58
|
-
|
|
59
|
-
survivors.push({ ...thread, ref });
|
|
61
|
+
survivors.push({ ...thread, ref: encodeAddress(moved.col, moved.row) });
|
|
60
62
|
}
|
|
61
63
|
replaceContents(this.#threads, survivors);
|
|
62
64
|
}
|
|
63
65
|
restore(threads) {
|
|
64
66
|
replaceContents(this.#threads, threads);
|
|
67
|
+
this.#takenIds.clear();
|
|
68
|
+
for (const thread of threads) {
|
|
69
|
+
for (const comment of thread.comments)
|
|
70
|
+
this.#takenIds.add(comment.id);
|
|
71
|
+
}
|
|
65
72
|
}
|
|
66
73
|
}
|
|
67
74
|
function anchorRef(reference) {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { MergeRect } from './merge.ts';
|
|
2
|
+
/** What removing a declared range did, which is two answers because a range and a rectangle are not
|
|
3
|
+
* the same thing: an unbounded whole-row/column merge is declared but has no rectangle, so dropping
|
|
4
|
+
* it leaves every geometry derived from the rectangles (the used extent, the index) still valid. */
|
|
5
|
+
export interface MergeRemoval {
|
|
6
|
+
/** Whether a merge with this exact range string was declared. */
|
|
7
|
+
readonly existed: boolean;
|
|
8
|
+
/** Whether a rectangle went with it, so anything derived from the rectangles is now stale. */
|
|
9
|
+
readonly rectsChanged: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare class WorksheetMerges {
|
|
12
|
+
#private;
|
|
13
|
+
/** The declared ranges, in the order they were added. Live, not a copy. */
|
|
14
|
+
get ranges(): readonly string[];
|
|
15
|
+
/**
|
|
16
|
+
* The bounded regions as rectangles. Live, and its *identity* is stable for the sheet's lifetime:
|
|
17
|
+
* {@link UsedExtent} holds this array by reference, so every rewrite here goes through
|
|
18
|
+
* `replaceContents` rather than reassignment.
|
|
19
|
+
*/
|
|
20
|
+
get rects(): readonly MergeRect[];
|
|
21
|
+
/**
|
|
22
|
+
* Declare a merged range, returning the rectangle it covers, or `undefined` for an unbounded
|
|
23
|
+
* whole-row/column range, which is declared and overlap-checks against nothing.
|
|
24
|
+
*
|
|
25
|
+
* @throws {AuthoringError} if the range overlaps an already-merged region. Excel forbids
|
|
26
|
+
* overlapping merges and writes such geometry as a file it then offers to repair.
|
|
27
|
+
*/
|
|
28
|
+
add(range: string): MergeRect | undefined;
|
|
29
|
+
/** Drop a declared range and, with it, the rectangle it covers. The inverse of {@link add}. */
|
|
30
|
+
remove(range: string): MergeRemoval;
|
|
31
|
+
/**
|
|
32
|
+
* Resolve a position to the top-left of the region covering it, or to itself when none does. This
|
|
33
|
+
* is what makes a write through a covered address land on the region's master.
|
|
34
|
+
*/
|
|
35
|
+
masterOf(row: number, col: number): {
|
|
36
|
+
row: number;
|
|
37
|
+
col: number;
|
|
38
|
+
};
|
|
39
|
+
/** Replace every declared range and rectangle at once: what a structural splice re-anchors to. */
|
|
40
|
+
replaceAll(ranges: readonly string[], rects: readonly MergeRect[]): void;
|
|
41
|
+
/** Report that something outside has rewritten the grid under these regions. */
|
|
42
|
+
invalidate(): void;
|
|
43
|
+
clear(): void;
|
|
44
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { AuthoringError, quoted } from '../errors.js';
|
|
2
|
+
import { boundedRect, decodeRange } from './address.js';
|
|
3
|
+
import { replaceContents } from './containers.js';
|
|
4
|
+
import { MergeIndex } from './merge-index.js';
|
|
5
|
+
export class WorksheetMerges {
|
|
6
|
+
#ranges = [];
|
|
7
|
+
#rects = [];
|
|
8
|
+
#index = new MergeIndex(this.#rects);
|
|
9
|
+
get ranges() {
|
|
10
|
+
return this.#ranges;
|
|
11
|
+
}
|
|
12
|
+
get rects() {
|
|
13
|
+
return this.#rects;
|
|
14
|
+
}
|
|
15
|
+
add(range) {
|
|
16
|
+
const rect = boundedRect(decodeRange(range));
|
|
17
|
+
if (rect !== undefined) {
|
|
18
|
+
if (this.#index.overlapping(rect) !== undefined) {
|
|
19
|
+
throw new AuthoringError(`merged range ${quoted(range)} overlaps an existing merged region`);
|
|
20
|
+
}
|
|
21
|
+
this.#rects.push(rect);
|
|
22
|
+
this.#index.note(rect);
|
|
23
|
+
}
|
|
24
|
+
this.#ranges.push(range);
|
|
25
|
+
return rect;
|
|
26
|
+
}
|
|
27
|
+
remove(range) {
|
|
28
|
+
const index = this.#ranges.indexOf(range);
|
|
29
|
+
if (index === -1)
|
|
30
|
+
return { existed: false, rectsChanged: false };
|
|
31
|
+
this.#ranges.splice(index, 1);
|
|
32
|
+
const rect = boundedRect(decodeRange(range));
|
|
33
|
+
if (rect === undefined)
|
|
34
|
+
return { existed: true, rectsChanged: false };
|
|
35
|
+
const { top, left, bottom, right } = rect;
|
|
36
|
+
const at = this.#rects.findIndex((r) => r.top === top && r.left === left && r.bottom === bottom && r.right === right);
|
|
37
|
+
if (at === -1)
|
|
38
|
+
return { existed: true, rectsChanged: false };
|
|
39
|
+
this.#rects.splice(at, 1);
|
|
40
|
+
this.#index.invalidate();
|
|
41
|
+
return { existed: true, rectsChanged: true };
|
|
42
|
+
}
|
|
43
|
+
masterOf(row, col) {
|
|
44
|
+
return this.#index.masterOf(row, col);
|
|
45
|
+
}
|
|
46
|
+
replaceAll(ranges, rects) {
|
|
47
|
+
replaceContents(this.#ranges, ranges);
|
|
48
|
+
replaceContents(this.#rects, rects);
|
|
49
|
+
this.#index.invalidate();
|
|
50
|
+
}
|
|
51
|
+
invalidate() {
|
|
52
|
+
this.#index.invalidate();
|
|
53
|
+
}
|
|
54
|
+
clear() {
|
|
55
|
+
this.#ranges.length = 0;
|
|
56
|
+
this.#rects.length = 0;
|
|
57
|
+
this.#index.invalidate();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -3,7 +3,15 @@ import type { Worksheet, WorksheetModel } from './worksheet.ts';
|
|
|
3
3
|
/** One field of a {@link WorksheetModel}, with both directions of its round-trip declared together. */
|
|
4
4
|
interface ModelFacet<K extends keyof WorksheetModel = keyof WorksheetModel> {
|
|
5
5
|
readonly key: K;
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Produce the field's value, in a form a caller cannot mutate the sheet through.
|
|
8
|
+
*
|
|
9
|
+
* Copying is one way to get there and the type is the other. `tabColor`, `autoFilter` and
|
|
10
|
+
* `protection` are handed back by reference precisely because their types are readonly all the way
|
|
11
|
+
* down, so there is nothing to defend against and a clone would only be one more shape to keep in
|
|
12
|
+
* step with its declaration. Every other field is a mutable record or array and is copied, which is
|
|
13
|
+
* where the spreads below come from.
|
|
14
|
+
*/
|
|
7
15
|
readonly read: (sheet: Worksheet) => WorksheetModel[K];
|
|
8
16
|
/**
|
|
9
17
|
* Apply the field to a sheet whose content has already been reset. Takes the whole model rather
|
|
@@ -6,6 +6,21 @@ import { INTERNAL } from './internal.js';
|
|
|
6
6
|
function facet(key, read, write) {
|
|
7
7
|
return { key, read, write: (sheet, model) => write(sheet, model[key]) };
|
|
8
8
|
}
|
|
9
|
+
function recordFacet(key) {
|
|
10
|
+
return {
|
|
11
|
+
key,
|
|
12
|
+
read: (sheet) => ({ ...sheet[key] }),
|
|
13
|
+
write: (sheet, model) => overwrite(sheet[key], model[key]),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function recordsFacet(key) {
|
|
17
|
+
const copy = (breaks) => breaks.map((brk) => ({ ...brk }));
|
|
18
|
+
return {
|
|
19
|
+
key,
|
|
20
|
+
read: (sheet) => copy(sheet[key]),
|
|
21
|
+
write: (sheet, model) => replaceContents(sheet[key], copy(model[key])),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
9
24
|
export const WORKSHEET_MODEL_FACETS = [
|
|
10
25
|
facet('state', (sheet) => sheet.state, (sheet, value) => {
|
|
11
26
|
sheet.state = value;
|
|
@@ -13,15 +28,15 @@ export const WORKSHEET_MODEL_FACETS = [
|
|
|
13
28
|
facet('tabColor', (sheet) => sheet.tabColor, (sheet, value) => {
|
|
14
29
|
sheet.tabColor = value;
|
|
15
30
|
}),
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
31
|
+
recordFacet('properties'),
|
|
32
|
+
recordFacet('outline'),
|
|
33
|
+
recordFacet('view'),
|
|
34
|
+
recordFacet('pageSetup'),
|
|
35
|
+
recordFacet('printOptions'),
|
|
36
|
+
recordFacet('pageMargins'),
|
|
37
|
+
recordFacet('headerFooter'),
|
|
38
|
+
recordsFacet('rowBreaks'),
|
|
39
|
+
recordsFacet('columnBreaks'),
|
|
25
40
|
facet('columns', (sheet) => [...sheet.columns()].map(({ index, properties }) => ({ index, properties: { ...properties } })), (sheet, value) => {
|
|
26
41
|
for (const { index, properties } of value)
|
|
27
42
|
Object.assign(sheet.getColumn(index), properties);
|
package/dist/core/worksheet.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ import type { PreservedWorksheetReference } from './preserved.ts';
|
|
|
12
12
|
import { type SheetProtection, type SheetProtectionOptions } from './protection.ts';
|
|
13
13
|
import { Range } from './range.ts';
|
|
14
14
|
import { Row } from './row.ts';
|
|
15
|
-
import type { CellStyle, Color, Fill } from './style.ts';
|
|
15
|
+
import type { CellContent, CellStyle, Color, Fill } from './style.ts';
|
|
16
16
|
import { Table, type TableOptions } from './table.ts';
|
|
17
17
|
import type { CellValue } from './value.ts';
|
|
18
18
|
/**
|
|
@@ -24,7 +24,7 @@ import type { CellValue } from './value.ts';
|
|
|
24
24
|
*/
|
|
25
25
|
export type Visibility = 'visible' | 'hidden' | 'veryHidden';
|
|
26
26
|
/** Narrow a raw `<sheet state>` or `<workbookView visibility>` token to a known {@link Visibility}. */
|
|
27
|
-
export declare
|
|
27
|
+
export declare const isVisibility: (value: string) => value is Visibility;
|
|
28
28
|
export interface WorksheetState {
|
|
29
29
|
/** Sheet visibility, as Excel models it. Defaults to `visible`. */
|
|
30
30
|
readonly state: Visibility;
|
|
@@ -107,8 +107,13 @@ export interface RowProperties {
|
|
|
107
107
|
/** Background fill applied to the row's cells that carry no fill of their own. */
|
|
108
108
|
fill?: Fill;
|
|
109
109
|
}
|
|
110
|
-
/**
|
|
111
|
-
|
|
110
|
+
/**
|
|
111
|
+
* One materialised cell in a {@link WorksheetModel}: its position, value, note, and every facet of its
|
|
112
|
+
* formatting. Extends {@link CellContent} rather than {@link CellStyle} so the quote-prefix flag and
|
|
113
|
+
* the named-style link travel with a model round-trip: they are written and read back like any other
|
|
114
|
+
* facet, and leaving them off the tuple is what made a `dst.model = src.model` drop them.
|
|
115
|
+
*/
|
|
116
|
+
export interface CellModel extends CellContent {
|
|
112
117
|
readonly row: number;
|
|
113
118
|
readonly col: number;
|
|
114
119
|
value: CellValue;
|
|
@@ -177,6 +182,17 @@ export declare class Worksheet {
|
|
|
177
182
|
* never fabricates one.
|
|
178
183
|
*/
|
|
179
184
|
tabColor: Color | undefined;
|
|
185
|
+
/**
|
|
186
|
+
* The sheet's VBA identity (`<sheetPr codeName>`), the name a macro means by `Sheet1`. Undefined
|
|
187
|
+
* for a sheet in a workbook with no VBA project, which is what Excel writes for one.
|
|
188
|
+
*
|
|
189
|
+
* Preserved rather than modeled: nothing here reads it, but a `.xlsm` whose sheet code names are
|
|
190
|
+
* dropped on a round trip has had the binding between its macros and its sheets cut. Deliberately
|
|
191
|
+
* absent from {@link WorksheetModel}, which is the copy shape: a code name identifies *this* sheet
|
|
192
|
+
* to the workbook's VBA project, so copying it onto a second sheet would give the project two
|
|
193
|
+
* sheets answering to one name.
|
|
194
|
+
*/
|
|
195
|
+
codeName?: string;
|
|
180
196
|
/** Sheet-level format defaults. Mutate in place: `sheet.properties.defaultRowHeight = 20`. */
|
|
181
197
|
readonly properties: WorksheetProperties;
|
|
182
198
|
/**
|
|
@@ -267,6 +283,7 @@ export declare class Worksheet {
|
|
|
267
283
|
*
|
|
268
284
|
* @throws {SyntaxError} if the reference is unparseable, names another worksheet, or leaves an
|
|
269
285
|
* axis unbounded.
|
|
286
|
+
* @throws {AuthoringError} if the numeric form is called with fewer than four corners.
|
|
270
287
|
* @throws {RangeError} if a numeric corner is not a positive integer within the sheet's bounds.
|
|
271
288
|
*/
|
|
272
289
|
getRange(reference: string): Range;
|
|
@@ -276,14 +293,21 @@ export declare class Worksheet {
|
|
|
276
293
|
* or 0 for an empty sheet. Spans gaps: a value in row 5 makes this 5 even if rows 2–4
|
|
277
294
|
* are empty. This is the used-range extent, not a populated-row tally (see
|
|
278
295
|
* {@link actualRowCount}).
|
|
296
|
+
*
|
|
297
|
+
* *Carrying anything* is deliberately wide: a value, a cell's own style facet, quote-prefix flag
|
|
298
|
+
* or named-style link, a note, a row height or outline level, or a merge reaching down. Styling a
|
|
299
|
+
* band of empty rows is how a template is laid out, so those rows are used and {@link addRow}
|
|
300
|
+
* appends past them. A cell merely materialised by {@link getCell} and left untouched carries
|
|
301
|
+
* nothing, so reading a far address never grows the sheet.
|
|
279
302
|
*/
|
|
280
303
|
get rowCount(): number;
|
|
281
304
|
/** The number of rows that hold at least one non-empty cell, ignoring gaps and formatting-only rows. */
|
|
282
305
|
get actualRowCount(): number;
|
|
283
306
|
/**
|
|
284
|
-
* The 1-based index of the last column carrying anything (a
|
|
307
|
+
* The 1-based index of the last column carrying anything (a used cell or the column's own format
|
|
285
308
|
* properties), or 0 for an empty sheet. The used-range width, mirroring {@link rowCount} for the
|
|
286
|
-
* other axis: a value in column E makes this 5 even if
|
|
309
|
+
* other axis, down to what *carrying anything* means: a value in column E makes this 5 even if
|
|
310
|
+
* columns B–D are empty, and a column holding nothing but a styled empty cell is still used.
|
|
287
311
|
*/
|
|
288
312
|
get columnCount(): number;
|
|
289
313
|
/**
|
|
@@ -505,6 +529,9 @@ export declare class Worksheet {
|
|
|
505
529
|
* shift with the rows they cover.
|
|
506
530
|
*
|
|
507
531
|
* @throws {RangeError} if `start` is not a positive integer or `count` is negative.
|
|
532
|
+
* @throws {RangeError} if an inserted row would land past the last row of the grid. The sheet is
|
|
533
|
+
* left untouched, so this is a refused edit rather than half of one: a region pushed off the edge
|
|
534
|
+
* clamps and absorbs the loss, but content pushed off it is what Excel refuses outright.
|
|
508
535
|
*/
|
|
509
536
|
spliceRows(start: number, count: number, ...inserts: RowInput[]): void;
|
|
510
537
|
/**
|
|
@@ -548,9 +575,13 @@ export declare class Worksheet {
|
|
|
548
575
|
/**
|
|
549
576
|
* Copy the row at the 1-based `start`, `options.count` times (default 1). With `options.insert`
|
|
550
577
|
* (the default) the copies are inserted directly after the source, shifting the rows below, and
|
|
551
|
-
* any merged range there, down by `count`; otherwise the copies
|
|
552
|
-
* below without shifting.
|
|
553
|
-
*
|
|
578
|
+
* any merged range there, down by `count`; otherwise the copies *replace* the rows immediately
|
|
579
|
+
* below without shifting. A destination row is not overlaid but wholly re-made, so a cell it held
|
|
580
|
+
* in a column the source leaves empty is dropped, exactly as it would be with a shifting insert.
|
|
581
|
+
*
|
|
582
|
+
* Each copy is a faithful duplicate of the source: its cell values, its per-cell styles, and its
|
|
583
|
+
* row properties (height, hidden, outline level, row fill). It carries no merge of its own, so a
|
|
584
|
+
* range can be merged onto a duplicated row afterwards.
|
|
554
585
|
*
|
|
555
586
|
* @throws {RangeError} if `start` is not a positive integer or `count` is negative.
|
|
556
587
|
*/
|
|
@@ -566,6 +597,10 @@ export declare class Worksheet {
|
|
|
566
597
|
* indexed by row (index 0 → row 1); an empty array inserts a blank column.
|
|
567
598
|
*
|
|
568
599
|
* @throws {RangeError} if `start` is not a positive integer or `count` is negative.
|
|
600
|
+
* @throws {RangeError} if an inserted column would land past the last column, or one of its values
|
|
601
|
+
* past the last row. The sheet is left untouched, so this is a refused edit rather than half of
|
|
602
|
+
* one: a region pushed off the edge clamps and absorbs the loss, but content pushed off it is
|
|
603
|
+
* what Excel refuses outright, and {@link addColumn} refuses the same argument identically.
|
|
569
604
|
*/
|
|
570
605
|
spliceColumns(start: number, count: number, ...inserts: CellValue[][]): void;
|
|
571
606
|
/**
|
|
@@ -573,7 +608,8 @@ export declare class Worksheet {
|
|
|
573
608
|
* by one. `values` is an array of values indexed by row (index 0 → row 1), like
|
|
574
609
|
* {@link addColumn}. Shorthand for {@link spliceColumns}`(pos, 0, values)`.
|
|
575
610
|
*
|
|
576
|
-
* @throws {RangeError} if `pos` is not a positive integer
|
|
611
|
+
* @throws {RangeError} if `pos` is not a positive integer, or if the column would land past the
|
|
612
|
+
* last column or one of its values past the last row; see {@link spliceColumns}.
|
|
577
613
|
*/
|
|
578
614
|
insertColumn(pos: number, values: CellValue[]): void;
|
|
579
615
|
/**
|
|
@@ -682,18 +718,42 @@ export interface WorksheetInternals {
|
|
|
682
718
|
*/
|
|
683
719
|
cellAt(row: number, col: number): Cell;
|
|
684
720
|
/**
|
|
685
|
-
* The
|
|
721
|
+
* The cell materialised at a position, or `undefined` when nothing has been written there.
|
|
722
|
+
*
|
|
723
|
+
* Merge-blind and non-materialising, which is what separates it from `Worksheet.getCell`: that
|
|
724
|
+
* resolves a covered address to its merge master, so `hasCell(row, col)` followed by a `getCell` of
|
|
725
|
+
* the same position can hand back a *different* cell. A caller walking a rectangle got the master
|
|
726
|
+
* once per covered position and never saw the covered cells at all, which made a `clearStyle` over a
|
|
727
|
+
* merge clear the master repeatedly and the covered cells not once. A caller that wants merge
|
|
728
|
+
* resolution keeps `getCell`; a caller enumerating what is actually stored wants this.
|
|
729
|
+
*/
|
|
730
|
+
peekCell(row: number, col: number): Cell | undefined;
|
|
731
|
+
/**
|
|
732
|
+
* {@link cellAt} with merge resolution: the cell a write to this position lands on, materialised.
|
|
733
|
+
*
|
|
734
|
+
* What {@link Worksheet.getCell} does, minus the address. `getCell` is the public spelling and takes
|
|
735
|
+
* an A1 reference, so a caller already holding a row and a column had to encode one and have it
|
|
736
|
+
* decoded straight back. That round-trip costs about three times a positional read, and a
|
|
737
|
+
* {@link Range} write performs one per cell: styling a 100x100 block spent 10,000 encodes and 10,000
|
|
738
|
+
* regex decodes on positions it already had.
|
|
739
|
+
*/
|
|
740
|
+
masterAt(row: number, col: number): Cell;
|
|
741
|
+
/**
|
|
742
|
+
* The store behind a {@link Row} or {@link Column} handle. These exist because the handles are
|
|
686
743
|
* views rather than records: they hold a sheet and a position, and every read and write goes
|
|
687
744
|
* through here to the one authoritative map. `…PropertiesOf` never fabricates, so reading a row
|
|
688
745
|
* cannot extend the used range; `ensure…` is what a write calls, so the record appears exactly
|
|
689
|
-
* when a value is set
|
|
746
|
+
* when a value is set; `drop…` is what clearing the last field calls, so the record disappears
|
|
747
|
+
* exactly when the line stops being formatted, which is what keeps the used range honest.
|
|
690
748
|
*/
|
|
691
749
|
rowPropertiesOf(number: number): RowProperties | undefined;
|
|
692
750
|
ensureRowProperties(number: number): RowProperties;
|
|
751
|
+
dropRowProperties(number: number): void;
|
|
693
752
|
/** The row's materialised cells in ascending column order. */
|
|
694
753
|
rowCells(number: number): Cell[];
|
|
695
754
|
columnPropertiesOf(index: number): ColumnProperties | undefined;
|
|
696
755
|
ensureColumnProperties(index: number): ColumnProperties;
|
|
756
|
+
dropColumnProperties(index: number): void;
|
|
697
757
|
/** The column's materialised cells in ascending row order. */
|
|
698
758
|
columnCells(index: number): Cell[];
|
|
699
759
|
}
|