documonster 0.14.0 → 0.15.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 +1 -1
- package/README_zh.md +1 -1
- package/dist/esm/modules/archive/compression/crc32.browser.js +6 -26
- package/dist/esm/modules/archive/compression/crc32.js +18 -80
- package/dist/esm/modules/archive/zip/stream.js +1 -8
- package/dist/esm/modules/excel/core/worksheet-core.js +65 -7
- package/dist/esm/modules/excel/core/worksheet.js +1 -1
- package/dist/esm/modules/excel/surface/column.js +88 -1
- package/dist/esm/modules/excel/utils/col-cache.js +6 -1
- package/dist/esm/modules/mermaid/layout/flowchart.js +527 -80
- package/dist/esm/modules/mermaid/parse/flowchart.js +55 -5
- package/dist/esm/modules/mermaid/theme.js +5 -4
- package/dist/esm/modules/pdf/render/layout-engine.js +138 -104
- package/dist/esm/modules/word/convert/markdown/markdown-import.js +218 -31
- package/dist/esm/modules/word/layout/layout-full.js +42 -2
- package/dist/iife/documonster.archive.iife.min.js +3 -3
- package/dist/iife/documonster.csv.iife.min.js +2 -2
- package/dist/iife/documonster.draw.iife.min.js +2 -2
- package/dist/iife/documonster.excel.iife.min.js +48 -48
- package/dist/iife/documonster.formula.iife.min.js +1 -1
- package/dist/iife/documonster.markdown.iife.min.js +1 -1
- package/dist/iife/documonster.mermaid.iife.min.js +3 -3
- package/dist/iife/documonster.pdf.iife.min.js +18 -18
- package/dist/iife/documonster.stream.iife.min.js +1 -1
- package/dist/iife/documonster.word.iife.min.js +12 -12
- package/dist/iife/documonster.xml.iife.min.js +1 -1
- package/dist/types/modules/archive/compression/crc32.browser.d.ts +6 -22
- package/dist/types/modules/archive/compression/crc32.d.ts +10 -18
- package/dist/types/modules/archive/zip/stream.d.ts +0 -1
- package/dist/types/modules/excel/core/worksheet-core.d.ts +42 -2
- package/dist/types/modules/excel/core/worksheet.d.ts +1 -1
- package/dist/types/modules/excel/surface/column.d.ts +83 -2
- package/dist/types/modules/mermaid/layout/flowchart.d.ts +12 -1
- package/dist/types/modules/word/layout/layout-model.d.ts +8 -0
- package/package.json +13 -13
package/README.md
CHANGED
|
@@ -211,7 +211,7 @@ const buffer = await Workbook.toBuffer(wb);
|
|
|
211
211
|
|
|
212
212
|
```html
|
|
213
213
|
<!-- Script tag (no bundler) — one IIFE per module, each under the shared `Documonster` global -->
|
|
214
|
-
<script src="https://unpkg.com/documonster@0.
|
|
214
|
+
<script src="https://unpkg.com/documonster@0.15.0/dist/iife/documonster.excel.iife.min.js"></script>
|
|
215
215
|
<script>
|
|
216
216
|
const { Workbook, Cell } = Documonster.Excel;
|
|
217
217
|
const wb = Workbook.create();
|
package/README_zh.md
CHANGED
|
@@ -198,7 +198,7 @@ const buffer = await Workbook.toBuffer(wb);
|
|
|
198
198
|
|
|
199
199
|
```html
|
|
200
200
|
<!-- Script 标签(无需打包工具)— 每个模块一个 IIFE,共享同一个 `Documonster` 全局 -->
|
|
201
|
-
<script src="https://unpkg.com/documonster@0.
|
|
201
|
+
<script src="https://unpkg.com/documonster@0.15.0/dist/iife/documonster.excel.iife.min.js"></script>
|
|
202
202
|
<script>
|
|
203
203
|
const { Workbook, Cell } = Documonster.Excel;
|
|
204
204
|
const wb = Workbook.create();
|
|
@@ -1,33 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* CRC32
|
|
2
|
+
* CRC32 for ZIP files — browser variant.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* The portable lookup-table implementation, with no `zlib` and no Node built-in of any kind. `crc32.ts` is
|
|
5
|
+
* the sibling that uses native `zlib.crc32`.
|
|
5
6
|
*
|
|
6
|
-
* The polynomial
|
|
7
|
+
* The polynomial is the standard CRC-32 IEEE 802.3:
|
|
7
8
|
* x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
|
|
8
|
-
* Represented as 0xEDB88320 in reversed (LSB-first) form
|
|
9
|
-
*/
|
|
10
|
-
export { crc32JS as crc32, crc32UpdateJS as crc32Update, crc32Finalize } from "./crc32.base.js";
|
|
11
|
-
/**
|
|
12
|
-
* Ensure CRC32 is ready (no-op in browser, for API compatibility)
|
|
13
|
-
*/
|
|
14
|
-
export async function ensureCrc32() {
|
|
15
|
-
// No-op in browser
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Synchronously ensure CRC32 is ready (no-op in browser).
|
|
19
|
-
* Exists for API compatibility with the Node.js version.
|
|
20
|
-
*/
|
|
21
|
-
export function ensureZlibSync() {
|
|
22
|
-
// No-op in browser — CRC32 always uses JS implementation
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Calculate CRC32 incrementally (useful for streaming)
|
|
26
|
-
* Call with initial crc of 0xffffffff, then finalize with crc32Finalize
|
|
27
|
-
*
|
|
28
|
-
* @param crc - Current CRC value (start with 0xffffffff)
|
|
29
|
-
* @param data - Input data chunk
|
|
30
|
-
* @returns Updated CRC value (not finalized)
|
|
9
|
+
* Represented as 0xEDB88320 in reversed (LSB-first) form.
|
|
31
10
|
*
|
|
32
11
|
* @example
|
|
33
12
|
* ```ts
|
|
@@ -37,3 +16,4 @@ export function ensureZlibSync() {
|
|
|
37
16
|
* const checksum = crc32Finalize(crc);
|
|
38
17
|
* ```
|
|
39
18
|
*/
|
|
19
|
+
export { crc32JS as crc32, crc32UpdateJS as crc32Update, crc32Finalize } from "./crc32.base.js";
|
|
@@ -1,61 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* CRC32
|
|
2
|
+
* CRC32 for ZIP files — Node variant.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* `zlib` is imported **statically**, and that is the invariant this file exists to hold. Loading it lazily
|
|
5
|
+
* leaves a window in which CRC32 runs on the portable lookup table instead, and the window cannot be closed
|
|
6
|
+
* synchronously from an ES module. `crc32.browser.ts` is the sibling that has no `zlib` and uses the table.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
+
* `zlib.crc32` has existed since Node 22.2 and `engines.node` is `>=22.13`, so it needs no capability probe.
|
|
9
|
+
*
|
|
10
|
+
* The polynomial is the standard CRC-32 IEEE 802.3:
|
|
8
11
|
* x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
|
|
9
|
-
* Represented as 0xEDB88320 in reversed (LSB-first) form
|
|
10
|
-
*/
|
|
11
|
-
import { crc32JS, crc32UpdateJS, crc32Finalize } from "./crc32.base.js";
|
|
12
|
-
import { isNode } from "../../../utils/env.js";
|
|
13
|
-
// Lazy-loaded zlib module for Node.js
|
|
14
|
-
let _zlib = null;
|
|
15
|
-
let _zlibLoading = null;
|
|
16
|
-
let _zlibInitStarted = false;
|
|
17
|
-
/**
|
|
18
|
-
* Lazily initialize zlib loading in Node.js.
|
|
19
|
-
* Called on first use rather than at module load time.
|
|
12
|
+
* Represented as 0xEDB88320 in reversed (LSB-first) form.
|
|
20
13
|
*/
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
_zlibInitStarted = true;
|
|
26
|
-
if (isNode()) {
|
|
27
|
-
_zlibLoading = import("zlib")
|
|
28
|
-
.then(module => {
|
|
29
|
-
_zlib = module.default ?? module;
|
|
30
|
-
return _zlib;
|
|
31
|
-
})
|
|
32
|
-
.catch(() => {
|
|
33
|
-
_zlib = null;
|
|
34
|
-
return null;
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Synchronously ensure zlib is loaded for Node.js.
|
|
40
|
-
* Used by the sync deflate path where the async dynamic import may not have
|
|
41
|
-
* resolved yet. Falls back to `require()` which is synchronous in Node.js.
|
|
42
|
-
*/
|
|
43
|
-
export function ensureZlibSync() {
|
|
44
|
-
if (_zlib || !isNode()) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
try {
|
|
48
|
-
// oxlint-disable-next-line typescript/no-require-imports
|
|
49
|
-
_zlib = require("zlib");
|
|
50
|
-
_zlibInitStarted = true;
|
|
51
|
-
}
|
|
52
|
-
catch {
|
|
53
|
-
// Bundler or non-Node environment — JS fallback will be used
|
|
54
|
-
}
|
|
55
|
-
}
|
|
14
|
+
import { crc32 as nativeCrc32 } from "zlib";
|
|
15
|
+
import { crc32Finalize } from "./crc32.base.js";
|
|
56
16
|
/**
|
|
57
17
|
* Calculate CRC32 checksum for the given data
|
|
58
|
-
* Uses native zlib.crc32 in Node.js for ~100x better performance
|
|
59
18
|
*
|
|
60
19
|
* @param data - Input data as Uint8Array or Buffer
|
|
61
20
|
* @returns CRC32 checksum as unsigned 32-bit integer
|
|
@@ -68,28 +27,13 @@ export function ensureZlibSync() {
|
|
|
68
27
|
* ```
|
|
69
28
|
*/
|
|
70
29
|
export function crc32(data) {
|
|
71
|
-
|
|
72
|
-
// Use native zlib.crc32 if available (Node.js)
|
|
73
|
-
if (_zlib && typeof _zlib.crc32 === "function") {
|
|
74
|
-
return _zlib.crc32(data) >>> 0;
|
|
75
|
-
}
|
|
76
|
-
// Fallback to JS implementation
|
|
77
|
-
return crc32JS(data);
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Ensure zlib is loaded (for use before calling crc32)
|
|
81
|
-
*/
|
|
82
|
-
export async function ensureCrc32() {
|
|
83
|
-
ensureZlibLoading();
|
|
84
|
-
if (_zlibLoading) {
|
|
85
|
-
await _zlibLoading;
|
|
86
|
-
}
|
|
30
|
+
return nativeCrc32(data) >>> 0;
|
|
87
31
|
}
|
|
88
32
|
/**
|
|
89
33
|
* Calculate CRC32 incrementally (useful for streaming)
|
|
90
34
|
* Call with initial crc of 0xffffffff, then finalize with crc32Finalize
|
|
91
|
-
*
|
|
92
|
-
* The internal
|
|
35
|
+
*
|
|
36
|
+
* The internal state matches the lookup-table implementation, so the two are interchangeable:
|
|
93
37
|
* - initial state: 0xffffffff
|
|
94
38
|
* - finalize: xor with 0xffffffff
|
|
95
39
|
*
|
|
@@ -106,17 +50,11 @@ export async function ensureCrc32() {
|
|
|
106
50
|
* ```
|
|
107
51
|
*/
|
|
108
52
|
export function crc32Update(crc, data) {
|
|
109
|
-
|
|
110
|
-
//
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
if (_zlib && typeof _zlib.crc32 === "function") {
|
|
115
|
-
const prevFinal = (crc ^ 0xffffffff) >>> 0;
|
|
116
|
-
const nextFinal = _zlib.crc32(data, prevFinal) >>> 0;
|
|
117
|
-
return (nextFinal ^ 0xffffffff) >>> 0;
|
|
118
|
-
}
|
|
119
|
-
return crc32UpdateJS(crc, data);
|
|
53
|
+
// `zlib.crc32` takes and returns a *finalized* CRC and chains through its second argument. The state here
|
|
54
|
+
// is the inverted (non-finalized) form, so convert on the way in and out.
|
|
55
|
+
const prevFinal = (crc ^ 0xffffffff) >>> 0;
|
|
56
|
+
const nextFinal = nativeCrc32(data, prevFinal) >>> 0;
|
|
57
|
+
return (nextFinal ^ 0xffffffff) >>> 0;
|
|
120
58
|
}
|
|
121
59
|
/**
|
|
122
60
|
* Finalize CRC32 calculation
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* - In Node builds it uses `./compression/crc32` + `./compression/streaming-compress` (zlib-backed).
|
|
6
6
|
* - In browser builds the bundler aliases those imports to their browser variants.
|
|
7
7
|
*/
|
|
8
|
-
import { crc32Update, crc32Finalize
|
|
8
|
+
import { crc32Update, crc32Finalize } from "#platform/modules/archive/compression/crc32";
|
|
9
9
|
import { createDeflateStream, SyncDeflater, hasNativeAsyncDeflate } from "#platform/modules/archive/compression/streaming-compress";
|
|
10
10
|
import { EMPTY_UINT8ARRAY } from "../core/bytes.js";
|
|
11
11
|
import { DEFAULT_ZIP_LEVEL, DEFAULT_ZIP_TIMESTAMPS } from "../core/defaults.js";
|
|
@@ -77,7 +77,6 @@ export class ZipDeflateFile {
|
|
|
77
77
|
this._inputPos = 0;
|
|
78
78
|
// Synchronous compression state for pushSync() path.
|
|
79
79
|
this._syncDeflater = null;
|
|
80
|
-
this._syncZlibReady = false;
|
|
81
80
|
const resolvedName = options?.path ? normalizeZipPath(name, options.path) : name;
|
|
82
81
|
this.name = resolvedName;
|
|
83
82
|
const modTime = options?.modTime ?? new Date();
|
|
@@ -723,12 +722,6 @@ export class ZipDeflateFile {
|
|
|
723
722
|
if (this._finalized) {
|
|
724
723
|
throw new ArchiveError("Cannot push to finalized ZipDeflateFile");
|
|
725
724
|
}
|
|
726
|
-
// Ensure native CRC32 is available before the first _writeDataSync call.
|
|
727
|
-
// Without this, the JS fallback is ~60x slower.
|
|
728
|
-
if (!this._syncZlibReady) {
|
|
729
|
-
ensureZlibSync();
|
|
730
|
-
this._syncZlibReady = true;
|
|
731
|
-
}
|
|
732
725
|
if (this._deflateWanted === null) {
|
|
733
726
|
this._accumulateSampleLen(data);
|
|
734
727
|
if (!this._shouldDecide(final)) {
|
|
@@ -4,7 +4,7 @@ import { Enums } from "./enums.js";
|
|
|
4
4
|
import { rangeCreate, rangeRange } from "./range.js";
|
|
5
5
|
import { rowCreate, rowFindCell, rowHasValues, rowValues, resolveColumnKeyValue } from "./row.js";
|
|
6
6
|
import { invalidateSharedCellStyle, sharedCellFacet } from "./style-sharing.js";
|
|
7
|
-
import { ExcelError, InvalidAddressError } from "../errors.js";
|
|
7
|
+
import { ColumnOutOfBoundsError, ExcelError, InvalidAddressError } from "../errors.js";
|
|
8
8
|
import { colCache } from "../utils/col-cache.js";
|
|
9
9
|
import { copyStyle } from "../utils/copy-style.js";
|
|
10
10
|
// =============================================================================
|
|
@@ -34,6 +34,40 @@ export function eachColumnKey(ws, f) {
|
|
|
34
34
|
// =============================================================================
|
|
35
35
|
// Columns
|
|
36
36
|
// =============================================================================
|
|
37
|
+
/**
|
|
38
|
+
* The 1-based column number for a key, a letter or a number — **without**
|
|
39
|
+
* creating the column record, unlike {@link getColumn}.
|
|
40
|
+
*
|
|
41
|
+
* A read addressed by column reference needs the number and nothing else (the
|
|
42
|
+
* cells live in the rows, not in the column record), so it resolves the
|
|
43
|
+
* reference through this instead of walking through a handle: `getColumn` pads
|
|
44
|
+
* `ws._columns` up to the column asked for, which moves `Worksheet.columns`
|
|
45
|
+
* and is a mutation on a read path — see `core/__tests__/read-side-effects.test.ts`.
|
|
46
|
+
*
|
|
47
|
+
* Unlike `getColumn` it also *validates*, so a reference that names no column
|
|
48
|
+
* fails the same way whichever form it took. Without that a numeric reference is
|
|
49
|
+
* the worst case of all: `0`, `-1`, `1.5` and `NaN` all index the cell array with
|
|
50
|
+
* something no row can hold, so the read reports an empty column rather than a
|
|
51
|
+
* bad argument.
|
|
52
|
+
*/
|
|
53
|
+
export function findColumnNumber(ws, c) {
|
|
54
|
+
if (typeof c === "string") {
|
|
55
|
+
// Own-property only. `ws._keys` is a plain object, so a bare `ws._keys[c]`
|
|
56
|
+
// resolves `"toString"` / `"constructor"` against `Object.prototype` and
|
|
57
|
+
// yields a function, whose `.number` is `undefined` — an unreadable column
|
|
58
|
+
// instead of an unknown key.
|
|
59
|
+
const keyed = Object.prototype.hasOwnProperty.call(ws._keys, c) ? ws._keys[c] : undefined;
|
|
60
|
+
return keyed ? keyed.number : colCache.l2n(c);
|
|
61
|
+
}
|
|
62
|
+
if (!Number.isInteger(c)) {
|
|
63
|
+
throw new ColumnOutOfBoundsError(c);
|
|
64
|
+
}
|
|
65
|
+
// `n2l` owns the 1..16384 bound and throws `ColumnOutOfBoundsError` past it,
|
|
66
|
+
// so the numeric form is rejected exactly as `l2n` rejects `"XFE"` above
|
|
67
|
+
// rather than duplicating the limit here.
|
|
68
|
+
colCache.n2l(c);
|
|
69
|
+
return c;
|
|
70
|
+
}
|
|
37
71
|
export function getColumn(ws, c) {
|
|
38
72
|
let colNum;
|
|
39
73
|
if (typeof c === "string") {
|
|
@@ -313,34 +347,58 @@ export function columnEachCell(c, optOrCallback, maybeCallback) {
|
|
|
313
347
|
});
|
|
314
348
|
}
|
|
315
349
|
export function columnValues(c) {
|
|
350
|
+
return columnValuesAt(c.worksheet, c.number);
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* The values down a column, addressed by column number rather than by a handle —
|
|
354
|
+
* so a caller holding only a reference does not have to materialise the column
|
|
355
|
+
* record to read through it.
|
|
356
|
+
*
|
|
357
|
+
* `base` is the index row 1 lands on: `1` keys the array by row number and
|
|
358
|
+
* leaves an empty leading slot (what `Column.values` returns), `0` makes it a
|
|
359
|
+
* plain array (`Column.getValues`). Either way an empty cell is a hole.
|
|
360
|
+
*/
|
|
361
|
+
export function columnValuesAt(ws, colNumber, base = 1) {
|
|
316
362
|
const v = [];
|
|
317
363
|
// Deliberately not via `columnEachCell`: its callback signature demands a
|
|
318
364
|
// `CellData`, so it materialises a cell on every row of the column. This is a
|
|
319
365
|
// getter, so walk the rows non-destructively instead.
|
|
320
|
-
const rows =
|
|
366
|
+
const rows = ws._rows;
|
|
321
367
|
for (let i = 0; i < rows.length; i++) {
|
|
322
368
|
const row = rows[i];
|
|
323
369
|
if (!row) {
|
|
324
370
|
continue;
|
|
325
371
|
}
|
|
326
|
-
const cell = rowFindCell(row,
|
|
372
|
+
const cell = rowFindCell(row, colNumber);
|
|
327
373
|
if (cell && cellType(cell) !== Enums.ValueType.Null) {
|
|
328
|
-
v[row.number] = cellGetValue(cell);
|
|
374
|
+
v[row.number - 1 + base] = cellGetValue(cell);
|
|
329
375
|
}
|
|
330
376
|
}
|
|
331
377
|
return v;
|
|
332
378
|
}
|
|
333
|
-
|
|
379
|
+
/**
|
|
380
|
+
* Write values down a column, addressed by column number.
|
|
381
|
+
*
|
|
382
|
+
* The array is read as **1-based by row number** when index 0 is a hole — the
|
|
383
|
+
* shape {@link columnValuesAt} hands back, so a read round-trips — and as
|
|
384
|
+
* 0-based when index 0 is present, so a plain array starts at row 1. The two
|
|
385
|
+
* cannot be told apart when a 0-based array's first slot is *also* a hole; that
|
|
386
|
+
* ambiguity is inherent to the protocol, and `rowSetValues` shares it.
|
|
387
|
+
*
|
|
388
|
+
* Only the indices the array actually carries are written: unlike
|
|
389
|
+
* `rowSetValues`, which resets the row, this leaves every other cell in the
|
|
390
|
+
* column alone.
|
|
391
|
+
*/
|
|
392
|
+
export function columnSetValuesAt(ws, colNumber, v) {
|
|
334
393
|
if (!v) {
|
|
335
394
|
return;
|
|
336
395
|
}
|
|
337
|
-
const colNumber = c.number;
|
|
338
396
|
let offset = 0;
|
|
339
397
|
if (Object.prototype.hasOwnProperty.call(v, "0")) {
|
|
340
398
|
offset = 1;
|
|
341
399
|
}
|
|
342
400
|
v.forEach((value, index) => {
|
|
343
|
-
cellSetValue(getCell(
|
|
401
|
+
cellSetValue(getCell(ws, index + offset, colNumber), value);
|
|
344
402
|
});
|
|
345
403
|
}
|
|
346
404
|
// =============================================================================
|
|
@@ -1979,4 +1979,4 @@ function _resolveOrigin(origin, rowCount) {
|
|
|
1979
1979
|
}
|
|
1980
1980
|
// Re-export the worksheet-core container layer so `@excel/worksheet` remains the
|
|
1981
1981
|
// canonical import path for all worksheet operations.
|
|
1982
|
-
export { addRow, addRows, getColumnKey, setColumnKey, deleteColumnKey, getColumn, _commitRow, findRow, findRows, getRow, getRows, eachRow, getSheetValues, findCell, getCell, getSheetName, getSheetWorkbook, getTable, getTables, rowGetCell, rowGetCellEx, rowSetValues, rowEachCell, rowSplice, rowCommit, rowSetModel, columnCreate, columnSetDefn, columnSetHeader, columnSetKey, columnEachCell, columnValues,
|
|
1982
|
+
export { addRow, addRows, getColumnKey, setColumnKey, deleteColumnKey, getColumn, _commitRow, findRow, findRows, getRow, getRows, eachRow, getSheetValues, findCell, getCell, getSheetName, getSheetWorkbook, getTable, getTables, rowGetCell, rowGetCellEx, rowSetValues, rowEachCell, rowSplice, rowCommit, rowSetModel, columnCreate, columnSetDefn, columnSetHeader, columnSetKey, columnEachCell, columnValues, columnSetValuesAt, columnFromModel, columnSetNumFmt, columnSetFont, columnSetAlignment, columnSetProtection, columnSetBorder, columnSetFill, freeze, split, unfreeze, panes, setAutoFilter, autoFilter } from "./worksheet-core.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { columnAddPageBreak, columnDefn, columnHidden, columnLetter, columnOutlineLevel, columnSetHidden, columnSetOutlineLevel } from "../core/column.js";
|
|
2
2
|
import { invalidateSharedCellStyle } from "../core/style-sharing.js";
|
|
3
|
-
import {
|
|
3
|
+
import { columnSetHeader, columnSetKey, columnSetNumFmt, columnSetStyle, columnSetValuesAt, columnValuesAt, findColumnNumber, getColumn } from "../core/worksheet-core.js";
|
|
4
4
|
// --- identity ---
|
|
5
5
|
/**
|
|
6
6
|
* The 1-based column number for a key, letter or number.
|
|
@@ -111,6 +111,93 @@ export function setNumFmt(ws, col, value) {
|
|
|
111
111
|
export function getDefinition(ws, col) {
|
|
112
112
|
return columnDefn(getColumn(ws, col));
|
|
113
113
|
}
|
|
114
|
+
// --- values ---
|
|
115
|
+
/**
|
|
116
|
+
* Read the values down a column as a **0-based sparse** array: the value in row
|
|
117
|
+
* 1 is at index `0`, row 2 at index `1`, and so on, and an empty cell is a hole
|
|
118
|
+
* rather than a `null`.
|
|
119
|
+
*
|
|
120
|
+
* Contrast with {@link values}, which is indexed by row *number* and therefore
|
|
121
|
+
* composes directly with the `Cell` namespace. That is also the one to pass back
|
|
122
|
+
* to {@link setValues} — see the ambiguity noted there.
|
|
123
|
+
*
|
|
124
|
+
* The read is non-destructive: it walks the rows that exist rather than asking
|
|
125
|
+
* each one for a cell, so it neither materialises cells down the column nor
|
|
126
|
+
* declares the column itself. The metadata and style accessors in this namespace
|
|
127
|
+
* resolve their reference through a column *record*, which pads
|
|
128
|
+
* `Worksheet.columns` up to the column asked for.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```typescript
|
|
132
|
+
* import { Column, Workbook, Worksheet } from "documonster/excel";
|
|
133
|
+
*
|
|
134
|
+
* const wb = Workbook.create();
|
|
135
|
+
* const ws = Workbook.addWorksheet(wb, "Sales");
|
|
136
|
+
* Worksheet.setColumns(ws, [{ key: "total", header: "Total" }]);
|
|
137
|
+
* Column.setValues(ws, "total", [10, 20, 30]);
|
|
138
|
+
* const [first] = Column.getValues(ws, "total"); // 10 — row 1
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
export function getValues(ws, col) {
|
|
142
|
+
return columnValuesAt(ws, findColumnNumber(ws, col), 0);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Read the values down a column as a **sparse** array indexed by **row number**:
|
|
146
|
+
* index `0` is always an empty leading slot, the value in row 1 is at index `1`,
|
|
147
|
+
* and so on. This mirrors Excel's 1-based row numbering, so the index can be
|
|
148
|
+
* handed straight to the `Cell` namespace, and it is the form {@link setValues}
|
|
149
|
+
* reads back unambiguously.
|
|
150
|
+
*
|
|
151
|
+
* Use {@link getValues} when the values are wanted as a plain 0-based array. Like
|
|
152
|
+
* it, this read materialises nothing.
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```typescript
|
|
156
|
+
* import { Cell, Column, Workbook } from "documonster/excel";
|
|
157
|
+
*
|
|
158
|
+
* const wb = Workbook.create();
|
|
159
|
+
* const ws = Workbook.addWorksheet(wb, "Sales");
|
|
160
|
+
* Column.setValues(ws, "C", [120, -40, 75]);
|
|
161
|
+
*
|
|
162
|
+
* // Colour the losses red. The index *is* the row number, and `Column.getNumber`
|
|
163
|
+
* // turns the reference into the column number `Cell` takes.
|
|
164
|
+
* const colNumber = Column.getNumber(ws, "C");
|
|
165
|
+
* Column.values(ws, "C").forEach((value, rowNumber) => {
|
|
166
|
+
* if (typeof value === "number" && value < 0) {
|
|
167
|
+
* Cell.setFont(ws, rowNumber, colNumber, { color: { argb: "FFC00000" } });
|
|
168
|
+
* }
|
|
169
|
+
* });
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
export function values(ws, col) {
|
|
173
|
+
return columnValuesAt(ws, findColumnNumber(ws, col));
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Write values down a column. Takes anything `Cell.setValue` takes — a number, a
|
|
177
|
+
* string, a formula, rich text, a hyperlink, a `Date` or a civil `Temporal`.
|
|
178
|
+
*
|
|
179
|
+
* The array is read as **1-based by row number** when index 0 is a hole — the
|
|
180
|
+
* shape {@link values} hands back, so that read round-trips — and as **0-based**
|
|
181
|
+
* when index 0 is present, so a plain array starts at row 1:
|
|
182
|
+
*
|
|
183
|
+
* ```typescript
|
|
184
|
+
* Column.setValues(ws, "A", [1, 2, 3]); // rows 1, 2, 3
|
|
185
|
+
* Column.setValues(ws, "A", [, 1, 2, 3]); // rows 1, 2, 3 — the same thing
|
|
186
|
+
* ```
|
|
187
|
+
*
|
|
188
|
+
* The two are indistinguishable when a 0-based array's own first slot is a hole,
|
|
189
|
+
* so pass {@link values} rather than {@link getValues} when writing a read back —
|
|
190
|
+
* a `getValues` array whose row 1 was empty lands a row high. `Row.setValues` has
|
|
191
|
+
* the same ambiguity.
|
|
192
|
+
*
|
|
193
|
+
* **This writes, it does not replace.** Only the indices the array carries are
|
|
194
|
+
* touched — unlike `Row.setValues`, which resets the row — so a shorter array
|
|
195
|
+
* does not truncate the column and a value already in a row the array skips
|
|
196
|
+
* survives. Clear a cell by passing `null` at its index.
|
|
197
|
+
*/
|
|
198
|
+
export function setValues(ws, col, v) {
|
|
199
|
+
columnSetValuesAt(ws, findColumnNumber(ws, col), v);
|
|
200
|
+
}
|
|
114
201
|
// --- printing ---
|
|
115
202
|
/**
|
|
116
203
|
* Add a manual vertical page break to the **right** of `col`, the equivalent of
|
|
@@ -32,7 +32,12 @@ const colCache = {
|
|
|
32
32
|
"Z"
|
|
33
33
|
],
|
|
34
34
|
_l2nFill: 0,
|
|
35
|
-
|
|
35
|
+
// Prototype-less: this is keyed by caller-supplied strings, so a plain object
|
|
36
|
+
// resolves `"toString"` / `"constructor"` / `"valueOf"` against
|
|
37
|
+
// `Object.prototype` and `l2n` returns that *function* instead of throwing —
|
|
38
|
+
// the truthiness guards below both pass. A column reference named after an
|
|
39
|
+
// `Object.prototype` member then reads as a column number of `NaN`.
|
|
40
|
+
_l2n: Object.create(null),
|
|
36
41
|
_n2l: [],
|
|
37
42
|
_level(n) {
|
|
38
43
|
if (n <= 26) {
|