@justybase/spreadsheet-tasks 3.1.1 → 3.2.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/CHANGELOG.md +78 -0
- package/README.md +124 -3
- package/browser/browser-spreadsheet.js +3659 -1784
- package/browser/justybase-spreadsheet.min.js +50 -23
- package/dist/cjs/index.d.ts +458 -59
- package/dist/cjs/index.js +5643 -2523
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +5623 -2523
- package/dist/esm/index.js.map +1 -1
- package/docs/API.md +130 -7
- package/package.json +6 -2
package/docs/API.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
- [XlsbWriter](#xlsbwriter)
|
|
6
6
|
- [XlsxWriter](#xlsxwriter)
|
|
7
|
+
- [Styles, formulas and sheet features](#styles-formulas-and-sheet-features)
|
|
7
8
|
- [XlsbReader](#xlsbreader)
|
|
8
9
|
- [XlsxReader](#xlsxreader)
|
|
9
10
|
- [XlsxUpdater](#xlsxupdater)
|
|
@@ -49,14 +50,21 @@ writer.addSheet('Sales Data');
|
|
|
49
50
|
writer.addSheet('Hidden Sheet', true);
|
|
50
51
|
```
|
|
51
52
|
|
|
52
|
-
#### `writeSheet(rows: any[][], headers?: string[] | null,
|
|
53
|
+
#### `writeSheet(rows: any[][], headers?: string[] | null, options?: boolean | XlsbSheetOptions): void`
|
|
53
54
|
|
|
54
55
|
Writes data to the current sheet.
|
|
55
56
|
|
|
56
57
|
**Parameters:**
|
|
57
|
-
- `rows` - 2D array of data to write
|
|
58
|
-
- `headers` - Optional. Array of header strings
|
|
59
|
-
- `doAutofilter` - Optional
|
|
58
|
+
- `rows` - 2D array of data to write (`CellValue`, including styles and formulas)
|
|
59
|
+
- `headers` - Optional. Array of header strings
|
|
60
|
+
- `doAutofilter` - Optional legacy boolean; pass `XlsbSheetOptions` instead for features and widths
|
|
61
|
+
- `options.merges` - Merged ranges, e.g. `['A4:B4']`
|
|
62
|
+
- `options.hyperlinks` - `{ ref, target?, location?, tooltip?, display? }[]`
|
|
63
|
+
- `options.dataValidations` - List, whole/decimal/date/time/text-length/custom rules
|
|
64
|
+
- `options.columnWidths` - Fixed widths in Excel character units; skips autofit
|
|
65
|
+
- `options.autofit` - Set `false` to disable the conservative width heuristic
|
|
66
|
+
- `options.autofitRows` - Rows measured by autofit (default 200; `0` uses headers/samples only)
|
|
67
|
+
- `options.sampleRows` - Extra rows used by autofit in streaming mode
|
|
60
68
|
|
|
61
69
|
**Supported Data Types:**
|
|
62
70
|
- `string` - Written as shared string
|
|
@@ -64,8 +72,12 @@ Writes data to the current sheet.
|
|
|
64
72
|
- `boolean` - Written as boolean
|
|
65
73
|
- `Date` - Written as Excel date serial number. The serial is taken from the UTC
|
|
66
74
|
time (`getTime()`), not local wall-clock time: `new Date(2024, 5, 30)` in UTC+2
|
|
67
|
-
is stored as 2024-06-29 22:00 and shows that way in Excel.
|
|
68
|
-
|
|
75
|
+
is stored as 2024-06-29 22:00 and shows that way in Excel. Dates with a UTC
|
|
76
|
+
time of day use the datetime number format (`m/d/yy h:mm`); midnight uses the
|
|
77
|
+
date format. Use `Date.UTC(...)` for date-only values
|
|
78
|
+
- `FormattedCell` - Legacy `{ value, format }` number format
|
|
79
|
+
- `StyledCell` - `{ value, style }` with font/fill/border/alignment/protection/number format
|
|
80
|
+
- `FormulaCell` - `{ formula, value?, style? }`; `value` is the cached result
|
|
69
81
|
- `null` / `undefined` - Written as empty cell
|
|
70
82
|
|
|
71
83
|
**Example:**
|
|
@@ -108,11 +120,105 @@ new XlsxWriter(filePath: string)
|
|
|
108
120
|
|
|
109
121
|
All methods are identical to [XlsbWriter](#xlsbwriter):
|
|
110
122
|
- `addSheet(sheetName: string, hidden?: boolean): void`
|
|
111
|
-
- `writeSheet(rows: any[][], headers?: string[] | null,
|
|
123
|
+
- `writeSheet(rows: any[][], headers?: string[] | null, options?: boolean | XlsxSheetOptions): void`
|
|
112
124
|
- `finalize(): Promise<void>`
|
|
113
125
|
|
|
114
126
|
---
|
|
115
127
|
|
|
128
|
+
## Styles, formulas and sheet features
|
|
129
|
+
|
|
130
|
+
### `CellStyle`
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
interface CellStyle {
|
|
134
|
+
numFmt?: string;
|
|
135
|
+
font?: { name?: string; size?: number; bold?: boolean; italic?: boolean;
|
|
136
|
+
underline?: 'single' | 'double' | 'singleAccounting' | 'doubleAccounting' | boolean;
|
|
137
|
+
strike?: boolean; color?: StyleColor; family?: number;
|
|
138
|
+
scheme?: 'major' | 'minor'; vertAlign?: 'baseline' | 'superscript' | 'subscript';
|
|
139
|
+
outline?: boolean; shadow?: boolean; condense?: boolean; extend?: boolean; charset?: number };
|
|
140
|
+
fill?: { patternType?: PatternType; fgColor?: StyleColor; bgColor?: StyleColor };
|
|
141
|
+
border?: { top?: BorderSide; bottom?: BorderSide; left?: BorderSide; right?: BorderSide;
|
|
142
|
+
diagonal?: BorderSide; diagonalUp?: boolean; diagonalDown?: boolean; outline?: boolean };
|
|
143
|
+
alignment?: { horizontal?: ...; vertical?: ...; wrapText?: boolean; shrinkToFit?: boolean;
|
|
144
|
+
indent?: number; textRotation?: number; justifyLastLine?: boolean; readingOrder?: 0 | 1 | 2 };
|
|
145
|
+
protection?: { locked?: boolean; hidden?: boolean };
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
`StyleColor` is `RRGGBB`, `AARRGGBB`, `#RRGGBB`, `{ indexed }` or `{ theme, tint? }`.
|
|
150
|
+
|
|
151
|
+
### `StyledCell`, `FormulaCell` and `RichText`
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
{ value: 10, style: { font: { bold: true }, fill: { fgColor: 'FFFF00' } } }
|
|
155
|
+
{ formula: 'SUM(A2:A3)', value: 30, style: { numFmt: '#,##0.00' } }
|
|
156
|
+
new RichText([
|
|
157
|
+
{ text: 'red', style: { font: { color: 'FF0000' } } },
|
|
158
|
+
{ text: ' plain' },
|
|
159
|
+
])
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`FormattedCell` (`{ value, format }`) remains supported; it is equivalent to
|
|
163
|
+
`{ value, style: { numFmt: format } }`.
|
|
164
|
+
|
|
165
|
+
### `XlsxSheetOptions`
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
interface XlsxSheetOptions {
|
|
169
|
+
merges?: string[];
|
|
170
|
+
hyperlinks?: Array<{ ref: string; target?: string; location?: string; tooltip?: string; display?: string }>;
|
|
171
|
+
dataValidations?: DataValidationSpec[];
|
|
172
|
+
conditionalFormats?: ConditionalFormatSpec[];
|
|
173
|
+
comments?: Array<{ ref: string; text: string; author?: string }>;
|
|
174
|
+
columnWidths?: Array<number | null | undefined>;
|
|
175
|
+
autofit?: boolean;
|
|
176
|
+
autofitRows?: number;
|
|
177
|
+
sampleRows?: unknown[][];
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
XLSB accepts the same options except `conditionalFormats` and `comments`, which
|
|
182
|
+
throw a clear error because the XLSB writer does not emit those parts yet.
|
|
183
|
+
XLSB rich text is also XLSX-only.
|
|
184
|
+
|
|
185
|
+
### Column autofit
|
|
186
|
+
|
|
187
|
+
When `columnWidths` is omitted and `autofit` is not `false`, widths are estimated
|
|
188
|
+
from the header and up to 200 sample rows (xlspy measures up to 1000) using
|
|
189
|
+
conservative per-character costs. The estimate accounts for CJK/fullwidth
|
|
190
|
+
characters, emoji, bold/italic text, font size, wide font families, common
|
|
191
|
+
number/date formats, alignment indent, the longest line of wrapped text and
|
|
192
|
+
negative number-format sections. It is clamped to Excel's 8.43 minimum,
|
|
193
|
+
reserves room for the autofilter drop-down, adds the 5/7-character cell padding
|
|
194
|
+
when written, and caps the stored width at 200. The widths are deliberately
|
|
195
|
+
biased wide so they are not narrower than xlspy/Excel AutoFit up to that cap.
|
|
196
|
+
In streaming mode the sheet head is delayed until the first 200 data rows have
|
|
197
|
+
been measured (200 by default). Explicit `columnWidths` entries must be
|
|
198
|
+
0.5-255 characters, always win and are written unchanged.
|
|
199
|
+
|
|
200
|
+
The stored width is in Excel character units, so the heuristic is independent
|
|
201
|
+
of display DPI. Excel's *displayed* pixel width can still vary with the Normal
|
|
202
|
+
font and screen scaling; 96 DPI gives reproducible visual/COM measurements when
|
|
203
|
+
comparing screenshots or `ColumnWidth` values.
|
|
204
|
+
|
|
205
|
+
### Reading styles, formulas and rich text (XLSX)
|
|
206
|
+
|
|
207
|
+
`XlsxReader` exposes metadata for cells in the row returned by the last
|
|
208
|
+
`read()` / `readRow()`:
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
reader.getStyle(columnIndex); // CellStyle | null
|
|
212
|
+
reader.getFormula(columnIndex); // formula text without '=', or null
|
|
213
|
+
reader.getRichText(columnIndex); // RichText | null
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
`XlsbReader.getStyle(columnIndex)` returns the parsed cell style. Formula text
|
|
217
|
+
is not reconstructed by the XLSB reader; formulas are read as their cached
|
|
218
|
+
values.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
116
222
|
## XlsbReader
|
|
117
223
|
|
|
118
224
|
High-performance reader for Excel Binary Workbook (.xlsb) format.
|
|
@@ -198,6 +304,11 @@ do {
|
|
|
198
304
|
} while (await reader.nextResult());
|
|
199
305
|
```
|
|
200
306
|
|
|
307
|
+
#### `getStyle(columnIndex: number): CellStyle | null`
|
|
308
|
+
|
|
309
|
+
Returns the parsed style of the cell in the current row. `null` means the
|
|
310
|
+
default style.
|
|
311
|
+
|
|
201
312
|
#### `getValue(columnIndex: number): CellValue`
|
|
202
313
|
|
|
203
314
|
Gets value at the specified column index in the current row.
|
|
@@ -265,6 +376,18 @@ See [XlsbReader](#xlsbreader).
|
|
|
265
376
|
|
|
266
377
|
See [XlsbReader](#xlsbreader).
|
|
267
378
|
|
|
379
|
+
#### `getFormula(columnIndex: number): string | null`
|
|
380
|
+
|
|
381
|
+
Formula text without the leading `=` for the current row, or `null`.
|
|
382
|
+
|
|
383
|
+
#### `getRichText(columnIndex: number): RichText | null`
|
|
384
|
+
|
|
385
|
+
Rich-text runs for the current row, or `null` for plain strings.
|
|
386
|
+
|
|
387
|
+
#### `getStyle(columnIndex: number): CellStyle | null`
|
|
388
|
+
|
|
389
|
+
Parsed cell style for the current row, or `null` for the default style.
|
|
390
|
+
|
|
268
391
|
#### `getValue(columnIndex: number): CellValue`
|
|
269
392
|
|
|
270
393
|
Gets value at the specified column index.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@justybase/spreadsheet-tasks",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "High-performance TypeScript library for reading and writing Excel files in XLSB and XLSX formats. XLSB is 3.3x faster to write and 2.3x faster to read than XLSX.",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -29,15 +29,19 @@
|
|
|
29
29
|
"typecheck": "tsc --noEmit && tsc -p tsconfig.browser.json",
|
|
30
30
|
"test": "npm run typecheck && npm run test:smoke && npm run test:unit && npm run test:integration && npm run test:dist",
|
|
31
31
|
"test:smoke": "npx ts-node tests/smoke.test.ts",
|
|
32
|
-
"test:unit": "npx ts-node tests/unit/bigbuffer.test.ts && npx ts-node tests/unit/biff-reader-writer.test.ts && npx ts-node tests/unit/xlsb-writer.test.ts && npx ts-node tests/unit/excel-converter.test.ts && npx ts-node tests/unit/updater-streaming.test.ts && npx ts-node tests/unit/xlsx-reader-cell-refs.test.ts && npx ts-node tests/unit/writer-limits-columns.test.ts && npx ts-node tests/unit/reader-xml-fixes.test.ts && npx ts-node tests/unit/xlsb-sst-dim.test.ts && npx ts-node tests/unit/updater-cleanup.test.ts && npx ts-node tests/unit/oa-1900-leap.test.ts && npx ts-node tests/unit/reader-row-limit.test.ts && npx ts-node tests/unit/xlsx-cell-positions.test.ts",
|
|
32
|
+
"test:unit": "npx ts-node tests/unit/bigbuffer.test.ts && npx ts-node tests/unit/biff-reader-writer.test.ts && npx ts-node tests/unit/xlsb-writer.test.ts && npx ts-node tests/unit/excel-converter.test.ts && npx ts-node tests/unit/updater-streaming.test.ts && npx ts-node tests/unit/xlsx-reader-cell-refs.test.ts && npx ts-node tests/unit/writer-limits-columns.test.ts && npx ts-node tests/unit/reader-xml-fixes.test.ts && npx ts-node tests/unit/xlsb-sst-dim.test.ts && npx ts-node tests/unit/updater-cleanup.test.ts && npx ts-node tests/unit/oa-1900-leap.test.ts && npx ts-node tests/unit/reader-row-limit.test.ts && npx ts-node tests/unit/reader-throughput.test.ts && npx ts-node tests/unit/xlsx-cell-positions.test.ts && npx ts-node tests/unit/writer-core-parity.test.ts && npx ts-node tests/unit/stage2-features.test.ts",
|
|
33
33
|
"test:integration": "npx ts-node tests/integration/xlsb-writer.test.ts && npx ts-node tests/integration/xlsx-writer.test.ts && npx ts-node tests/integration/xlsx-updater.test.ts && npx ts-node tests/integration/xlsb-updater.test.ts",
|
|
34
34
|
"test:dist": "npm run build && npx ts-node tests/dist-surface.test.ts",
|
|
35
35
|
"test:excel-conversion": "npm run build && npx ts-node tests/excel-compat/conversion.ts",
|
|
36
36
|
"test:xlsb": "npx ts-node tests/integration/xlsb-writer.test.ts && npx ts-node tests/integration/xlsb-updater.test.ts",
|
|
37
37
|
"test:xlsx": "npx ts-node tests/integration/xlsx-writer.test.ts",
|
|
38
38
|
"benchmark": "npm run build && npx ts-node benchmarks/performance.bench.ts",
|
|
39
|
+
"benchmark:io": "npx ts-node benchmarks/io.bench.ts",
|
|
40
|
+
"benchmark:io:baseline": "npx ts-node benchmarks/io.bench.ts --quick --save-baseline",
|
|
41
|
+
"benchmark:io:check": "npx ts-node benchmarks/io.bench.ts --quick --check",
|
|
39
42
|
"benchmark:comparison": "npm run build && npx ts-node benchmarks/comparison.bench.ts",
|
|
40
43
|
"test:excel-compat": "npm run build && npx tsx tests/excel-compat/run.ts",
|
|
44
|
+
"test:excel-com": "npx ts-node tests/excel-com/conformance.test.ts && npx ts-node tests/excel-com/stage2.test.ts",
|
|
41
45
|
"test:cross": "npx ts-node tests/cross/xlspy-cross.test.ts",
|
|
42
46
|
"prepublishOnly": "npm run build && npm run build:browser && npm test"
|
|
43
47
|
},
|