xlvane 1.3.1 → 1.3.3
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 +3 -3
- package/dist/cli.js +7 -7
- package/docs/errors.md +9 -9
- package/docs/exceljs-compat.md +9 -9
- package/docs/migrate-from-exceljs.md +16 -16
- package/llms-full.txt +39 -39
- package/package.json +2 -2
- package/skills/xlvane/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -31,11 +31,11 @@ From a shell: `npx xlvane inspect orders.xlsx`, then `npx xlvane read orders.xls
|
|
|
31
31
|
- [Large files: streaming](#large-files-streaming)
|
|
32
32
|
- [Inspecting a workbook](#inspecting-a-workbook) · [Errors and warnings](#errors-and-warnings) · [Untrusted input and limits](#untrusted-input-and-limits)
|
|
33
33
|
- [Limitations](#limitations) · [Package size](#package-size) · [Links](#links)
|
|
34
|
-
- exceljs users: [`@xlvane/
|
|
34
|
+
- exceljs users: [`@xlvane/exceljs`](https://www.npmjs.com/package/@xlvane/exceljs) and `xlvane migrate`
|
|
35
35
|
|
|
36
36
|
## Tested environments
|
|
37
37
|
|
|
38
|
-
The core API (reading, writing, inspect, tables, CSV, editing, diff, streaming with Web Streams) and `@xlvane/
|
|
38
|
+
The core API (reading, writing, inspect, tables, CSV, editing, diff, streaming with Web Streams) and `@xlvane/exceljs` are tested in Node.js 22, 24 and 26, Bun, Deno, Chromium (Playwright) and the Cloudflare Workers runtime (workerd), with the same test bundle (`npm run test:runtimes`). In Deno, import from `npm:xlvane`; in browsers and Workers, through a bundler such as Vite, esbuild or webpack. `xlvane/node` and the command line need Node.js. Reading is tested on 340 files of the Apache POI test corpus (written by Excel for Windows, Mac and the web, LibreOffice, ONLYOFFICE and others, and damaged files) and on files saved by LibreOffice; see `tests/corpus/`.
|
|
39
39
|
|
|
40
40
|
## Command line in 5 minutes
|
|
41
41
|
|
|
@@ -58,7 +58,7 @@ xlvane help edit # usage and examples of one command
|
|
|
58
58
|
- `--json` prints one JSON document per command with a documented schema ([docs/cli-json.md](https://github.com/DevXord/xlvane/blob/main/docs/cli-json.md)). Exit codes: 0 success, 1 a check found something (`diff`, `validate`), 2 usage error, 3 input or file error.
|
|
59
59
|
- Colour (red errors, yellow warnings, green results, bold headings) is used only on a terminal and never carries information alone; `NO_COLOR` or `TERM=dumb` turn it off, `FORCE_COLOR=1` turns it on. Control characters from files, such as an escape character in a cell, are shown as `\x1b` and never reach the terminal.
|
|
60
60
|
- Tables and summaries go to separate streams: `xlvane read report.xlsx > out.txt` writes only the table; the row count and warnings notes go to stderr.
|
|
61
|
-
- `xlvane migrate` prepares a project for `@xlvane/
|
|
61
|
+
- `xlvane migrate` prepares a project for `@xlvane/exceljs`, and `xlvane mcp` starts the MCP server from `@xlvane/mcp` (a separate package; [its README](https://github.com/DevXord/xlvane/blob/main/packages/mcp/README.md)).
|
|
62
62
|
|
|
63
63
|
## Reading a workbook
|
|
64
64
|
|
package/dist/cli.js
CHANGED
|
@@ -1977,8 +1977,8 @@ const mcpCommand = {
|
|
|
1977
1977
|
}
|
|
1978
1978
|
};
|
|
1979
1979
|
// src/cli/commands/migrate.ts
|
|
1980
|
-
/** The dependency value that installs @xlvane/
|
|
1981
|
-
const ALIAS = "npm:@xlvane/
|
|
1980
|
+
/** The dependency value that installs @xlvane/exceljs under the name exceljs (npm alias). */
|
|
1981
|
+
const ALIAS = "npm:@xlvane/exceljs@^1";
|
|
1982
1982
|
const SECTIONS = [
|
|
1983
1983
|
"dependencies",
|
|
1984
1984
|
"devDependencies",
|
|
@@ -1989,7 +1989,7 @@ const SOURCE = /\.(?:js|mjs|cjs|jsx|ts|mts|cts|tsx)$/;
|
|
|
1989
1989
|
const MAX_FILES = 1e4;
|
|
1990
1990
|
const MAX_FILE_BYTES = 2097152;
|
|
1991
1991
|
/**
|
|
1992
|
-
* exceljs API that @xlvane/
|
|
1992
|
+
* exceljs API that @xlvane/exceljs does not support or supports only partly
|
|
1993
1993
|
* (docs/exceljs-compat.md). Matching is textual, so a hit is a place to look at, not proof.
|
|
1994
1994
|
*/
|
|
1995
1995
|
const PATTERNS = [{
|
|
@@ -2217,8 +2217,8 @@ async function run$1(ctx) {
|
|
|
2217
2217
|
lines.push(`${out.bold("Change in")} ${pkgPath}:`);
|
|
2218
2218
|
for (const c of changes) lines.push(` ${c.section}: ${out.red(`- "exceljs": "${escapeControls(c.from)}"`)}`, ` ${" ".repeat(c.section.length)} ${out.green(`+ "exceljs": "${escapeControls(c.to)}"`)}`);
|
|
2219
2219
|
}
|
|
2220
|
-
lines.push(`Node.js: require('exceljs') of @xlvane/
|
|
2221
|
-
lines.push("", `Scanned ${plural(files.length, "source file")}${limited ? ` (stopped at ${String(MAX_FILES)})` : ""} for exceljs API that @xlvane/
|
|
2220
|
+
lines.push(`Node.js: require('exceljs') of @xlvane/exceljs needs Node.js 22.12 or later (package.json engines.node: ${typeof engines === "string" ? `"${escapeControls(engines)}"` : "not set"}).`);
|
|
2221
|
+
lines.push("", `Scanned ${plural(files.length, "source file")}${limited ? ` (stopped at ${String(MAX_FILES)})` : ""} for exceljs API that @xlvane/exceljs does not fully support:`);
|
|
2222
2222
|
if (findings.length === 0) lines.push(" none found.");
|
|
2223
2223
|
for (const f of findings.slice(0, 200)) lines.push(` ${f.status === "partly" ? out.yellow("partly ") : out.red("not supported")} ${escapeControls(f.file)}:${String(f.line)}:${String(f.column)} ${escapeControls(f.api)}`);
|
|
2224
2224
|
if (findings.length > 200) lines.push(out.dim(` … ${String(findings.length - 200)} more; use --json for all`));
|
|
@@ -2241,8 +2241,8 @@ async function run$1(ctx) {
|
|
|
2241
2241
|
}
|
|
2242
2242
|
const migrateCommand = {
|
|
2243
2243
|
name: "migrate",
|
|
2244
|
-
summary: "Switch a project from exceljs to @xlvane/
|
|
2245
|
-
description: "Prepares a project for @xlvane/
|
|
2244
|
+
summary: "Switch a project from exceljs to @xlvane/exceljs",
|
|
2245
|
+
description: "Prepares a project for @xlvane/exceljs, which offers the commonly used exceljs API. It shows the change to package.json (\"exceljs\": \"npm:@xlvane/exceljs@^1\", an npm alias, so the code keeps importing \"exceljs\") and lists places in the source code that use exceljs API outside the supported subset. Only files that mention exceljs are scanned (node_modules and dot folders are skipped), and matching is textual. package.json is changed only with --force; nothing else is changed.",
|
|
2246
2246
|
usage: "[project-dir] [options]",
|
|
2247
2247
|
positionals: {
|
|
2248
2248
|
min: 0,
|
package/docs/errors.md
CHANGED
|
@@ -14,7 +14,7 @@ Each code links to its section, which says what to do. The CLI prints the code a
|
|
|
14
14
|
| --- | --- |
|
|
15
15
|
| [`XLV_E_INVALID_INPUT`](#xlv_e_invalid_input) | The input is not what the function expects: `readWorkbook` and `inspect` accept a `Uint8Array`, an `ArrayBuffer` (or another typed-array … |
|
|
16
16
|
| [`XLV_E_INVALID_OPTION`](#xlv_e_invalid_option) | An option is unknown, has the wrong type or is out of range. |
|
|
17
|
-
| [`XLV_E_INVALID_ARGUMENT`](#xlv_e_invalid_argument) | An argument would lose or move data: a method of `@xlvane/
|
|
17
|
+
| [`XLV_E_INVALID_ARGUMENT`](#xlv_e_invalid_argument) | An argument would lose or move data: a method of `@xlvane/exceljs` where exceljs 4.4.0 accepts it silently, or `appendRows` with array rows when the starting column is ambiguous. |
|
|
18
18
|
| [`XLV_E_LIMIT_EXCEEDED`](#xlv_e_limit_exceeded) | The file exceeds one of the resource limits (`ReadLimits`): input size, number of ZIP entries, decompressed size of one entry or of all … |
|
|
19
19
|
| [`XLV_E_NOT_ZIP`](#xlv_e_not_zip) | The input is not a ZIP archive, so it cannot be an XLSX file. |
|
|
20
20
|
| [`XLV_E_UNSUPPORTED_CONTAINER`](#xlv_e_unsupported_container) | The input is a Compound File Binary container (signature `D0 CF 11 E0 A1 B1 1A E1`). |
|
|
@@ -48,7 +48,7 @@ Each code links to its section, which says what to do. The CLI prints the code a
|
|
|
48
48
|
| [`XLV_E_INVALID_ROWS`](#xlv_e_invalid_rows) | Rows given to `writeTable`, `fromJSON` or `appendRows` have the wrong shape: not an array, rows mixing objects and arrays, a value that … |
|
|
49
49
|
| [`XLV_E_JSON_INVALID`](#xlv_e_json_invalid) | The text given to `fromJSON` is not valid JSON. |
|
|
50
50
|
| [`XLV_E_CSV_MALFORMED`](#xlv_e_csv_malformed) | The CSV text given to `fromCSV` has a quoted field that is never closed, text right after a closing quote, or bytes that are not valid … |
|
|
51
|
-
| [`XLV_E_NOT_SUPPORTED`](#xlv_e_not_supported) | `@xlvane/
|
|
51
|
+
| [`XLV_E_NOT_SUPPORTED`](#xlv_e_not_supported) | `@xlvane/exceljs` was asked for an exceljs feature it does not implement, for example a rich-text or hyperlink value, images, tables, … |
|
|
52
52
|
| [`XLV_E_USAGE`](#xlv_e_usage) | The `xlvane` command line was used incorrectly: an unknown command or option, a missing or extra argument, an option without its value, … |
|
|
53
53
|
| [`XLV_E_INTERNAL`](#xlv_e_internal) | The `xlvane` command line caught an error that is not an `XlvError`. |
|
|
54
54
|
| [`XLV_E_NOT_INSTALLED`](#xlv_e_not_installed) | `xlvane mcp` needs the separate package `@xlvane/mcp`, which could not be loaded. |
|
|
@@ -89,7 +89,7 @@ The settings of a note box (`box` of a note: `margins` in millimetres from 0 to
|
|
|
89
89
|
**Fix:** correct the option name or value.
|
|
90
90
|
|
|
91
91
|
### XLV_E_INVALID_ARGUMENT
|
|
92
|
-
An argument of a method of `@xlvane/
|
|
92
|
+
An argument of a method of `@xlvane/exceljs` is not valid, in a case where exceljs 4.4.0 accepts it and loses or moves data without an error: for example `insertRow(0, …)`, a row position given as a string, a negative count in `spliceRows` or `spliceColumns`, an outline level outside 0–7 set on a row or column (exceljs writes it), `duplicateRow` of a row that does not exist, `insertRows` without an array of values, or rows or columns pushed beyond the sheet (row 1048576, column XFD). `details.method`, `details.argument` and `details.value` name the method, the argument and its value (docs/exceljs-compat.md).
|
|
93
93
|
`appendRows` throws it for array rows when tables that start in different columns reach the sheet's last used row, so the column where the rows start is ambiguous (D-K04); `details.tables` names the tables and `details.row` the row. Pass object rows keyed by header text.
|
|
94
94
|
**Fix:** pass a whole number in the range the hint gives (rows from 1, columns from 1), or remove rows at the end of the sheet before inserting.
|
|
95
95
|
|
|
@@ -98,21 +98,21 @@ The file exceeds one of the resource limits (`ReadLimits`): input size, number o
|
|
|
98
98
|
|
|
99
99
|
Some limits also bound work derived from a small file (1.1.1, D-H01):
|
|
100
100
|
|
|
101
|
-
- `maxCells` (`details.limit` `maxCells`, `details.value` the budget): `toCSV`, `readTable`, `toJSON`, `readTableStream`, `xlvane read` and `xlvane convert` write at most `max(maxCells, 16 × cells read)` positions (rows × columns of the output), so a few cells far apart cannot make them produce a value for every position between; `@xlvane/
|
|
101
|
+
- `maxCells` (`details.limit` `maxCells`, `details.value` the budget): `toCSV`, `readTable`, `toJSON`, `readTableStream`, `xlvane read` and `xlvane convert` write at most `max(maxCells, 16 × cells read)` positions (rows × columns of the output), so a few cells far apart cannot make them produce a value for every position between; `@xlvane/exceljs`'s `xlsx.load` creates at most as many cells for merged ranges, tables and column definitions, and looks up at most 64 Mi rows (or 16 per cell read) for row settings up to the sheets' dimensions. Pass a smaller `range`, or raise `maxCells` for a trusted file.
|
|
102
102
|
- `maxXmlTextLength`: also the length of an XML comment or processing instruction.
|
|
103
103
|
- `maxSharedStringChars`: also the text of shared formulas, counted apart from shared strings: the length of each sharing cell's formula, as moved to that cell. From 1.2.3 (D-J01) also the header names that `readTable`, `toJSON` and `readTableStream` repeat in every row object: the sum of the key lengths times the number of rows (a long header over many rows would otherwise make JSON text far larger than the file); `readTableStream` counts one row at a time.
|
|
104
104
|
|
|
105
105
|
From 1.2.3 (D-J01):
|
|
106
106
|
|
|
107
|
-
- `maxCells`: `fromCSV`, `fromJSON` and `writeTable` write at most `max(maxCells, 16 × cells written)` positions (rows × columns), so one very wide row followed by many short ones cannot make them visit every position; each takes a `maxCells` option (default 5 000 000). While streaming, one `<row>` element may hold at most 16 384 cells (`details.value` 16384), the most a row can have, because its cells are held until the element ends. `@xlvane/
|
|
107
|
+
- `maxCells`: `fromCSV`, `fromJSON` and `writeTable` write at most `max(maxCells, 16 × cells written)` positions (rows × columns), so one very wide row followed by many short ones cannot make them visit every position; each takes a `maxCells` option (default 5 000 000). While streaming, one `<row>` element may hold at most 16 384 cells (`details.value` 16384), the most a row can have, because its cells are held until the element ends. `@xlvane/exceljs` `xlsx.load` also counts the cells of defined names against its budget, and its `xlsx.read`, `csv.read` and `stream.xlsx.WorkbookReader` stop collecting a stream after `maxInputBytes` (256 MiB; `details.limit` `maxInputBytes`).
|
|
108
108
|
|
|
109
109
|
From 1.3.0 (D-K04):
|
|
110
110
|
|
|
111
111
|
- `maxCells`: `editCells` and `appendRows` check, before building any cell, that the cells of the workbook (with a value or only a style) plus the new cells stay within `maxCells`, so the result can be read with the same limits, and they write at most 1 000 000 cells per call unless `limits.maxCells` is given, then at most `maxCells` (`details.limit` `maxCells`, `details.value` the limit). Each cell written takes about 0.5 KB of memory while the file is rebuilt; split the edits into several calls, or pass a larger `maxCells` if there is enough memory.
|
|
112
112
|
- `maxCells`: `insertRows` with `style: 'above'` or `'below'` (and `xlvane edit --insert-rows` with a style) counts the formatted cells copied into the new rows (the formatted cells of the copied row times the number of rows) plus the cells of the workbook against `maxCells`, before the rows are built. Insert fewer rows, use `style: 'none'`, or raise `maxCells`.
|
|
113
|
-
- `sharedFormulaText`: `@xlvane/
|
|
113
|
+
- `sharedFormulaText`: `@xlvane/exceljs` `cell.formula` of a `{ sharedFormula }` dependent moves the master's formula once and keeps the result; the text moved per workbook (master text read plus moved text built) is limited to 512 Mi characters, the default `maxSharedStringChars` with which `readWorkbook` expands shared formulas, and for masters longer than 8192 characters (the longest formula Office writes, [MS-OI29500] §2.1.1085 a) to 32 Mi characters; also in `stream.xlsx.WorkbookReader` (per read). `location` names the dependent cell; its cached `cell.result` stays readable.
|
|
114
114
|
|
|
115
|
-
From 1.3.0 (D-K03): `@xlvane/
|
|
115
|
+
From 1.3.0 (D-K03): `@xlvane/exceljs` `xlsx.load` limits merged cells to `max(1 048 576, cells in the file)` (`details.limit` `mergedCells`; each merged position becomes a cell, which a row or column style gives a style, so a few bytes of `mergeCell` could ask for millions of styled cells), and `csv.read` stops at more than 1 048 576 rows (`details.limit` `maxRows`) 16 384 fields in a row (`details.limit` `maxColumns`, with `location.line`) or 5 000 000 fields in all (`details.limit` `maxCells`) while it parses.
|
|
116
116
|
|
|
117
117
|
The MCP server (`@xlvane/mcp`) returns it as a tool error for a file larger than `--max-file-size` (`details.limit` `maxFileBytes`; `convert` to JSON stops building the text at that size), for a workbook with more cells than `--max-cells` (`details.limit` `maxCells`) and for a result longer than `--max-response-chars` (`details.limit` `maxResponseChars`; `read_table` instead returns the rows that fit). `xlvane convert` to JSON returns it when the text would be longer than a JavaScript string can be.
|
|
118
118
|
|
|
@@ -283,12 +283,12 @@ The CSV text given to `fromCSV` has a quoted field that is never closed, text ri
|
|
|
283
283
|
**Fix:** close the quoted field or double the quotes inside it (`""`), or convert the file to UTF-8.
|
|
284
284
|
|
|
285
285
|
### XLV_E_NOT_SUPPORTED
|
|
286
|
-
`@xlvane/
|
|
286
|
+
`@xlvane/exceljs` was asked for an exceljs feature it does not implement, for example a rich-text or hyperlink value, images, tables, conditional formatting, data validation, notes, CSV, protection or `insertRow`. `details.feature` names it. The error is thrown where the feature is used, so nothing is dropped silently.
|
|
287
287
|
`hashPassword` and `verifyPassword` throw it for a hash algorithm other than SHA-1, SHA-256, SHA-384 and SHA-512, and `hashPassword` without a `salt` throws it in a runtime that has no `crypto.getRandomValues` (pass your own random salt there; SR-50, D-C08).
|
|
288
288
|
`editCells` throws it for an array or shared formula in an edit (it writes plain formulas only), and for a cell inside an array formula's range or the master of a shared formula with other cells in its range (D-E02); `details.cell` names it.
|
|
289
289
|
`appendRows` throws it when a table ends with a totals row on the sheet's last used row (the new rows would fall below the totals row; the hint gives the `insertRows` call that grows the table instead), or when growing a table for the new rows would overlap another table (D-R03).
|
|
290
290
|
`insertRows` and `deleteRows` (and `xlvane edit --insert-rows` / `--delete-rows`) also throw it when the sheet has content whose cell references xlvane cannot move yet: tables, charts, shapes and other drawing objects (pictures alone are moved, and deleting rows that would cut a picture is refused), pivot tables, form controls, embedded objects, custom sheet views, threaded comments, extended content such as sparklines or slicers (the conditional formats and data validations of the [MS-XLSX] extension are moved, D-F04), a chart or pivot cache elsewhere that names the sheet (also when the XML escapes the name, such as `R&D`, or quotes it, such as `'O''Brien'!`; pivot cache definitions are found by part name, content type or workbook relationship, D-K04), a drawing, chart or pivot cache relationship whose target is not a part of the package (for example a chart stored under a percent-encoded name; `details.type` and `details.target`), a data table, an array formula the change would split, or a formula or defined name that cannot be adjusted safely (for example a 3-D reference such as `Jan:Mar!A1` that includes the sheet, D-B01). The message names the part or the cell, and `details` gives the element, relationship type or formula.
|
|
291
|
-
**Fix:** for `@xlvane/
|
|
291
|
+
**Fix:** for `@xlvane/exceljs`, see docs/exceljs-compat.md for the supported subset; remove the call, or keep using exceljs for files that need the feature.
|
|
292
292
|
For `insertRows`/`deleteRows`, insert or delete the rows in a spreadsheet application, or remove the named content first.
|
|
293
293
|
|
|
294
294
|
### XLV_E_USAGE
|
package/docs/exceljs-compat.md
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
# exceljs compatibility (`@xlvane/
|
|
1
|
+
# exceljs compatibility (`@xlvane/exceljs`)
|
|
2
2
|
|
|
3
|
-
`@xlvane/
|
|
3
|
+
`@xlvane/exceljs` offers the commonly used part of the exceljs 4.4.0 API on top of xlvane, so that code written for exceljs keeps working after one change in `package.json`:
|
|
4
4
|
|
|
5
5
|
```json
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"exceljs": "npm:@xlvane/
|
|
7
|
+
"exceljs": "npm:@xlvane/exceljs@^1"
|
|
8
8
|
}
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
npm installs an alias `<alias>@npm:<name>` under the alias name in `node_modules` (npm/cli `docs/lib/content/using-npm/package-spec.md`, "Aliases"), so `require('exceljs')` and `import ExcelJS from 'exceljs'` load `@xlvane/
|
|
11
|
+
npm installs an alias `<alias>@npm:<name>` under the alias name in `node_modules` (npm/cli `docs/lib/content/using-npm/package-spec.md`, "Aliases"), so `require('exceljs')` and `import ExcelJS from 'exceljs'` load `@xlvane/exceljs`.
|
|
12
12
|
|
|
13
|
-
- **ESM:** `import ExcelJS from 'exceljs'` works as with exceljs. `@xlvane/
|
|
13
|
+
- **ESM:** `import ExcelJS from 'exceljs'` works as with exceljs. `@xlvane/exceljs` is an ES module, so named imports (`import { Workbook } from 'exceljs'`) work too; exceljs 4.4.0 rejects them because it is a CommonJS package.
|
|
14
14
|
- **CommonJS:** `const ExcelJS = require('exceljs')` needs **Node.js 22.12 or later**. The package is ESM-only and exports the `ExcelJS` object under the name `"module.exports"`, which `require()` of an ES module returns directly from Node.js 22.12 on (Node.js `doc/api/modules.md`, "Loading ECMAScript modules using `require()`"). `engines.node` is `>=22.12`.
|
|
15
15
|
- **Unsupported API** throws an `XlvError` with code `XLV_E_NOT_SUPPORTED`, naming the method (docs/errors.md). Options and settings that are accepted but not handled as exceljs handles them are described with the API they belong to (for example `formatterOptions.objectMode` of `csv.write` has no effect); the [Known differences from the 1.3.0 review](#known-differences-from-the-130-review) lists further differences in values.
|
|
16
16
|
|
|
@@ -153,7 +153,7 @@ Status: **supported** means the same behaviour as exceljs for the cases covered
|
|
|
153
153
|
| Other deep imports (`exceljs/lib/...`) | not supported | Internal files of exceljs; not offered. |
|
|
154
154
|
| `ModelContainer` | not supported | exceljs exports it as a holder of a workbook model with an `xlsx` property (`lib/exceljs.nodejs.js` L3, `lib/doc/modelcontainer.js`). The class is on the module object so that code referring to it loads; constructing it throws `XLV_E_NOT_SUPPORTED`. `xlvane migrate` lists its uses. |
|
|
155
155
|
| `RelationshipType`, `DocumentType`, `ReadingOrder` | supported | The enums of `lib/doc/enums.js`, on the module object and as named exports. |
|
|
156
|
-
| `PaperSize` | supported | exceljs declares it as a `const enum` in index.d.ts (inlined by TypeScript, absent at run time); @xlvane/
|
|
156
|
+
| `PaperSize` | supported | exceljs declares it as a `const enum` in index.d.ts (inlined by TypeScript, absent at run time); @xlvane/exceljs exports it as an object and on the default export. |
|
|
157
157
|
| TypeScript types (`ExcelJS.Worksheet`, `ExcelJS.Fill`, `ExcelJS.stream.xlsx.WorkbookWriterOptions`, …) | supported | The type names of exceljs's index.d.ts are exported and usable through `import * as ExcelJS`, `import ExcelJS from`, and `import ExcelJS = require('exceljs')`, under `moduleResolution` bundler, nodenext (ESM and CommonJS) and `module: commonjs` (`tests/exceljs/types-compat.test.ts`, which type-checks code from the exceljs README). In a CommonJS project TypeScript refuses `import ExcelJS = require(...)` of an ES module under `module: node16` (TS1471, checked with TypeScript 5.9.3); `module: nodenext` and `module: commonjs` accept it. `Buffer` is `Uint8Array`. Enums (`ValueType`, `FormulaType`, `ErrorValue`, `PaperSize`) are also types. `WorkbookStreamReaderOptions` is an alias of `WorkbookReaderOptions`. As in exceljs's declarations, `getTable(name)` returns `Table`, `workbook.getImage(id)` returns `Image`, `getImages()[i].range` is required and `fillFormula`'s `results` is `(row, col) => value`, a flat or a 2-D array (index.d.ts L1327, L1342–1346, L1365, L1780); at run time an unknown table name or image id gives `undefined`, as in exceljs. The module object is frozen: adding or replacing its properties (monkey-patching) has no effect. |
|
|
158
158
|
| Bundling for browsers and Cloudflare Workers | supported | The file helpers of `xlvane/node` are loaded only by `readFile`/`writeFile` and the `filename` forms of the streaming classes, through the package imports `#xlvane-node` and `#node-fs` (package.json `imports`), which resolve to `xlvane/node` and a re-export of `node:fs/promises` under the `node` condition (Node.js, Bun, Deno) and to a module that fails to load elsewhere, so bundlers such as esbuild, vite and wrangler leave out every `node:` import (D-R07); in browsers and Workers these methods throw `XLV_E_NOT_SUPPORTED`. `npm run test:runtimes` bundles the built packages for the browser and runs them in Chromium and workerd. |
|
|
159
159
|
|
|
@@ -168,7 +168,7 @@ A workbook loaded with `xlsx.load()` is written again by `xlsx.writeBuffer()` (`
|
|
|
168
168
|
- Row heights above 409.5 points are read as 409.5; 409.5 itself, which Excel writes, is accepted.
|
|
169
169
|
- A table whose style is a custom style of the file is written without a style name, because xlvane does not write the file's custom table styles; a style name set in code must still be one of the built-in names.
|
|
170
170
|
- Totals-row formulas keep their cached results.
|
|
171
|
-
- Charts are not kept. exceljs 4.4.0 has no chart API (`lib/` mentions charts only in a comment of `lib/xlsx/xform/book/workbook-xform.js` L174–178; docs/facts/charts.md CH-30) and drops the charts of a file it reads and writes again; `@xlvane/
|
|
171
|
+
- Charts are not kept. exceljs 4.4.0 has no chart API (`lib/` mentions charts only in a comment of `lib/xlsx/xform/book/workbook-xform.js` L174–178; docs/facts/charts.md CH-30) and drops the charts of a file it reads and writes again; `@xlvane/exceljs` does the same and offers no chart API. xlvane itself writes charts with `NewSheet.addChart` and reads them as `Sheet.charts`.
|
|
172
172
|
- `activeTab` and `firstSheet` count chart sheets in the file; chart sheets are not loaded, so the indexes are mapped to the worksheet they fall on, or the worksheet before a chart sheet.
|
|
173
173
|
- Row height, visibility and outline level are also read for rows without cells, up to the sheet's `dimension` or its last cell; rows after both are not looked at.
|
|
174
174
|
|
|
@@ -184,13 +184,13 @@ A workbook loaded with `xlsx.load()` is written again by `xlsx.writeBuffer()` (`
|
|
|
184
184
|
|
|
185
185
|
## Known differences found by the cross-check
|
|
186
186
|
|
|
187
|
-
`tests/exceljs/cross-check.test.ts` runs `tests/exceljs/sample-project` against exceljs 4.4.0 and stores its output in `expected-exceljs-4.4.0.json`. `tests/exceljs/alias.test.ts` requires @xlvane/
|
|
187
|
+
`tests/exceljs/cross-check.test.ts` runs `tests/exceljs/sample-project` against exceljs 4.4.0 and stores its output in `expected-exceljs-4.4.0.json`. `tests/exceljs/alias.test.ts` requires @xlvane/exceljs to produce the same output, except for the entries of `KNOWN_DIFFERENCES` in `tests/exceljs/project-helper.ts`, which are listed here:
|
|
188
188
|
|
|
189
189
|
- None so far for what the sample reads back. The sample covers document properties (including `company` and `manager`), rich text, a column style, defined names (including `cell.name`), the built-in date format, a tab colour, a zoomed frozen view external, `mailto:` and `#` links (without tooltips, which exceljs does not read back), gradient fills, a diagonal border, alignment (`textRotation`, `shrinkToFit`, `readingOrder`) and protection, a shared formula from `fillFormula`, outline levels of rows and columns, workbook views, and `insertRow` with style `'i'`, `spliceRows`, `duplicateRow`, `spliceColumns`, `insertRows` and `row.splice` on plain values (no formulas, merges, notes or names, which exceljs does not move); CSV written with the default and with custom options and read back (no formula-like text, no formula result 0, no gap before the first row); `cross-check.test.ts` and `alias.test.ts` also run the documented deep imports (`deep-imports.cjs`); `alias.test.ts` also checks that LibreOffice shows the dates as exceljs's files do (`1/31/2024`).
|
|
190
190
|
|
|
191
191
|
## Known differences from the 1.3.0 review
|
|
192
192
|
|
|
193
|
-
Found by a review of 1.3.0 and checked by running exceljs 4.4.0 and `@xlvane/
|
|
193
|
+
Found by a review of 1.3.0 and checked by running exceljs 4.4.0 and `@xlvane/exceljs` on the same input (Node.js 22.23). F6 describes a difference that xlvane keeps, and F8 values that xlvane refuses. F1, F2, F3, F4, F5, F7, F9, F10 and F12 of that review (merged-cell styles, row styles, the default font, six-digit colours, upper-case date formats, CSV formatter options, `latin1` CSV reading, `column.eachCell`) are fixed in 1.3.1 and described in the tables above, with the differences that remain.
|
|
194
194
|
|
|
195
195
|
- **F6** Dates from 1900-01-01 to 1900-02-28 differ by one day. xlvane writes and reads them with serial 1 = 1900-01-01 (ECMA-376 Part 4 §15.3.4, docs/facts/ecma-376.md E-15); exceljs writes 1900-01-15 as serial 16 and reads serial 15 as 1900-01-14 (`lib/utils/utils.js` L55-61), so here exceljs is the one that is off, and xlvane keeps its reading. From 1900-03-01 on both agree. Serial 60 (the 29 February 1900 that does not exist) and negative serials with a date format read as numbers (exceljs gives 1900-02-28 and dates before 1899-12-30). In a workbook with the 1904 date system a `Date` before 1904-01-01, such as a time-only value given as 1899-12-30 plus the time, throws `XLV_E_INVALID_VALUE` when written; exceljs writes a negative serial (-1461.44... for 1899-12-30T13:20). Time-only values in the 1900 date system and upper-case date formats such as `DD.MM.YYYY` (F6 and F7 of the 1.3.0 review) behave as in exceljs from 1.3.1.
|
|
196
196
|
- **F8** Values exceljs writes without checks (`lib/xlsx/xform/sheet/cell-xform.js` L199-250, `render`) that xlvane refuses with `XLV_E_INVALID_VALUE` when the workbook is written: `NaN` and `Infinity` (exceljs writes `<v>NaN</v>`, `<v>Infinity</v>`), an invalid `Date` (exceljs writes `<v>NaN</v>`), dates before 1900-01-01 or after 9999-12-31 (exceljs writes the serial, for example -18260 for 1850-01-01), text of more than 32 767 characters, text with an unpaired UTF-16 surrogate, and formulas of more than 8 192 characters.
|
|
@@ -2,21 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
xlvane is not affiliated with the ExcelJS project; its name is used only to identify the package.
|
|
4
4
|
|
|
5
|
-
`@xlvane/
|
|
5
|
+
`@xlvane/exceljs` offers the commonly used part of the exceljs 4.4.0 API on top of xlvane. It is installed under the name `exceljs` with an npm alias, so code that imports `exceljs` keeps its imports:
|
|
6
6
|
|
|
7
7
|
```json
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"exceljs": "npm:@xlvane/
|
|
9
|
+
"exceljs": "npm:@xlvane/exceljs@^1"
|
|
10
10
|
}
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
npm installs an alias `<alias>@npm:<name>` under the alias name in `node_modules` (npm/cli `docs/lib/content/using-npm/package-spec.md`, "Aliases"; docs/exceljs-compat.md), so `import ExcelJS from 'exceljs'` and `require('exceljs')` load `@xlvane/
|
|
13
|
+
npm installs an alias `<alias>@npm:<name>` under the alias name in `node_modules` (npm/cli `docs/lib/content/using-npm/package-spec.md`, "Aliases"; docs/exceljs-compat.md), so `import ExcelJS from 'exceljs'` and `require('exceljs')` load `@xlvane/exceljs`. What is supported, partly supported and not supported is listed method by method in [docs/exceljs-compat.md](https://github.com/DevXord/xlvane/blob/main/docs/exceljs-compat.md) (also in `node_modules/xlvane/docs/exceljs-compat.md` after installing xlvane).
|
|
14
14
|
|
|
15
15
|
This guide uses the `xlvane migrate` command of the `xlvane` package. The `xlvane` commands, the report shown below and the TypeScript examples are checked by the tests in `tests/docs/`; the npm commands were run with npm 10.9.9 on 2026-11-03.
|
|
16
16
|
|
|
17
17
|
## Before you start
|
|
18
18
|
|
|
19
|
-
- **Node.js.** `@xlvane/
|
|
19
|
+
- **Node.js.** `@xlvane/exceljs` is an ES module and declares `engines.node` `>=22.12`. `require('exceljs')` of an ES module works without a flag from Node.js 22.12 (docs/exceljs-compat.md); `import` works too, and so do named imports such as `import { Workbook } from 'exceljs'`.
|
|
20
20
|
- **Version control.** Commit `package.json` and the lockfile first, so the change can be reviewed and undone.
|
|
21
21
|
|
|
22
22
|
## 1. See what would change
|
|
@@ -30,9 +30,9 @@ npx xlvane migrate
|
|
|
30
30
|
`xlvane migrate` does the following, and nothing else:
|
|
31
31
|
|
|
32
32
|
1. It reads `package.json` of the project directory (the current directory, or the directory given as the first argument). A `package.json` that is a symbolic link is refused.
|
|
33
|
-
2. It looks for an `"exceljs"` entry in `dependencies`, `devDependencies`, `optionalDependencies` and `peerDependencies`, and shows how each would change to `"npm:@xlvane/
|
|
33
|
+
2. It looks for an `"exceljs"` entry in `dependencies`, `devDependencies`, `optionalDependencies` and `peerDependencies`, and shows how each would change to `"npm:@xlvane/exceljs@^1"`. Other sections, such as `overrides`, are not changed.
|
|
34
34
|
3. It prints the Node.js requirement of `require('exceljs')` next to the project's own `engines.node`.
|
|
35
|
-
4. It scans the source files of the project (`.js`, `.mjs`, `.cjs`, `.jsx`, `.ts`, `.mts`, `.cts`, `.tsx`, up to 2 MiB each and 10 000 files) for exceljs API that `@xlvane/
|
|
35
|
+
4. It scans the source files of the project (`.js`, `.mjs`, `.cjs`, `.jsx`, `.ts`, `.mts`, `.cts`, `.tsx`, up to 2 MiB each and 10 000 files) for exceljs API that `@xlvane/exceljs` does not support: `ModelContainer` and deep imports of `exceljs/lib/...`. Only files that contain the text `exceljs` are checked; `node_modules`, folders whose names start with a dot, and symbolic links are skipped. The matching is textual, so a finding is a place to look at, not proof.
|
|
36
36
|
5. It writes nothing unless `--force` is given.
|
|
37
37
|
|
|
38
38
|
For a project whose `package.json` has `"exceljs": "^4.4.0"` in `dependencies`, with a file `src/report.js` that imports `exceljs` and a file `src/legacy.cjs` that requires `exceljs/lib/xlsx/xform/base-xform`, the report is:
|
|
@@ -40,10 +40,10 @@ For a project whose `package.json` has `"exceljs": "^4.4.0"` in `dependencies`,
|
|
|
40
40
|
```text
|
|
41
41
|
Change in package.json:
|
|
42
42
|
dependencies: - "exceljs": "^4.4.0"
|
|
43
|
-
+ "exceljs": "npm:@xlvane/
|
|
44
|
-
Node.js: require('exceljs') of @xlvane/
|
|
43
|
+
+ "exceljs": "npm:@xlvane/exceljs@^1"
|
|
44
|
+
Node.js: require('exceljs') of @xlvane/exceljs needs Node.js 22.12 or later (package.json engines.node: not set).
|
|
45
45
|
|
|
46
|
-
Scanned 2 source files for exceljs API that @xlvane/
|
|
46
|
+
Scanned 2 source files for exceljs API that @xlvane/exceljs does not fully support:
|
|
47
47
|
not supported src/legacy.cjs:1:27 deep import (exceljs/lib/...)
|
|
48
48
|
Details: docs/exceljs-compat.md. Unsupported calls throw XLV_E_NOT_SUPPORTED at run time.
|
|
49
49
|
|
|
@@ -61,18 +61,18 @@ npx xlvane migrate --json
|
|
|
61
61
|
```sh
|
|
62
62
|
npx xlvane migrate --force --dry-run # show the change without writing it
|
|
63
63
|
npx xlvane migrate --force # change package.json
|
|
64
|
-
npm install # install @xlvane/
|
|
64
|
+
npm install # install @xlvane/exceljs under the name exceljs
|
|
65
65
|
```
|
|
66
66
|
|
|
67
67
|
`--force` replaces only the value of each `"exceljs"` entry; the rest of `package.json` keeps its formatting and key order. Instead of `xlvane migrate`, the alias can also be installed directly:
|
|
68
68
|
|
|
69
69
|
```sh
|
|
70
|
-
npm install exceljs@npm:@xlvane/
|
|
70
|
+
npm install exceljs@npm:@xlvane/exceljs@^1
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
npm then saves the version it installed as the range (with npm 10.9.9 and `@xlvane/
|
|
73
|
+
npm then saves the version it installed as the range (with npm 10.9.9 and `@xlvane/exceljs` 1.2.2: `"exceljs": "npm:@xlvane/exceljs@^1.2.2"`).
|
|
74
74
|
|
|
75
|
-
The code stays as it was. For example, this exceljs code runs unchanged on `@xlvane/
|
|
75
|
+
The code stays as it was. For example, this exceljs code runs unchanged on `@xlvane/exceljs`:
|
|
76
76
|
|
|
77
77
|
```ts
|
|
78
78
|
import ExcelJS from 'exceljs';
|
|
@@ -97,7 +97,7 @@ In CommonJS, `const ExcelJS = require('exceljs');` gives the same object.
|
|
|
97
97
|
|
|
98
98
|
- **Run the project's tests.** Unsupported API throws an `XlvError` whose `code` is `XLV_E_NOT_SUPPORTED` and whose message names the method; nothing is dropped silently.
|
|
99
99
|
- **Look at each finding of `xlvane migrate`.** Deep imports of `exceljs/lib/...` do not resolve (`exceljs/dist/es5` and the `exceljs/dist/exceljs*.js` files do); `ModelContainer` throws `XLV_E_NOT_SUPPORTED` when it is constructed.
|
|
100
|
-
- **Read the differences.** [docs/exceljs-compat.md](https://github.com/DevXord/xlvane/blob/main/docs/exceljs-compat.md) lists every method with its status and the exceljs source of each behaviour, and ends with the differences found in reviews and cross-checks. The ones most likely to matter are summarised in the [@xlvane/
|
|
100
|
+
- **Read the differences.** [docs/exceljs-compat.md](https://github.com/DevXord/xlvane/blob/main/docs/exceljs-compat.md) lists every method with its status and the exceljs source of each behaviour, and ends with the differences found in reviews and cross-checks. The ones most likely to matter are summarised in the [@xlvane/exceljs README](https://github.com/DevXord/xlvane/blob/main/packages/exceljs/README.md#differences-from-exceljs): CSV output escapes text that starts like a formula (`formulaInjection: "off"` writes it unchanged, as exceljs does), a sheet id outside 1 to 65534 is written as the lowest unused id, only the first view of a worksheet is written, the module object is frozen, the streaming writer compresses in JavaScript, and input files are checked against ZIP and XML limits.
|
|
101
101
|
- **TypeScript.** The type names of exceljs's `index.d.ts` are exported and work with `moduleResolution` `bundler` and `nodenext` and with `module: commonjs`. Under `module: node16`, TypeScript refuses `import ExcelJS = require('exceljs')` of an ES module (TS1471); use `nodenext` or `commonjs`.
|
|
102
102
|
- **Browsers and Workers.** The methods that read or write files (`xlsx.readFile`, `xlsx.writeFile`, `csv.readFile`, `csv.writeFile`, the `filename` forms of the streaming classes and of `addImage`) work in Node.js, Bun and Deno; in browsers and Workers they throw `XLV_E_NOT_SUPPORTED`.
|
|
103
103
|
|
|
@@ -111,7 +111,7 @@ try {
|
|
|
111
111
|
await workbook.xlsx.readFile('report.xlsx');
|
|
112
112
|
} catch (error) {
|
|
113
113
|
const code = (error as { code?: unknown }).code;
|
|
114
|
-
if (code === 'XLV_E_NOT_SUPPORTED') console.error('Not supported by @xlvane/
|
|
114
|
+
if (code === 'XLV_E_NOT_SUPPORTED') console.error('Not supported by @xlvane/exceljs:', (error as Error).message);
|
|
115
115
|
else throw error;
|
|
116
116
|
}
|
|
117
117
|
```
|
|
@@ -128,4 +128,4 @@ npm replaces the alias in `package.json` and `node_modules`. Restoring `package.
|
|
|
128
128
|
|
|
129
129
|
## Reporting a problem
|
|
130
130
|
|
|
131
|
-
When exceljs code behaves differently on `@xlvane/
|
|
131
|
+
When exceljs code behaves differently on `@xlvane/exceljs` and the difference is not listed in docs/exceljs-compat.md, please open an issue at https://github.com/DevXord/xlvane/issues with a small script that shows it.
|
package/llms-full.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# xlvane 1.3.
|
|
1
|
+
# xlvane 1.3.3: documentation in one file
|
|
2
2
|
|
|
3
3
|
This file joins the README of the xlvane package, the Agent Skill and the documentation in docs/. It is generated by scripts/package-docs.mjs; the separate files are in the same package.
|
|
4
4
|
|
|
@@ -37,11 +37,11 @@ From a shell: `npx xlvane inspect orders.xlsx`, then `npx xlvane read orders.xls
|
|
|
37
37
|
- [Large files: streaming](#large-files-streaming)
|
|
38
38
|
- [Inspecting a workbook](#inspecting-a-workbook) · [Errors and warnings](#errors-and-warnings) · [Untrusted input and limits](#untrusted-input-and-limits)
|
|
39
39
|
- [Limitations](#limitations) · [Package size](#package-size) · [Links](#links)
|
|
40
|
-
- exceljs users: [`@xlvane/
|
|
40
|
+
- exceljs users: [`@xlvane/exceljs`](https://www.npmjs.com/package/@xlvane/exceljs) and `xlvane migrate`
|
|
41
41
|
|
|
42
42
|
## Tested environments
|
|
43
43
|
|
|
44
|
-
The core API (reading, writing, inspect, tables, CSV, editing, diff, streaming with Web Streams) and `@xlvane/
|
|
44
|
+
The core API (reading, writing, inspect, tables, CSV, editing, diff, streaming with Web Streams) and `@xlvane/exceljs` are tested in Node.js 22, 24 and 26, Bun, Deno, Chromium (Playwright) and the Cloudflare Workers runtime (workerd), with the same test bundle (`npm run test:runtimes`). In Deno, import from `npm:xlvane`; in browsers and Workers, through a bundler such as Vite, esbuild or webpack. `xlvane/node` and the command line need Node.js. Reading is tested on 340 files of the Apache POI test corpus (written by Excel for Windows, Mac and the web, LibreOffice, ONLYOFFICE and others, and damaged files) and on files saved by LibreOffice; see `tests/corpus/`.
|
|
45
45
|
|
|
46
46
|
## Command line in 5 minutes
|
|
47
47
|
|
|
@@ -64,7 +64,7 @@ xlvane help edit # usage and examples of one command
|
|
|
64
64
|
- `--json` prints one JSON document per command with a documented schema ([docs/cli-json.md](https://github.com/DevXord/xlvane/blob/main/docs/cli-json.md)). Exit codes: 0 success, 1 a check found something (`diff`, `validate`), 2 usage error, 3 input or file error.
|
|
65
65
|
- Colour (red errors, yellow warnings, green results, bold headings) is used only on a terminal and never carries information alone; `NO_COLOR` or `TERM=dumb` turn it off, `FORCE_COLOR=1` turns it on. Control characters from files, such as an escape character in a cell, are shown as `\x1b` and never reach the terminal.
|
|
66
66
|
- Tables and summaries go to separate streams: `xlvane read report.xlsx > out.txt` writes only the table; the row count and warnings notes go to stderr.
|
|
67
|
-
- `xlvane migrate` prepares a project for `@xlvane/
|
|
67
|
+
- `xlvane migrate` prepares a project for `@xlvane/exceljs`, and `xlvane mcp` starts the MCP server from `@xlvane/mcp` (a separate package; [its README](https://github.com/DevXord/xlvane/blob/main/packages/mcp/README.md)).
|
|
68
68
|
|
|
69
69
|
## Reading a workbook
|
|
70
70
|
|
|
@@ -639,7 +639,7 @@ Formulas on every sheet, merged cells, links, notes, conditional formats (also e
|
|
|
639
639
|
|
|
640
640
|
In Node.js, `xlvane/node` adds `readWorkbookFile`, `inspectFile` and `writeWorkbookFile` (which never replaces an existing file unless `{ overwrite: true }` is passed). `toCSV`, `fromCSV`, `toJSON` and `fromJSON` convert tables. For very large files use `openWorkbookStream` and `writeWorkbookStream`.
|
|
641
641
|
|
|
642
|
-
Code written for the `exceljs` API can run on xlvane through `@xlvane/
|
|
642
|
+
Code written for the `exceljs` API can run on xlvane through `@xlvane/exceljs` (`"exceljs": "npm:@xlvane/exceljs@^1"` in package.json); unsupported exceljs features throw `XLV_E_NOT_SUPPORTED`.
|
|
643
643
|
|
|
644
644
|
## Command line
|
|
645
645
|
|
|
@@ -697,7 +697,7 @@ Each code links to its section, which says what to do. The CLI prints the code a
|
|
|
697
697
|
| --- | --- |
|
|
698
698
|
| [`XLV_E_INVALID_INPUT`](#xlv_e_invalid_input) | The input is not what the function expects: `readWorkbook` and `inspect` accept a `Uint8Array`, an `ArrayBuffer` (or another typed-array … |
|
|
699
699
|
| [`XLV_E_INVALID_OPTION`](#xlv_e_invalid_option) | An option is unknown, has the wrong type or is out of range. |
|
|
700
|
-
| [`XLV_E_INVALID_ARGUMENT`](#xlv_e_invalid_argument) | An argument would lose or move data: a method of `@xlvane/
|
|
700
|
+
| [`XLV_E_INVALID_ARGUMENT`](#xlv_e_invalid_argument) | An argument would lose or move data: a method of `@xlvane/exceljs` where exceljs 4.4.0 accepts it silently, or `appendRows` with array rows when the starting column is ambiguous. |
|
|
701
701
|
| [`XLV_E_LIMIT_EXCEEDED`](#xlv_e_limit_exceeded) | The file exceeds one of the resource limits (`ReadLimits`): input size, number of ZIP entries, decompressed size of one entry or of all … |
|
|
702
702
|
| [`XLV_E_NOT_ZIP`](#xlv_e_not_zip) | The input is not a ZIP archive, so it cannot be an XLSX file. |
|
|
703
703
|
| [`XLV_E_UNSUPPORTED_CONTAINER`](#xlv_e_unsupported_container) | The input is a Compound File Binary container (signature `D0 CF 11 E0 A1 B1 1A E1`). |
|
|
@@ -731,7 +731,7 @@ Each code links to its section, which says what to do. The CLI prints the code a
|
|
|
731
731
|
| [`XLV_E_INVALID_ROWS`](#xlv_e_invalid_rows) | Rows given to `writeTable`, `fromJSON` or `appendRows` have the wrong shape: not an array, rows mixing objects and arrays, a value that … |
|
|
732
732
|
| [`XLV_E_JSON_INVALID`](#xlv_e_json_invalid) | The text given to `fromJSON` is not valid JSON. |
|
|
733
733
|
| [`XLV_E_CSV_MALFORMED`](#xlv_e_csv_malformed) | The CSV text given to `fromCSV` has a quoted field that is never closed, text right after a closing quote, or bytes that are not valid … |
|
|
734
|
-
| [`XLV_E_NOT_SUPPORTED`](#xlv_e_not_supported) | `@xlvane/
|
|
734
|
+
| [`XLV_E_NOT_SUPPORTED`](#xlv_e_not_supported) | `@xlvane/exceljs` was asked for an exceljs feature it does not implement, for example a rich-text or hyperlink value, images, tables, … |
|
|
735
735
|
| [`XLV_E_USAGE`](#xlv_e_usage) | The `xlvane` command line was used incorrectly: an unknown command or option, a missing or extra argument, an option without its value, … |
|
|
736
736
|
| [`XLV_E_INTERNAL`](#xlv_e_internal) | The `xlvane` command line caught an error that is not an `XlvError`. |
|
|
737
737
|
| [`XLV_E_NOT_INSTALLED`](#xlv_e_not_installed) | `xlvane mcp` needs the separate package `@xlvane/mcp`, which could not be loaded. |
|
|
@@ -772,7 +772,7 @@ The settings of a note box (`box` of a note: `margins` in millimetres from 0 to
|
|
|
772
772
|
**Fix:** correct the option name or value.
|
|
773
773
|
|
|
774
774
|
### XLV_E_INVALID_ARGUMENT
|
|
775
|
-
An argument of a method of `@xlvane/
|
|
775
|
+
An argument of a method of `@xlvane/exceljs` is not valid, in a case where exceljs 4.4.0 accepts it and loses or moves data without an error: for example `insertRow(0, …)`, a row position given as a string, a negative count in `spliceRows` or `spliceColumns`, an outline level outside 0–7 set on a row or column (exceljs writes it), `duplicateRow` of a row that does not exist, `insertRows` without an array of values, or rows or columns pushed beyond the sheet (row 1048576, column XFD). `details.method`, `details.argument` and `details.value` name the method, the argument and its value (docs/exceljs-compat.md).
|
|
776
776
|
`appendRows` throws it for array rows when tables that start in different columns reach the sheet's last used row, so the column where the rows start is ambiguous (D-K04); `details.tables` names the tables and `details.row` the row. Pass object rows keyed by header text.
|
|
777
777
|
**Fix:** pass a whole number in the range the hint gives (rows from 1, columns from 1), or remove rows at the end of the sheet before inserting.
|
|
778
778
|
|
|
@@ -781,21 +781,21 @@ The file exceeds one of the resource limits (`ReadLimits`): input size, number o
|
|
|
781
781
|
|
|
782
782
|
Some limits also bound work derived from a small file (1.1.1, D-H01):
|
|
783
783
|
|
|
784
|
-
- `maxCells` (`details.limit` `maxCells`, `details.value` the budget): `toCSV`, `readTable`, `toJSON`, `readTableStream`, `xlvane read` and `xlvane convert` write at most `max(maxCells, 16 × cells read)` positions (rows × columns of the output), so a few cells far apart cannot make them produce a value for every position between; `@xlvane/
|
|
784
|
+
- `maxCells` (`details.limit` `maxCells`, `details.value` the budget): `toCSV`, `readTable`, `toJSON`, `readTableStream`, `xlvane read` and `xlvane convert` write at most `max(maxCells, 16 × cells read)` positions (rows × columns of the output), so a few cells far apart cannot make them produce a value for every position between; `@xlvane/exceljs`'s `xlsx.load` creates at most as many cells for merged ranges, tables and column definitions, and looks up at most 64 Mi rows (or 16 per cell read) for row settings up to the sheets' dimensions. Pass a smaller `range`, or raise `maxCells` for a trusted file.
|
|
785
785
|
- `maxXmlTextLength`: also the length of an XML comment or processing instruction.
|
|
786
786
|
- `maxSharedStringChars`: also the text of shared formulas, counted apart from shared strings: the length of each sharing cell's formula, as moved to that cell. From 1.2.3 (D-J01) also the header names that `readTable`, `toJSON` and `readTableStream` repeat in every row object: the sum of the key lengths times the number of rows (a long header over many rows would otherwise make JSON text far larger than the file); `readTableStream` counts one row at a time.
|
|
787
787
|
|
|
788
788
|
From 1.2.3 (D-J01):
|
|
789
789
|
|
|
790
|
-
- `maxCells`: `fromCSV`, `fromJSON` and `writeTable` write at most `max(maxCells, 16 × cells written)` positions (rows × columns), so one very wide row followed by many short ones cannot make them visit every position; each takes a `maxCells` option (default 5 000 000). While streaming, one `<row>` element may hold at most 16 384 cells (`details.value` 16384), the most a row can have, because its cells are held until the element ends. `@xlvane/
|
|
790
|
+
- `maxCells`: `fromCSV`, `fromJSON` and `writeTable` write at most `max(maxCells, 16 × cells written)` positions (rows × columns), so one very wide row followed by many short ones cannot make them visit every position; each takes a `maxCells` option (default 5 000 000). While streaming, one `<row>` element may hold at most 16 384 cells (`details.value` 16384), the most a row can have, because its cells are held until the element ends. `@xlvane/exceljs` `xlsx.load` also counts the cells of defined names against its budget, and its `xlsx.read`, `csv.read` and `stream.xlsx.WorkbookReader` stop collecting a stream after `maxInputBytes` (256 MiB; `details.limit` `maxInputBytes`).
|
|
791
791
|
|
|
792
792
|
From 1.3.0 (D-K04):
|
|
793
793
|
|
|
794
794
|
- `maxCells`: `editCells` and `appendRows` check, before building any cell, that the cells of the workbook (with a value or only a style) plus the new cells stay within `maxCells`, so the result can be read with the same limits, and they write at most 1 000 000 cells per call unless `limits.maxCells` is given, then at most `maxCells` (`details.limit` `maxCells`, `details.value` the limit). Each cell written takes about 0.5 KB of memory while the file is rebuilt; split the edits into several calls, or pass a larger `maxCells` if there is enough memory.
|
|
795
795
|
- `maxCells`: `insertRows` with `style: 'above'` or `'below'` (and `xlvane edit --insert-rows` with a style) counts the formatted cells copied into the new rows (the formatted cells of the copied row times the number of rows) plus the cells of the workbook against `maxCells`, before the rows are built. Insert fewer rows, use `style: 'none'`, or raise `maxCells`.
|
|
796
|
-
- `sharedFormulaText`: `@xlvane/
|
|
796
|
+
- `sharedFormulaText`: `@xlvane/exceljs` `cell.formula` of a `{ sharedFormula }` dependent moves the master's formula once and keeps the result; the text moved per workbook (master text read plus moved text built) is limited to 512 Mi characters, the default `maxSharedStringChars` with which `readWorkbook` expands shared formulas, and for masters longer than 8192 characters (the longest formula Office writes, [MS-OI29500] §2.1.1085 a) to 32 Mi characters; also in `stream.xlsx.WorkbookReader` (per read). `location` names the dependent cell; its cached `cell.result` stays readable.
|
|
797
797
|
|
|
798
|
-
From 1.3.0 (D-K03): `@xlvane/
|
|
798
|
+
From 1.3.0 (D-K03): `@xlvane/exceljs` `xlsx.load` limits merged cells to `max(1 048 576, cells in the file)` (`details.limit` `mergedCells`; each merged position becomes a cell, which a row or column style gives a style, so a few bytes of `mergeCell` could ask for millions of styled cells), and `csv.read` stops at more than 1 048 576 rows (`details.limit` `maxRows`) 16 384 fields in a row (`details.limit` `maxColumns`, with `location.line`) or 5 000 000 fields in all (`details.limit` `maxCells`) while it parses.
|
|
799
799
|
|
|
800
800
|
The MCP server (`@xlvane/mcp`) returns it as a tool error for a file larger than `--max-file-size` (`details.limit` `maxFileBytes`; `convert` to JSON stops building the text at that size), for a workbook with more cells than `--max-cells` (`details.limit` `maxCells`) and for a result longer than `--max-response-chars` (`details.limit` `maxResponseChars`; `read_table` instead returns the rows that fit). `xlvane convert` to JSON returns it when the text would be longer than a JavaScript string can be.
|
|
801
801
|
|
|
@@ -966,12 +966,12 @@ The CSV text given to `fromCSV` has a quoted field that is never closed, text ri
|
|
|
966
966
|
**Fix:** close the quoted field or double the quotes inside it (`""`), or convert the file to UTF-8.
|
|
967
967
|
|
|
968
968
|
### XLV_E_NOT_SUPPORTED
|
|
969
|
-
`@xlvane/
|
|
969
|
+
`@xlvane/exceljs` was asked for an exceljs feature it does not implement, for example a rich-text or hyperlink value, images, tables, conditional formatting, data validation, notes, CSV, protection or `insertRow`. `details.feature` names it. The error is thrown where the feature is used, so nothing is dropped silently.
|
|
970
970
|
`hashPassword` and `verifyPassword` throw it for a hash algorithm other than SHA-1, SHA-256, SHA-384 and SHA-512, and `hashPassword` without a `salt` throws it in a runtime that has no `crypto.getRandomValues` (pass your own random salt there; SR-50, D-C08).
|
|
971
971
|
`editCells` throws it for an array or shared formula in an edit (it writes plain formulas only), and for a cell inside an array formula's range or the master of a shared formula with other cells in its range (D-E02); `details.cell` names it.
|
|
972
972
|
`appendRows` throws it when a table ends with a totals row on the sheet's last used row (the new rows would fall below the totals row; the hint gives the `insertRows` call that grows the table instead), or when growing a table for the new rows would overlap another table (D-R03).
|
|
973
973
|
`insertRows` and `deleteRows` (and `xlvane edit --insert-rows` / `--delete-rows`) also throw it when the sheet has content whose cell references xlvane cannot move yet: tables, charts, shapes and other drawing objects (pictures alone are moved, and deleting rows that would cut a picture is refused), pivot tables, form controls, embedded objects, custom sheet views, threaded comments, extended content such as sparklines or slicers (the conditional formats and data validations of the [MS-XLSX] extension are moved, D-F04), a chart or pivot cache elsewhere that names the sheet (also when the XML escapes the name, such as `R&D`, or quotes it, such as `'O''Brien'!`; pivot cache definitions are found by part name, content type or workbook relationship, D-K04), a drawing, chart or pivot cache relationship whose target is not a part of the package (for example a chart stored under a percent-encoded name; `details.type` and `details.target`), a data table, an array formula the change would split, or a formula or defined name that cannot be adjusted safely (for example a 3-D reference such as `Jan:Mar!A1` that includes the sheet, D-B01). The message names the part or the cell, and `details` gives the element, relationship type or formula.
|
|
974
|
-
**Fix:** for `@xlvane/
|
|
974
|
+
**Fix:** for `@xlvane/exceljs`, see docs/exceljs-compat.md for the supported subset; remove the call, or keep using exceljs for files that need the feature.
|
|
975
975
|
For `insertRows`/`deleteRows`, insert or delete the rows in a spreadsheet application, or remove the named content first.
|
|
976
976
|
|
|
977
977
|
### XLV_E_USAGE
|
|
@@ -1307,19 +1307,19 @@ The error envelope is defined in [cli-json/common.schema.json](cli-json/common.s
|
|
|
1307
1307
|
|
|
1308
1308
|
<!-- file: docs/exceljs-compat.md -->
|
|
1309
1309
|
|
|
1310
|
-
# exceljs compatibility (`@xlvane/
|
|
1310
|
+
# exceljs compatibility (`@xlvane/exceljs`)
|
|
1311
1311
|
|
|
1312
|
-
`@xlvane/
|
|
1312
|
+
`@xlvane/exceljs` offers the commonly used part of the exceljs 4.4.0 API on top of xlvane, so that code written for exceljs keeps working after one change in `package.json`:
|
|
1313
1313
|
|
|
1314
1314
|
```json
|
|
1315
1315
|
"dependencies": {
|
|
1316
|
-
"exceljs": "npm:@xlvane/
|
|
1316
|
+
"exceljs": "npm:@xlvane/exceljs@^1"
|
|
1317
1317
|
}
|
|
1318
1318
|
```
|
|
1319
1319
|
|
|
1320
|
-
npm installs an alias `<alias>@npm:<name>` under the alias name in `node_modules` (npm/cli `docs/lib/content/using-npm/package-spec.md`, "Aliases"), so `require('exceljs')` and `import ExcelJS from 'exceljs'` load `@xlvane/
|
|
1320
|
+
npm installs an alias `<alias>@npm:<name>` under the alias name in `node_modules` (npm/cli `docs/lib/content/using-npm/package-spec.md`, "Aliases"), so `require('exceljs')` and `import ExcelJS from 'exceljs'` load `@xlvane/exceljs`.
|
|
1321
1321
|
|
|
1322
|
-
- **ESM:** `import ExcelJS from 'exceljs'` works as with exceljs. `@xlvane/
|
|
1322
|
+
- **ESM:** `import ExcelJS from 'exceljs'` works as with exceljs. `@xlvane/exceljs` is an ES module, so named imports (`import { Workbook } from 'exceljs'`) work too; exceljs 4.4.0 rejects them because it is a CommonJS package.
|
|
1323
1323
|
- **CommonJS:** `const ExcelJS = require('exceljs')` needs **Node.js 22.12 or later**. The package is ESM-only and exports the `ExcelJS` object under the name `"module.exports"`, which `require()` of an ES module returns directly from Node.js 22.12 on (Node.js `doc/api/modules.md`, "Loading ECMAScript modules using `require()`"). `engines.node` is `>=22.12`.
|
|
1324
1324
|
- **Unsupported API** throws an `XlvError` with code `XLV_E_NOT_SUPPORTED`, naming the method (docs/errors.md). Options and settings that are accepted but not handled as exceljs handles them are described with the API they belong to (for example `formatterOptions.objectMode` of `csv.write` has no effect); the [Known differences from the 1.3.0 review](#known-differences-from-the-130-review) lists further differences in values.
|
|
1325
1325
|
|
|
@@ -1462,7 +1462,7 @@ Status: **supported** means the same behaviour as exceljs for the cases covered
|
|
|
1462
1462
|
| Other deep imports (`exceljs/lib/...`) | not supported | Internal files of exceljs; not offered. |
|
|
1463
1463
|
| `ModelContainer` | not supported | exceljs exports it as a holder of a workbook model with an `xlsx` property (`lib/exceljs.nodejs.js` L3, `lib/doc/modelcontainer.js`). The class is on the module object so that code referring to it loads; constructing it throws `XLV_E_NOT_SUPPORTED`. `xlvane migrate` lists its uses. |
|
|
1464
1464
|
| `RelationshipType`, `DocumentType`, `ReadingOrder` | supported | The enums of `lib/doc/enums.js`, on the module object and as named exports. |
|
|
1465
|
-
| `PaperSize` | supported | exceljs declares it as a `const enum` in index.d.ts (inlined by TypeScript, absent at run time); @xlvane/
|
|
1465
|
+
| `PaperSize` | supported | exceljs declares it as a `const enum` in index.d.ts (inlined by TypeScript, absent at run time); @xlvane/exceljs exports it as an object and on the default export. |
|
|
1466
1466
|
| TypeScript types (`ExcelJS.Worksheet`, `ExcelJS.Fill`, `ExcelJS.stream.xlsx.WorkbookWriterOptions`, …) | supported | The type names of exceljs's index.d.ts are exported and usable through `import * as ExcelJS`, `import ExcelJS from`, and `import ExcelJS = require('exceljs')`, under `moduleResolution` bundler, nodenext (ESM and CommonJS) and `module: commonjs` (`tests/exceljs/types-compat.test.ts`, which type-checks code from the exceljs README). In a CommonJS project TypeScript refuses `import ExcelJS = require(...)` of an ES module under `module: node16` (TS1471, checked with TypeScript 5.9.3); `module: nodenext` and `module: commonjs` accept it. `Buffer` is `Uint8Array`. Enums (`ValueType`, `FormulaType`, `ErrorValue`, `PaperSize`) are also types. `WorkbookStreamReaderOptions` is an alias of `WorkbookReaderOptions`. As in exceljs's declarations, `getTable(name)` returns `Table`, `workbook.getImage(id)` returns `Image`, `getImages()[i].range` is required and `fillFormula`'s `results` is `(row, col) => value`, a flat or a 2-D array (index.d.ts L1327, L1342–1346, L1365, L1780); at run time an unknown table name or image id gives `undefined`, as in exceljs. The module object is frozen: adding or replacing its properties (monkey-patching) has no effect. |
|
|
1467
1467
|
| Bundling for browsers and Cloudflare Workers | supported | The file helpers of `xlvane/node` are loaded only by `readFile`/`writeFile` and the `filename` forms of the streaming classes, through the package imports `#xlvane-node` and `#node-fs` (package.json `imports`), which resolve to `xlvane/node` and a re-export of `node:fs/promises` under the `node` condition (Node.js, Bun, Deno) and to a module that fails to load elsewhere, so bundlers such as esbuild, vite and wrangler leave out every `node:` import (D-R07); in browsers and Workers these methods throw `XLV_E_NOT_SUPPORTED`. `npm run test:runtimes` bundles the built packages for the browser and runs them in Chromium and workerd. |
|
|
1468
1468
|
|
|
@@ -1477,7 +1477,7 @@ A workbook loaded with `xlsx.load()` is written again by `xlsx.writeBuffer()` (`
|
|
|
1477
1477
|
- Row heights above 409.5 points are read as 409.5; 409.5 itself, which Excel writes, is accepted.
|
|
1478
1478
|
- A table whose style is a custom style of the file is written without a style name, because xlvane does not write the file's custom table styles; a style name set in code must still be one of the built-in names.
|
|
1479
1479
|
- Totals-row formulas keep their cached results.
|
|
1480
|
-
- Charts are not kept. exceljs 4.4.0 has no chart API (`lib/` mentions charts only in a comment of `lib/xlsx/xform/book/workbook-xform.js` L174–178; docs/facts/charts.md CH-30) and drops the charts of a file it reads and writes again; `@xlvane/
|
|
1480
|
+
- Charts are not kept. exceljs 4.4.0 has no chart API (`lib/` mentions charts only in a comment of `lib/xlsx/xform/book/workbook-xform.js` L174–178; docs/facts/charts.md CH-30) and drops the charts of a file it reads and writes again; `@xlvane/exceljs` does the same and offers no chart API. xlvane itself writes charts with `NewSheet.addChart` and reads them as `Sheet.charts`.
|
|
1481
1481
|
- `activeTab` and `firstSheet` count chart sheets in the file; chart sheets are not loaded, so the indexes are mapped to the worksheet they fall on, or the worksheet before a chart sheet.
|
|
1482
1482
|
- Row height, visibility and outline level are also read for rows without cells, up to the sheet's `dimension` or its last cell; rows after both are not looked at.
|
|
1483
1483
|
|
|
@@ -1493,13 +1493,13 @@ A workbook loaded with `xlsx.load()` is written again by `xlsx.writeBuffer()` (`
|
|
|
1493
1493
|
|
|
1494
1494
|
## Known differences found by the cross-check
|
|
1495
1495
|
|
|
1496
|
-
`tests/exceljs/cross-check.test.ts` runs `tests/exceljs/sample-project` against exceljs 4.4.0 and stores its output in `expected-exceljs-4.4.0.json`. `tests/exceljs/alias.test.ts` requires @xlvane/
|
|
1496
|
+
`tests/exceljs/cross-check.test.ts` runs `tests/exceljs/sample-project` against exceljs 4.4.0 and stores its output in `expected-exceljs-4.4.0.json`. `tests/exceljs/alias.test.ts` requires @xlvane/exceljs to produce the same output, except for the entries of `KNOWN_DIFFERENCES` in `tests/exceljs/project-helper.ts`, which are listed here:
|
|
1497
1497
|
|
|
1498
1498
|
- None so far for what the sample reads back. The sample covers document properties (including `company` and `manager`), rich text, a column style, defined names (including `cell.name`), the built-in date format, a tab colour, a zoomed frozen view external, `mailto:` and `#` links (without tooltips, which exceljs does not read back), gradient fills, a diagonal border, alignment (`textRotation`, `shrinkToFit`, `readingOrder`) and protection, a shared formula from `fillFormula`, outline levels of rows and columns, workbook views, and `insertRow` with style `'i'`, `spliceRows`, `duplicateRow`, `spliceColumns`, `insertRows` and `row.splice` on plain values (no formulas, merges, notes or names, which exceljs does not move); CSV written with the default and with custom options and read back (no formula-like text, no formula result 0, no gap before the first row); `cross-check.test.ts` and `alias.test.ts` also run the documented deep imports (`deep-imports.cjs`); `alias.test.ts` also checks that LibreOffice shows the dates as exceljs's files do (`1/31/2024`).
|
|
1499
1499
|
|
|
1500
1500
|
## Known differences from the 1.3.0 review
|
|
1501
1501
|
|
|
1502
|
-
Found by a review of 1.3.0 and checked by running exceljs 4.4.0 and `@xlvane/
|
|
1502
|
+
Found by a review of 1.3.0 and checked by running exceljs 4.4.0 and `@xlvane/exceljs` on the same input (Node.js 22.23). F6 describes a difference that xlvane keeps, and F8 values that xlvane refuses. F1, F2, F3, F4, F5, F7, F9, F10 and F12 of that review (merged-cell styles, row styles, the default font, six-digit colours, upper-case date formats, CSV formatter options, `latin1` CSV reading, `column.eachCell`) are fixed in 1.3.1 and described in the tables above, with the differences that remain.
|
|
1503
1503
|
|
|
1504
1504
|
- **F6** Dates from 1900-01-01 to 1900-02-28 differ by one day. xlvane writes and reads them with serial 1 = 1900-01-01 (ECMA-376 Part 4 §15.3.4, docs/facts/ecma-376.md E-15); exceljs writes 1900-01-15 as serial 16 and reads serial 15 as 1900-01-14 (`lib/utils/utils.js` L55-61), so here exceljs is the one that is off, and xlvane keeps its reading. From 1900-03-01 on both agree. Serial 60 (the 29 February 1900 that does not exist) and negative serials with a date format read as numbers (exceljs gives 1900-02-28 and dates before 1899-12-30). In a workbook with the 1904 date system a `Date` before 1904-01-01, such as a time-only value given as 1899-12-30 plus the time, throws `XLV_E_INVALID_VALUE` when written; exceljs writes a negative serial (-1461.44... for 1899-12-30T13:20). Time-only values in the 1900 date system and upper-case date formats such as `DD.MM.YYYY` (F6 and F7 of the 1.3.0 review) behave as in exceljs from 1.3.1.
|
|
1505
1505
|
- **F8** Values exceljs writes without checks (`lib/xlsx/xform/sheet/cell-xform.js` L199-250, `render`) that xlvane refuses with `XLV_E_INVALID_VALUE` when the workbook is written: `NaN` and `Infinity` (exceljs writes `<v>NaN</v>`, `<v>Infinity</v>`), an invalid `Date` (exceljs writes `<v>NaN</v>`), dates before 1900-01-01 or after 9999-12-31 (exceljs writes the serial, for example -18260 for 1850-01-01), text of more than 32 767 characters, text with an unpaired UTF-16 surrogate, and formulas of more than 8 192 characters.
|
|
@@ -1510,21 +1510,21 @@ Found by a review of 1.3.0 and checked by running exceljs 4.4.0 and `@xlvane/com
|
|
|
1510
1510
|
|
|
1511
1511
|
xlvane is not affiliated with the ExcelJS project; its name is used only to identify the package.
|
|
1512
1512
|
|
|
1513
|
-
`@xlvane/
|
|
1513
|
+
`@xlvane/exceljs` offers the commonly used part of the exceljs 4.4.0 API on top of xlvane. It is installed under the name `exceljs` with an npm alias, so code that imports `exceljs` keeps its imports:
|
|
1514
1514
|
|
|
1515
1515
|
```json
|
|
1516
1516
|
"dependencies": {
|
|
1517
|
-
"exceljs": "npm:@xlvane/
|
|
1517
|
+
"exceljs": "npm:@xlvane/exceljs@^1"
|
|
1518
1518
|
}
|
|
1519
1519
|
```
|
|
1520
1520
|
|
|
1521
|
-
npm installs an alias `<alias>@npm:<name>` under the alias name in `node_modules` (npm/cli `docs/lib/content/using-npm/package-spec.md`, "Aliases"; docs/exceljs-compat.md), so `import ExcelJS from 'exceljs'` and `require('exceljs')` load `@xlvane/
|
|
1521
|
+
npm installs an alias `<alias>@npm:<name>` under the alias name in `node_modules` (npm/cli `docs/lib/content/using-npm/package-spec.md`, "Aliases"; docs/exceljs-compat.md), so `import ExcelJS from 'exceljs'` and `require('exceljs')` load `@xlvane/exceljs`. What is supported, partly supported and not supported is listed method by method in [docs/exceljs-compat.md](https://github.com/DevXord/xlvane/blob/main/docs/exceljs-compat.md) (also in `node_modules/xlvane/docs/exceljs-compat.md` after installing xlvane).
|
|
1522
1522
|
|
|
1523
1523
|
This guide uses the `xlvane migrate` command of the `xlvane` package. The `xlvane` commands, the report shown below and the TypeScript examples are checked by the tests in `tests/docs/`; the npm commands were run with npm 10.9.9 on 2026-11-03.
|
|
1524
1524
|
|
|
1525
1525
|
## Before you start
|
|
1526
1526
|
|
|
1527
|
-
- **Node.js.** `@xlvane/
|
|
1527
|
+
- **Node.js.** `@xlvane/exceljs` is an ES module and declares `engines.node` `>=22.12`. `require('exceljs')` of an ES module works without a flag from Node.js 22.12 (docs/exceljs-compat.md); `import` works too, and so do named imports such as `import { Workbook } from 'exceljs'`.
|
|
1528
1528
|
- **Version control.** Commit `package.json` and the lockfile first, so the change can be reviewed and undone.
|
|
1529
1529
|
|
|
1530
1530
|
## 1. See what would change
|
|
@@ -1538,9 +1538,9 @@ npx xlvane migrate
|
|
|
1538
1538
|
`xlvane migrate` does the following, and nothing else:
|
|
1539
1539
|
|
|
1540
1540
|
1. It reads `package.json` of the project directory (the current directory, or the directory given as the first argument). A `package.json` that is a symbolic link is refused.
|
|
1541
|
-
2. It looks for an `"exceljs"` entry in `dependencies`, `devDependencies`, `optionalDependencies` and `peerDependencies`, and shows how each would change to `"npm:@xlvane/
|
|
1541
|
+
2. It looks for an `"exceljs"` entry in `dependencies`, `devDependencies`, `optionalDependencies` and `peerDependencies`, and shows how each would change to `"npm:@xlvane/exceljs@^1"`. Other sections, such as `overrides`, are not changed.
|
|
1542
1542
|
3. It prints the Node.js requirement of `require('exceljs')` next to the project's own `engines.node`.
|
|
1543
|
-
4. It scans the source files of the project (`.js`, `.mjs`, `.cjs`, `.jsx`, `.ts`, `.mts`, `.cts`, `.tsx`, up to 2 MiB each and 10 000 files) for exceljs API that `@xlvane/
|
|
1543
|
+
4. It scans the source files of the project (`.js`, `.mjs`, `.cjs`, `.jsx`, `.ts`, `.mts`, `.cts`, `.tsx`, up to 2 MiB each and 10 000 files) for exceljs API that `@xlvane/exceljs` does not support: `ModelContainer` and deep imports of `exceljs/lib/...`. Only files that contain the text `exceljs` are checked; `node_modules`, folders whose names start with a dot, and symbolic links are skipped. The matching is textual, so a finding is a place to look at, not proof.
|
|
1544
1544
|
5. It writes nothing unless `--force` is given.
|
|
1545
1545
|
|
|
1546
1546
|
For a project whose `package.json` has `"exceljs": "^4.4.0"` in `dependencies`, with a file `src/report.js` that imports `exceljs` and a file `src/legacy.cjs` that requires `exceljs/lib/xlsx/xform/base-xform`, the report is:
|
|
@@ -1548,10 +1548,10 @@ For a project whose `package.json` has `"exceljs": "^4.4.0"` in `dependencies`,
|
|
|
1548
1548
|
```text
|
|
1549
1549
|
Change in package.json:
|
|
1550
1550
|
dependencies: - "exceljs": "^4.4.0"
|
|
1551
|
-
+ "exceljs": "npm:@xlvane/
|
|
1552
|
-
Node.js: require('exceljs') of @xlvane/
|
|
1551
|
+
+ "exceljs": "npm:@xlvane/exceljs@^1"
|
|
1552
|
+
Node.js: require('exceljs') of @xlvane/exceljs needs Node.js 22.12 or later (package.json engines.node: not set).
|
|
1553
1553
|
|
|
1554
|
-
Scanned 2 source files for exceljs API that @xlvane/
|
|
1554
|
+
Scanned 2 source files for exceljs API that @xlvane/exceljs does not fully support:
|
|
1555
1555
|
not supported src/legacy.cjs:1:27 deep import (exceljs/lib/...)
|
|
1556
1556
|
Details: docs/exceljs-compat.md. Unsupported calls throw XLV_E_NOT_SUPPORTED at run time.
|
|
1557
1557
|
|
|
@@ -1569,18 +1569,18 @@ npx xlvane migrate --json
|
|
|
1569
1569
|
```sh
|
|
1570
1570
|
npx xlvane migrate --force --dry-run # show the change without writing it
|
|
1571
1571
|
npx xlvane migrate --force # change package.json
|
|
1572
|
-
npm install # install @xlvane/
|
|
1572
|
+
npm install # install @xlvane/exceljs under the name exceljs
|
|
1573
1573
|
```
|
|
1574
1574
|
|
|
1575
1575
|
`--force` replaces only the value of each `"exceljs"` entry; the rest of `package.json` keeps its formatting and key order. Instead of `xlvane migrate`, the alias can also be installed directly:
|
|
1576
1576
|
|
|
1577
1577
|
```sh
|
|
1578
|
-
npm install exceljs@npm:@xlvane/
|
|
1578
|
+
npm install exceljs@npm:@xlvane/exceljs@^1
|
|
1579
1579
|
```
|
|
1580
1580
|
|
|
1581
|
-
npm then saves the version it installed as the range (with npm 10.9.9 and `@xlvane/
|
|
1581
|
+
npm then saves the version it installed as the range (with npm 10.9.9 and `@xlvane/exceljs` 1.2.2: `"exceljs": "npm:@xlvane/exceljs@^1.2.2"`).
|
|
1582
1582
|
|
|
1583
|
-
The code stays as it was. For example, this exceljs code runs unchanged on `@xlvane/
|
|
1583
|
+
The code stays as it was. For example, this exceljs code runs unchanged on `@xlvane/exceljs`:
|
|
1584
1584
|
|
|
1585
1585
|
```ts
|
|
1586
1586
|
import ExcelJS from 'exceljs';
|
|
@@ -1605,7 +1605,7 @@ In CommonJS, `const ExcelJS = require('exceljs');` gives the same object.
|
|
|
1605
1605
|
|
|
1606
1606
|
- **Run the project's tests.** Unsupported API throws an `XlvError` whose `code` is `XLV_E_NOT_SUPPORTED` and whose message names the method; nothing is dropped silently.
|
|
1607
1607
|
- **Look at each finding of `xlvane migrate`.** Deep imports of `exceljs/lib/...` do not resolve (`exceljs/dist/es5` and the `exceljs/dist/exceljs*.js` files do); `ModelContainer` throws `XLV_E_NOT_SUPPORTED` when it is constructed.
|
|
1608
|
-
- **Read the differences.** [docs/exceljs-compat.md](https://github.com/DevXord/xlvane/blob/main/docs/exceljs-compat.md) lists every method with its status and the exceljs source of each behaviour, and ends with the differences found in reviews and cross-checks. The ones most likely to matter are summarised in the [@xlvane/
|
|
1608
|
+
- **Read the differences.** [docs/exceljs-compat.md](https://github.com/DevXord/xlvane/blob/main/docs/exceljs-compat.md) lists every method with its status and the exceljs source of each behaviour, and ends with the differences found in reviews and cross-checks. The ones most likely to matter are summarised in the [@xlvane/exceljs README](https://github.com/DevXord/xlvane/blob/main/packages/exceljs/README.md#differences-from-exceljs): CSV output escapes text that starts like a formula (`formulaInjection: "off"` writes it unchanged, as exceljs does), a sheet id outside 1 to 65534 is written as the lowest unused id, only the first view of a worksheet is written, the module object is frozen, the streaming writer compresses in JavaScript, and input files are checked against ZIP and XML limits.
|
|
1609
1609
|
- **TypeScript.** The type names of exceljs's `index.d.ts` are exported and work with `moduleResolution` `bundler` and `nodenext` and with `module: commonjs`. Under `module: node16`, TypeScript refuses `import ExcelJS = require('exceljs')` of an ES module (TS1471); use `nodenext` or `commonjs`.
|
|
1610
1610
|
- **Browsers and Workers.** The methods that read or write files (`xlsx.readFile`, `xlsx.writeFile`, `csv.readFile`, `csv.writeFile`, the `filename` forms of the streaming classes and of `addImage`) work in Node.js, Bun and Deno; in browsers and Workers they throw `XLV_E_NOT_SUPPORTED`.
|
|
1611
1611
|
|
|
@@ -1619,7 +1619,7 @@ try {
|
|
|
1619
1619
|
await workbook.xlsx.readFile('report.xlsx');
|
|
1620
1620
|
} catch (error) {
|
|
1621
1621
|
const code = (error as { code?: unknown }).code;
|
|
1622
|
-
if (code === 'XLV_E_NOT_SUPPORTED') console.error('Not supported by @xlvane/
|
|
1622
|
+
if (code === 'XLV_E_NOT_SUPPORTED') console.error('Not supported by @xlvane/exceljs:', (error as Error).message);
|
|
1623
1623
|
else throw error;
|
|
1624
1624
|
}
|
|
1625
1625
|
```
|
|
@@ -1636,7 +1636,7 @@ npm replaces the alias in `package.json` and `node_modules`. Restoring `package.
|
|
|
1636
1636
|
|
|
1637
1637
|
## Reporting a problem
|
|
1638
1638
|
|
|
1639
|
-
When exceljs code behaves differently on `@xlvane/
|
|
1639
|
+
When exceljs code behaves differently on `@xlvane/exceljs` and the difference is not listed in docs/exceljs-compat.md, please open an issue at https://github.com/DevXord/xlvane/issues with a small script that shows it.
|
|
1640
1640
|
|
|
1641
1641
|
<!-- file: docs/xlsx-cves.md -->
|
|
1642
1642
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xlvane",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.3",
|
|
4
4
|
"description": "Read, inspect and write XLSX files; input is treated as untrusted. ESM only, one runtime dependency (fflate).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"xlsx",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"spreadsheetml"
|
|
11
11
|
],
|
|
12
12
|
"license": "MIT",
|
|
13
|
-
"homepage": "https://github.
|
|
13
|
+
"homepage": "https://xlvane.github.io/",
|
|
14
14
|
"bugs": {
|
|
15
15
|
"url": "https://github.com/DevXord/xlvane/issues"
|
|
16
16
|
},
|
package/skills/xlvane/SKILL.md
CHANGED
|
@@ -187,7 +187,7 @@ Formulas on every sheet, merged cells, links, notes, conditional formats (also e
|
|
|
187
187
|
|
|
188
188
|
In Node.js, `xlvane/node` adds `readWorkbookFile`, `inspectFile` and `writeWorkbookFile` (which never replaces an existing file unless `{ overwrite: true }` is passed). `toCSV`, `fromCSV`, `toJSON` and `fromJSON` convert tables. For very large files use `openWorkbookStream` and `writeWorkbookStream`.
|
|
189
189
|
|
|
190
|
-
Code written for the `exceljs` API can run on xlvane through `@xlvane/
|
|
190
|
+
Code written for the `exceljs` API can run on xlvane through `@xlvane/exceljs` (`"exceljs": "npm:@xlvane/exceljs@^1"` in package.json); unsupported exceljs features throw `XLV_E_NOT_SUPPORTED`.
|
|
191
191
|
|
|
192
192
|
## Command line
|
|
193
193
|
|