@xlsxflow/core 1.1.3 → 1.1.5
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 +38 -0
- package/README.md +20 -10
- package/dist/index.cjs +1113 -743
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -7
- package/dist/index.d.ts +30 -7
- package/dist/index.mjs +1113 -743
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.5
|
|
4
|
+
|
|
5
|
+
Fixes found while testing every claim in the README on Node 20.12 and 25, Bun, Deno, Chrome and Cloudflare Workers.
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- `SheetWriter`, `SheetEditor` and `OdsWriter` wait while nobody reads their output on Node and Bun too. Their `CompressionStream` takes thousands of chunks without pushing back, so a slow consumer let the writer pull the whole row source into memory.
|
|
10
|
+
- On Bun, `.ods` files and other ZIP entries stored without compression read correctly. Bun's `Blob.slice().stream()` runs past the end of the slice, which 1.1.4's size check rejected.
|
|
11
|
+
- `SheetWriter` refuses a merge that overlaps a table. Excel tables cannot hold merged cells, and Excel repaired such files by removing the table.
|
|
12
|
+
|
|
13
|
+
### Docs
|
|
14
|
+
|
|
15
|
+
- The README says to close a `createFileReader` reader (Node 25 stops the process when an open file is garbage-collected), lists Deno as tested, fixes the sheet-options example that merged cells inside a table, and corrects the comparison table: ExcelJS 4.4 has no pivot tables.
|
|
16
|
+
|
|
17
|
+
## 1.1.4
|
|
18
|
+
|
|
19
|
+
Fixes from the third round of end-user tests (700 cases).
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- `XlsxFlow.readFile` reads `.ods` files, and `getComments()` / `getImages()` work after reading an `.xlsx` with it.
|
|
24
|
+
- Control characters and U+FFFE/U+FFFF never reach the XML: cell text keeps them as `_xHHHH_` escapes, other text (document properties, notes' authors, validations, headers and footers, table columns, alt text, formulas) drops them, and sheet names with them are refused.
|
|
25
|
+
- `SheetWriter` stores formula text that starts with `#` as text, not as an error cell Excel repairs.
|
|
26
|
+
- `SheetWriter` waits while nobody reads its output, instead of pulling rows from the source without limit, and cancelling the output ends the row source (its `finally` runs).
|
|
27
|
+
- Cached formula results: formulas over other formula cells, scientific literals (`1E3`), reversed ranges, case-insensitive text comparison, values typed into `SUM`, 15-digit number text, `TRUE`/`FALSE` text, errors (`#DIV/0!`, `#VALUE!`) and circular references follow Excel. Streamed rows get no made-up cached values (in `OdsWriter` too).
|
|
28
|
+
- `SheetWriter` refuses overlapping or malformed merges, overlapping tables, table names that look like cell references, defined names over 255 characters, row options outside rows 1 to 1,048,576, list validations over 255 characters, truncated images, and picture sizes that are not positive numbers. Validation formulas lose a leading `=`, and every range of a multi-range print area names its sheet.
|
|
29
|
+
- `SheetEditor.appendSheet` writes dates, formulas, styles and NaN as `setCells` does, keeps both batches when called twice, writes rows in the sheet's namespace, and refuses rows past 1,048,576.
|
|
30
|
+
- `SheetEditor`: `setCells` edits the right row on sheets whose rows have no `r` attribute; a date and a style on one cell keep both; repeating a restyle reuses the formats it added; `insertRows` keeps ranges ending at the last row (`SUM(B1:B1048576)`), leaves references to other workbooks (`[1]S!A5`) alone, moves every cell of a shared formula on another sheet, and moves pivot tables on the sheet.
|
|
31
|
+
- `SheetReader`: entries whose data does not match their CRC-32, and worksheets cut off mid-row, are errors instead of silently different data. A zip comment holding the end-record signature, part names in another case, UTF-16 parts, rows with an unusable `r`, `t="d"` cells (now UTC ISO strings, formatted with their date format), sheet names with `&`, and a chart sheet as the first tab are read correctly.
|
|
32
|
+
- `sheetToJson` keeps values right of the header row (`Column3`); `streamToCsv` keeps blank rows between rows.
|
|
33
|
+
- `parseCsv` keeps numbers that overflow a double (`1e400`) as text.
|
|
34
|
+
- `OdsWriter` keeps the milliseconds of dates and converts whole-column references (`SUM(C:C)`); the `.ods` reader reads the created date as UTC.
|
|
35
|
+
- ZIP: UTF-8 entry names set the UTF-8 flag, 65,535 entries are refused (readers take 0xFFFF as ZIP64), and an encrypted or `.xls` file given where a ZIP is expected says so.
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
|
|
39
|
+
- The `errors` parse option: `row.errors` marks cells holding error values.
|
|
40
|
+
|
|
3
41
|
## 1.1.3
|
|
4
42
|
|
|
5
43
|
### Fixed
|
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ Rows are read and written one at a time instead of loading the whole workbook, s
|
|
|
29
29
|
|
|
30
30
|
- **No dependencies**: TypeScript on Web APIs (`ReadableStream`, `CompressionStream`, `Blob`).
|
|
31
31
|
- **Streaming**: rows are read and written one at a time, so memory stays flat as files grow (10M cells written with about 1 MB of extra heap; see [Benchmarks](#benchmarks)).
|
|
32
|
-
- **Runs anywhere with Web APIs**: tested on Node 20.12
|
|
32
|
+
- **Runs anywhere with Web APIs**: tested on Node 20.12 and later, Bun, Deno, Chrome and Cloudflare Workers (without `nodejs_compat`).
|
|
33
33
|
- **Read, write and edit**: stream rows out of a file, generate one on the fly, or change cells, rows, columns and sheets of an existing file while keeping everything else in it.
|
|
34
34
|
- **Styles and formulas**: fonts, fills, borders, alignment, number formats, conditional formats, validations, tables, notes, hyperlinks, autofilters, images, protection and page setup. Formulas and styles read back too.
|
|
35
35
|
- **Older and open formats**: the same reader opens Excel 97-2003 `.xls` files and OpenDocument `.ods` files, and `OdsWriter` writes `.ods`.
|
|
@@ -73,6 +73,7 @@ Dates come back as ISO-8601 strings. Opt in to more detail, each indexed like `r
|
|
|
73
73
|
- `{ formulas: true }` gives `row.formulas`, with shared formulas expanded per cell.
|
|
74
74
|
- `{ styles: true }` gives `row.styles`, as `CellStyle` objects (the same shape the writer takes). Theme and palette colours are resolved to ARGB.
|
|
75
75
|
- `{ richText: true }` gives `row.richText`, the formatted runs of cells that have them. `row.cells` still holds the plain text.
|
|
76
|
+
- `{ errors: true }` gives `row.errors`, `true` for the cells that hold an error value such as `#N/A`. `row.cells` gives errors as text, so this tells them from text that reads `#N/A` (`.xlsx` only).
|
|
76
77
|
- `{ formatted: true }` gives `row.formatted`, each cell's text as Excel (en-US) shows it: `1,234.50`, `25.6%`, `(42)`, `08-Oct-2026 2:05 PM`. It covers sections, conditions, dates and elapsed times, fractions, scientific notation, currency and text formats. Repeat fills (`*`) and colours are left out, and other locales are shown as en-US.
|
|
77
78
|
|
|
78
79
|
`await reader.readWorkbook(createBlobReader(blob))` lists the sheets with their visibility, the defined names and the document properties, without reading any sheet.
|
|
@@ -88,11 +89,20 @@ Parts held in memory (workbook, shared strings, styles) are capped at 1 GiB unco
|
|
|
88
89
|
In Node.js, read straight from disk with `XlsxFlow.readFile`, or pass `await createFileReader(path)` to any function that takes a reader:
|
|
89
90
|
|
|
90
91
|
```typescript
|
|
91
|
-
import { XlsxFlow } from '@xlsxflow/core';
|
|
92
|
+
import { XlsxFlow, SheetReader, createFileReader } from '@xlsxflow/core';
|
|
92
93
|
|
|
93
94
|
for await (const row of await XlsxFlow.readFile('./data.xlsx')) {
|
|
94
95
|
console.log(row.cells);
|
|
95
96
|
}
|
|
97
|
+
|
|
98
|
+
// createFileReader keeps the file open until you close it, after you are done with
|
|
99
|
+
// everything read through it (Node 25 stops the process when an open file is garbage-collected)
|
|
100
|
+
const file = await createFileReader('./data.xlsx');
|
|
101
|
+
try {
|
|
102
|
+
console.log((await new SheetReader().readWorkbook(file)).sheets);
|
|
103
|
+
} finally {
|
|
104
|
+
await file.close();
|
|
105
|
+
}
|
|
96
106
|
```
|
|
97
107
|
|
|
98
108
|
### Writing an Excel File
|
|
@@ -180,7 +190,7 @@ editor.setCells('Sheet1', {
|
|
|
180
190
|
A1: { style: { font: { bold: true }, fill: { type: 'solid', fgColor: 'FFFFFF00' } } }, // restyle, keep content
|
|
181
191
|
B3: { value: 7, style: { numFmt: '0.00' } },
|
|
182
192
|
});
|
|
183
|
-
editor.appendSheet('Sheet1', [['new', 'row']]); //
|
|
193
|
+
editor.appendSheet('Sheet1', [['new', 'row']]); // after the last existing row (values, formulas, styles)
|
|
184
194
|
editor.insertRows('Sheet1', 5, 3); // 3 empty rows before row 5
|
|
185
195
|
editor.deleteRows('Sheet1', 20, 2); // rows 20-21
|
|
186
196
|
editor.insertColumns('Sheet1', 'C'); // or deleteColumns('Sheet1', 'C', 2)
|
|
@@ -193,10 +203,10 @@ Edited cells keep their style. A style change is merged into the cell's current
|
|
|
193
203
|
|
|
194
204
|
Macro-enabled workbooks (`.xlsm`) keep their VBA project and content type through every edit.
|
|
195
205
|
|
|
196
|
-
`addSheet`
|
|
206
|
+
`addSheet` and `appendSheet` take arrays of rows with values, formulas and styles; for hyperlinks, notes and sheet options, write the workbook with `SheetWriter`. Calling `appendSheet` again for a sheet adds the rows after the earlier ones. `deleteSheet` removes names scoped to the sheet and turns other defined names that point at it into `#REF!`; formulas in other sheets that point at it are not rewritten. `insertRows`, `deleteRows`, `insertColumns` and `deleteColumns` move everything that points at the cells, as Excel does:
|
|
197
207
|
- formulas on every sheet and the workbook's defined names (print areas, named ranges);
|
|
198
208
|
- merged cells, conditional formats, validations, hyperlinks, the filter and its column filters, page breaks and column widths;
|
|
199
|
-
- tables, pictures, notes, sparklines, What-If data tables, chart series and pivot
|
|
209
|
+
- tables, pictures, notes, sparklines, What-If data tables, chart series, and pivot tables and their sources.
|
|
200
210
|
|
|
201
211
|
Ranges that span inserted rows or columns grow, and ranges over deleted ones shrink. References to deleted cells become `#REF!`. Columns inserted inside a table become table columns named Column1, Column2 and so on. Deleting a table's header row, all its data rows or all its columns is refused. Operations run in the order given, and `setCells` addresses count after the cells have moved. Inserted rows and columns are empty: they don't copy the formatting of their neighbours. Every sheet streams through the editor, because any of its formulas might point at the moved cells.
|
|
202
212
|
|
|
@@ -242,7 +252,7 @@ writer.addSheet('Report', rows, {
|
|
|
242
252
|
protection: { password: 'secret', sort: true }, // Excel's legacy hash: deters edits, is not encryption
|
|
243
253
|
pageSetup: { orientation: 'landscape', paperSize: 9, fitToWidth: 1, fitToHeight: 0, printArea: 'A1:C100', printTitleRows: '1', footer: '&CPage &P of &N' },
|
|
244
254
|
tabColor: 'FF00B050',
|
|
245
|
-
mergeCells: ['
|
|
255
|
+
mergeCells: ['E1:G1'], // not inside a table: Excel tables cannot hold merged cells
|
|
246
256
|
columnWidths: [30, 12], // in characters; `columns[i].width` wins where both are set
|
|
247
257
|
autoFitColumns: true, // widths from the longest value (array rows only)
|
|
248
258
|
});
|
|
@@ -250,13 +260,13 @@ writer.addSheet('Report', rows, {
|
|
|
250
260
|
// Formatted notes: comment: { text: [{ text: 'Ana:', font: { bold: true } }, { text: ' restated' }] }
|
|
251
261
|
```
|
|
252
262
|
|
|
253
|
-
Formulas are stored for Excel to calculate when it opens the file. For array rows, the writer also stores a cached result for simple formulas (`SUM`, `AVERAGE`, `COUNT`, `MIN`, `MAX`, `IF`, `CONCATENATE
|
|
263
|
+
Formulas are stored for Excel to calculate when it opens the file. For array rows, the writer also stores a cached result for simple formulas (`SUM`, `AVERAGE`, `COUNT`, `MIN`, `MAX`, `IF`, `CONCATENATE`, `&`, comparisons and arithmetic, including over other formula cells), so other readers see a value. Errors are stored as error values (`#DIV/0!`). Rows from an AsyncIterable get no cached results, since the writer cannot look back at them.
|
|
254
264
|
|
|
255
|
-
Strings are written inline, which keeps memory flat. `new SheetWriter({ sharedStrings: true })` stores each distinct string once instead. Files are smaller when
|
|
265
|
+
Strings are written inline, which keeps memory flat. `new SheetWriter({ sharedStrings: true })` stores each distinct string once instead. Files are smaller when many different strings repeat (with only a handful of distinct values, inline strings compress as well or better), but the distinct strings stay in memory until the file is finished.
|
|
256
266
|
|
|
257
267
|
## Compared with SheetJS and ExcelJS
|
|
258
268
|
|
|
259
|
-
Checked against each project's own documentation on
|
|
269
|
+
Checked against each project's own documentation, and ExcelJS 4.4.0's published code, on 9 October 2026. "Pro" means a paid add-on.
|
|
260
270
|
|
|
261
271
|
| | XlsxFlow | SheetJS Community Edition | ExcelJS 4.4 |
|
|
262
272
|
|---|---|---|---|
|
|
@@ -267,7 +277,7 @@ Checked against each project's own documentation on 8 October 2026. "Pro" means
|
|
|
267
277
|
| `.ods` | Read and write | Read and write | No |
|
|
268
278
|
| `.xlsb`, `.numbers` and other formats | No | Yes | No |
|
|
269
279
|
| Charts | Add (Pro) | No (SheetJS Pro) | No |
|
|
270
|
-
| Pivot tables | Add (Pro) | No (SheetJS Pro) |
|
|
280
|
+
| Pivot tables | Add (Pro) | No (SheetJS Pro) | No |
|
|
271
281
|
| Password-protected files | Open and save (Pro) | Old `.xls` obfuscation only (SheetJS Pro opens AES files) | No |
|
|
272
282
|
| Licence | MIT, Pro is paid | Apache 2.0 | MIT |
|
|
273
283
|
|