@xlsxflow/core 1.1.2 → 1.1.4
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 +146 -108
- package/README.md +7 -4
- package/dist/index.cjs +1151 -789
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -8
- package/dist/index.d.ts +32 -8
- package/dist/index.mjs +1151 -790
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,108 +1,146 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
## 1.1.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- `
|
|
10
|
-
-
|
|
11
|
-
- `
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- `
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
- `
|
|
32
|
-
- `
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
###
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
-
|
|
65
|
-
-
|
|
66
|
-
- `
|
|
67
|
-
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
- `
|
|
80
|
-
|
|
81
|
-
###
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
-
|
|
86
|
-
-
|
|
87
|
-
-
|
|
88
|
-
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
-
|
|
104
|
-
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.1.4
|
|
4
|
+
|
|
5
|
+
Fixes from the third round of end-user tests (700 cases).
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- `XlsxFlow.readFile` reads `.ods` files, and `getComments()` / `getImages()` work after reading an `.xlsx` with it.
|
|
10
|
+
- 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.
|
|
11
|
+
- `SheetWriter` stores formula text that starts with `#` as text, not as an error cell Excel repairs.
|
|
12
|
+
- `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).
|
|
13
|
+
- 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).
|
|
14
|
+
- `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.
|
|
15
|
+
- `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.
|
|
16
|
+
- `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.
|
|
17
|
+
- `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.
|
|
18
|
+
- `sheetToJson` keeps values right of the header row (`Column3`); `streamToCsv` keeps blank rows between rows.
|
|
19
|
+
- `parseCsv` keeps numbers that overflow a double (`1e400`) as text.
|
|
20
|
+
- `OdsWriter` keeps the milliseconds of dates and converts whole-column references (`SUM(C:C)`); the `.ods` reader reads the created date as UTC.
|
|
21
|
+
- 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.
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- The `errors` parse option: `row.errors` marks cells holding error values.
|
|
26
|
+
|
|
27
|
+
## 1.1.3
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- `SheetEditor.setCells` refuses addresses past column XFD or row 1,048,576, instead of writing a file Excel reports as damaged.
|
|
32
|
+
- `SheetWriter` and `SheetEditor` refuse text longer than Excel's 32,767 characters per cell.
|
|
33
|
+
- Colours are checked: ARGB (`FFFF0000`) and RGB (`FF0000`, `#FF0000`) hex are accepted, anything else (`'red'`) throws instead of making Excel repair the file.
|
|
34
|
+
- Picture anchors past the last column or row throw; a range given the wrong way round (`F20:A2`) is turned round.
|
|
35
|
+
- `SheetReader`: a shared string index past the end of the table reads as an empty cell, not as the index.
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
|
|
39
|
+
- `checkCellText` is exported, for `@xlsxflow/pro`.
|
|
40
|
+
|
|
41
|
+
## 1.1.2
|
|
42
|
+
|
|
43
|
+
### Fixed
|
|
44
|
+
|
|
45
|
+
- `SheetWriter` throws an error for a row longer than 16,384 cells or past row 1,048,576, instead of writing a file Excel reports as damaged.
|
|
46
|
+
- `SheetEditor.setCells`: a date in a cell without a date format gets `yyyy-mm-dd` (or `yyyy-mm-dd hh:mm:ss` with a time), as in `SheetWriter`, instead of showing as a serial number.
|
|
47
|
+
- `OdsWriter` stores formula results, so readers that don't recalculate show them.
|
|
48
|
+
- `sheetToJson` keeps every column when headers repeat: the second `Name` becomes `Name_2`.
|
|
49
|
+
- `parseCsv` returns `null` for empty unquoted fields with `{ convert: false }` too.
|
|
50
|
+
|
|
51
|
+
### Added
|
|
52
|
+
|
|
53
|
+
- `StylePatcher` is exported, for `@xlsxflow/pro`.
|
|
54
|
+
|
|
55
|
+
## 1.1.1
|
|
56
|
+
|
|
57
|
+
- README: the XlsxFlow website address, and Pro at a flat $5.
|
|
58
|
+
- More npm keywords: `xls` and `ods`.
|
|
59
|
+
|
|
60
|
+
## 1.1.0
|
|
61
|
+
|
|
62
|
+
### Added
|
|
63
|
+
|
|
64
|
+
- `SheetWriter`: workbook properties (title, author, company and so on), defined names, hidden and very hidden sheets, and sheet views (zoom, gridlines, headings, right-to-left). `SheetReader.readWorkbook` reads them back.
|
|
65
|
+
- `{ formatted: true }` reports each cell's text as Excel shows it, from its number format.
|
|
66
|
+
- `SheetEditor.insertRows`, `deleteRows`, `insertColumns` and `deleteColumns`. Everything that points at the moved cells moves with them: formulas on all sheets, defined names, merges, conditional formats, validations, hyperlinks, filters, page breaks, column widths, tables, pictures, notes, sparklines, data tables, chart series and pivot sources.
|
|
67
|
+
- `SheetEditor.setCells` edits and restyles cells of existing files; `addSheet` and `deleteSheet` add and remove sheets.
|
|
68
|
+
- `parseCsv` streams CSV rows, which `SheetWriter.addSheet` turns into a sheet.
|
|
69
|
+
- `SheetReader` reads Excel 97-2003 `.xls` files and OpenDocument `.ods` files: values, dates, formula results, merges, hidden rows, columns and sheets, frozen panes, defined names and document properties. `.ods` also gives formulas, hyperlinks and notes.
|
|
70
|
+
- `OdsWriter` writes `.ods` files: values, dates, formulas, merges, column widths, frozen panes and hidden sheets.
|
|
71
|
+
- Password-protected `.xlsx` files are rejected with an error that points to `decryptWorkbook` in `@xlsxflow/pro`, instead of a ZIP error.
|
|
72
|
+
- Cell notes on write (plain or formatted text) and `getComments()` on read.
|
|
73
|
+
- Conditional formats `cellIs`, `expression`, `top10`, `aboveAverage`, text rules, `duplicateValues`/`uniqueValues` and `iconSet`.
|
|
74
|
+
- Excel tables, sheet protection, page setup (margins, header and footer, print area and titles), row heights, hidden rows and columns, outline grouping, tab colour, and validation operators and messages.
|
|
75
|
+
- `Date` cell values, hyperlinks (URLs and locations in the workbook), `autoFilter`, and an optional shared string table on write.
|
|
76
|
+
- Reading returns formulas (`formulas: true`, shared formulas expanded), styles (`styles: true`) and rich text (`richText: true`). Theme and indexed colours are resolved to ARGB.
|
|
77
|
+
- PNG, JPEG and GIF images (`images` sheet option), anchored to a cell or stretched over a range. `getImages()` reads them back.
|
|
78
|
+
- Low-level parts are exported for add-ons: the ZIP reader and writer, `resolveWorkbookParts`, `readSharedStrings`, and `mapFormulaRefs`/`shiftFormula`.
|
|
79
|
+
- Tested: `.xlsm` files keep their macros through `SheetEditor`; the library runs in Cloudflare Workers without `nodejs_compat` (`scripts/workers` checks it).
|
|
80
|
+
|
|
81
|
+
### Security
|
|
82
|
+
|
|
83
|
+
Fixed crashes, hangs and memory blowups caused by crafted files:
|
|
84
|
+
|
|
85
|
+
- A ZIP directory pointing outside the file crashed Node.
|
|
86
|
+
- Unclosed tags and elements made the parser quadratic. The XML tokenizer is now linear on giant tags, text nodes and CDATA.
|
|
87
|
+
- Repeated hidden columns, far-right cells, fraction formats with long denominators and large style tables were slow or used unbounded memory.
|
|
88
|
+
- One deflated entry could be read many times under different names.
|
|
89
|
+
|
|
90
|
+
Also:
|
|
91
|
+
|
|
92
|
+
- `SheetEditor.edit` takes `maxUncompressedBytes`.
|
|
93
|
+
- Option values typed as enums are escaped, and appended rows encode control characters.
|
|
94
|
+
- `sheetToJson` keeps a `__proto__` header as an ordinary key.
|
|
95
|
+
- In-memory parts are capped at 1 GiB uncompressed by default.
|
|
96
|
+
|
|
97
|
+
### Fixed
|
|
98
|
+
|
|
99
|
+
- Sheets with frozen panes were all marked as selected, so Excel opened them grouped.
|
|
100
|
+
- The reader dropped or corrupted cells at stream chunk boundaries.
|
|
101
|
+
- Styles pointed at the wrong font, fill or border, and styles used only by `AsyncIterable` rows were missing from `styles.xml`.
|
|
102
|
+
- Number formats with quoted text, escapes or colours (`#,##0.00 "USD"`, `[Red]0.0`) were taken for date formats.
|
|
103
|
+
- Reading a corrupt file without calling `getMetadata()` caused an unhandled promise rejection, which is fatal in Node.
|
|
104
|
+
- `addSheet` accepted sheet names Excel refuses to open. It now throws.
|
|
105
|
+
- Files Excel would repair:
|
|
106
|
+
- gradient stops were written as `<gradientStop>`;
|
|
107
|
+
- `vertical: 'middle'` was written as is instead of `center`;
|
|
108
|
+
- conditional formats came after validations.
|
|
109
|
+
- Data bar `minValue`/`maxValue` were ignored, every conditional format had priority 1, and colours and ranges were not XML-escaped.
|
|
110
|
+
- Strings with `_xHHHH_`, control characters, CR, or leading and trailing spaces now survive a round trip. `NaN` and `Infinity` are written as `#NUM!`.
|
|
111
|
+
- Reader:
|
|
112
|
+
- Strict OOXML and non-standard part names work;
|
|
113
|
+
- empty `<v/>` reads as empty and `-0` as `0`;
|
|
114
|
+
- out-of-order cells land in the right column;
|
|
115
|
+
- time-only values are no longer a day off, and datetimes keep milliseconds.
|
|
116
|
+
- frozen panes saved by Excel as `frozenSplit` (frozen after a split) are reported.
|
|
117
|
+
- `sheetToJson` ignored its `headerRowIndex` argument.
|
|
118
|
+
|
|
119
|
+
### Changed
|
|
120
|
+
|
|
121
|
+
- The package ships compiled ESM and CommonJS builds with type declarations.
|
|
122
|
+
- Browser bundles no longer try to resolve Node's `fs`.
|
|
123
|
+
- `[Content_Types].xml` is written last in the ZIP.
|
|
124
|
+
- Real backpressure in the ZIP writer and worksheet stream. Producer errors now error the output stream instead of hanging it.
|
|
125
|
+
- About 2.5× faster reads, and a table-driven CRC-32 for faster writes.
|
|
126
|
+
- Styles, formulas and conditional formats are part of the MIT core. Paid add-ons are in the separate `@xlsxflow/pro` package.
|
|
127
|
+
- Benchmarks corrected: the earlier ExcelJS write time came from a cold first run, and write-excel-file was run with an old API.
|
|
128
|
+
|
|
129
|
+
## 1.0.0
|
|
130
|
+
|
|
131
|
+
- `SheetWriter` and `SheetEditor` stream the ZIP with data descriptors instead of buffering the file in memory.
|
|
132
|
+
- Dates are returned as ISO-8601 strings, detected from each cell's number format.
|
|
133
|
+
|
|
134
|
+
## 0.3.0-beta
|
|
135
|
+
|
|
136
|
+
- Workbooks with several sheets.
|
|
137
|
+
- Fixed a buffer bug that made parsing quadratic.
|
|
138
|
+
|
|
139
|
+
## 0.2.0-beta
|
|
140
|
+
|
|
141
|
+
- Deflate compression with `CompressionStream`: a 1M-cell file went from 30 MB to 2.9 MB.
|
|
142
|
+
- Inline and rich text strings are read.
|
|
143
|
+
|
|
144
|
+
## 0.1.0-beta
|
|
145
|
+
|
|
146
|
+
- First release: streaming reader, writer, and shared strings.
|
package/README.md
CHANGED
|
@@ -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.
|
|
@@ -180,7 +181,7 @@ editor.setCells('Sheet1', {
|
|
|
180
181
|
A1: { style: { font: { bold: true }, fill: { type: 'solid', fgColor: 'FFFFFF00' } } }, // restyle, keep content
|
|
181
182
|
B3: { value: 7, style: { numFmt: '0.00' } },
|
|
182
183
|
});
|
|
183
|
-
editor.appendSheet('Sheet1', [['new', 'row']]); //
|
|
184
|
+
editor.appendSheet('Sheet1', [['new', 'row']]); // after the last existing row (values, formulas, styles)
|
|
184
185
|
editor.insertRows('Sheet1', 5, 3); // 3 empty rows before row 5
|
|
185
186
|
editor.deleteRows('Sheet1', 20, 2); // rows 20-21
|
|
186
187
|
editor.insertColumns('Sheet1', 'C'); // or deleteColumns('Sheet1', 'C', 2)
|
|
@@ -193,10 +194,10 @@ Edited cells keep their style. A style change is merged into the cell's current
|
|
|
193
194
|
|
|
194
195
|
Macro-enabled workbooks (`.xlsm`) keep their VBA project and content type through every edit.
|
|
195
196
|
|
|
196
|
-
`addSheet`
|
|
197
|
+
`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
198
|
- formulas on every sheet and the workbook's defined names (print areas, named ranges);
|
|
198
199
|
- 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
|
|
200
|
+
- tables, pictures, notes, sparklines, What-If data tables, chart series, and pivot tables and their sources.
|
|
200
201
|
|
|
201
202
|
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
203
|
|
|
@@ -224,6 +225,8 @@ writer.addSheet('Sales', [
|
|
|
224
225
|
});
|
|
225
226
|
```
|
|
226
227
|
|
|
228
|
+
Colours are ARGB hex (`FFC00000`); RGB hex (`C00000` or `#C00000`) is opaque. A cell holds at most 32,767 characters, as in Excel.
|
|
229
|
+
|
|
227
230
|
Other sheet options:
|
|
228
231
|
|
|
229
232
|
```typescript
|
|
@@ -248,7 +251,7 @@ writer.addSheet('Report', rows, {
|
|
|
248
251
|
// Formatted notes: comment: { text: [{ text: 'Ana:', font: { bold: true } }, { text: ' restated' }] }
|
|
249
252
|
```
|
|
250
253
|
|
|
251
|
-
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
|
|
254
|
+
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.
|
|
252
255
|
|
|
253
256
|
Strings are written inline, which keeps memory flat. `new SheetWriter({ sharedStrings: true })` stores each distinct string once instead. Files are smaller when values repeat, but the distinct strings stay in memory until the file is finished.
|
|
254
257
|
|