xlvane 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/dist/cli.js +226 -47
- package/dist/index.d.ts +5 -4
- package/dist/index.js +3 -3
- package/dist/{node-files-B0iqSJIJ.js → node-files-CDb6TyZb.js} +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +3 -3
- package/dist/{options-CwSp2pA4.js → options-Ba1iWD-Z.js} +316 -75
- package/dist/{rows-DKwlr0rg.js → rows-IWKIxHt9.js} +59 -15
- package/dist/{stream-write-BKppyMz0.js → stream-write-BGuUjlXo.js} +24 -9
- package/dist/{stream-write-GJXORYQ2.d.ts → stream-write-BVaFkgwO.d.ts} +9 -6
- package/docs/cli-json/mcp.schema.json +43 -0
- package/docs/cli-json.md +2 -1
- package/docs/errors.md +27 -0
- package/docs/exceljs-compat.md +1 -1
- package/llms-full.txt +90 -10
- package/package.json +1 -1
- package/skills/xlvane/SKILL.md +8 -3
package/llms-full.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# xlvane 1.
|
|
1
|
+
# xlvane 1.2.0: 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
|
|
|
@@ -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/compat
|
|
67
|
+
- `xlvane migrate` prepares a project for `@xlvane/compat`, 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
|
|
|
@@ -391,10 +391,10 @@ Limits can be changed per call, for example `readWorkbook(bytes, { limits: { max
|
|
|
391
391
|
| `maxXmlDepth` | 128 | deeply nested XML |
|
|
392
392
|
| `maxXmlAttributes` | 256 | elements with huge numbers of attributes |
|
|
393
393
|
| `maxXmlNameLength` | 1 024 | huge element or attribute names |
|
|
394
|
-
| `maxXmlTextLength` | 8 Mi characters | huge text nodes
|
|
394
|
+
| `maxXmlTextLength` | 8 Mi characters | huge text nodes, attribute values, comments or processing instructions |
|
|
395
395
|
| `maxXmlTreeElements` | 1 000 000 | huge workbook, styles or relationship parts (elements plus attributes) |
|
|
396
|
-
| `maxCells` | 5 000 000 | workbooks too large to hold in memory (measured: about 180 bytes per numeric cell, Node.js 26) |
|
|
397
|
-
| `maxSharedStringChars` | 512 Mi characters | many cells pointing at one huge shared string (a few MB that become many GB when values are copied) |
|
|
396
|
+
| `maxCells` | 5 000 000 | workbooks too large to hold in memory (measured: about 180 bytes per numeric cell, Node.js 26); also bounds the output of `toCSV`, `readTable`, `toJSON` and `readTableStream` to `max(maxCells, 16 × cells read)` positions |
|
|
397
|
+
| `maxSharedStringChars` | 512 Mi characters | many cells pointing at one huge shared string (a few MB that become many GB when values are copied); counted separately, the same for cells sharing one huge formula |
|
|
398
398
|
|
|
399
399
|
## Package size
|
|
400
400
|
|
|
@@ -409,6 +409,7 @@ Limits can be changed per call, for example `readWorkbook(bytes, { limits: { max
|
|
|
409
409
|
|
|
410
410
|
## Links
|
|
411
411
|
|
|
412
|
+
- Website with the guide and an in-browser demo: [xlvane.github.io](https://xlvane.github.io)
|
|
412
413
|
- Changes in each version: [CHANGELOG.md](https://github.com/DevXord/xlvane/blob/main/CHANGELOG.md)
|
|
413
414
|
- Bugs and questions: [GitHub issues](https://github.com/DevXord/xlvane/issues)
|
|
414
415
|
- Reporting a vulnerability: [SECURITY.md](https://github.com/DevXord/xlvane/blob/main/SECURITY.md)
|
|
@@ -419,21 +420,22 @@ License: MIT
|
|
|
419
420
|
|
|
420
421
|
---
|
|
421
422
|
name: xlvane
|
|
422
|
-
description: Read, inspect, write, edit, convert, compare and validate Excel XLSX files with the xlvane library
|
|
423
|
+
description: Read, inspect, write, edit, convert, compare and validate Excel XLSX files with the xlvane library, its xlvane command line or its MCP server. Use when a task involves .xlsx files, sheets turned into JSON or CSV, spreadsheet reports, or checking changes to a workbook.
|
|
423
424
|
license: MIT
|
|
424
|
-
compatibility: Node.js 22 or later. The library core works on Uint8Array and has no Node.js dependencies; the CLI
|
|
425
|
+
compatibility: Node.js 22 or later. The library core works on Uint8Array and has no Node.js dependencies; the CLI, the file helpers in xlvane/node and the MCP server need Node.js.
|
|
425
426
|
---
|
|
426
427
|
|
|
427
428
|
# xlvane: XLSX files
|
|
428
429
|
|
|
429
430
|
xlvane reads, writes and edits `.xlsx` files. It treats input files as untrusted (size and ZIP limits, no external entities, macros are never run, links are never followed). It does not calculate formulas: it reads the cached results stored in the file and writes the formula text you give.
|
|
430
431
|
|
|
431
|
-
|
|
432
|
+
Three ways to use it, with the same behaviour:
|
|
432
433
|
|
|
433
434
|
| Way | When | Start |
|
|
434
435
|
|---|---|---|
|
|
435
436
|
| Library `xlvane` | You write JavaScript or TypeScript code | `npm install xlvane` |
|
|
436
437
|
| Command line `xlvane` | You run shell commands | `npx xlvane help` |
|
|
438
|
+
| MCP server `@xlvane/mcp` | Your client calls MCP tools | `npx @xlvane/mcp --root <dir>` |
|
|
437
439
|
|
|
438
440
|
## Recommended order of work
|
|
439
441
|
|
|
@@ -609,6 +611,10 @@ xlvane validate report.xlsx --columns "Region:string,Revenue:number"
|
|
|
609
611
|
|
|
610
612
|
Add `--json` to any command for one JSON document with a documented schema (`docs/cli-json.md` in the package). Exit codes: 0 success, 1 a check found something, 2 usage error, 3 input or file error. Nothing is overwritten without `--force`; commands that write accept `--dry-run`.
|
|
611
613
|
|
|
614
|
+
## MCP server
|
|
615
|
+
|
|
616
|
+
`npx @xlvane/mcp --root ./data` serves the tools `inspect_workbook`, `read_table`, `diff` and `validate` for files inside `./data` only. With `--allow-write` it also serves `write_table`, `edit_cells` and `convert`; they create new files and replace an existing file only when the call passes `"overwrite": true`. Paths outside the roots, also through `..` or symbolic links, are refused with `XLV_E_PATH_NOT_ALLOWED`. A result is at most 1 Mi characters of JSON (`--max-response-chars`): `read_table` then returns the rows that fit, with `truncated: true` and `nextOffset` for the next call.
|
|
617
|
+
|
|
612
618
|
## Errors
|
|
613
619
|
|
|
614
620
|
Every error is an `XlvError` with a stable `code` (`XLV_E_*`), a `location` (sheet, cell, part), a `hint` that says what to do, and `details` (for example the list of available sheets). Read the hint and correct the call; the codes are described in `docs/errors.md` in the package. Warnings (`XLV_W_*`) never stop reading; check `workbook.warnings` or `inspect(...).warnings`.
|
|
@@ -693,11 +699,13 @@ Each code links to its section, which says what to do. The CLI prints the code a
|
|
|
693
699
|
| [`XLV_W_MACROS_PRESENT`](#xlv_w_macros_present) | The workbook contains a VBA project or Excel 4.0 macro sheets. |
|
|
694
700
|
| [`XLV_W_EXTERNAL_LINKS`](#xlv_w_external_links) | The workbook links to other workbooks. |
|
|
695
701
|
| [`XLV_W_DUPLICATE_CELL`](#xlv_w_duplicate_cell) | A sheet defines the same cell more than once. |
|
|
702
|
+
| [`XLV_W_LIMIT_REACHED`](#xlv_w_limit_reached) | Reading stopped computing something derived from the file because the work would be far out of proportion to its data. |
|
|
696
703
|
| [`XLV_W_INVALID_VALUE`](#xlv_w_invalid_value) | A value does not match its declared type and is returned in a safe form, for example a numeric cell whose text is not a number (returned … |
|
|
697
704
|
| [`XLV_W_UNUSUAL_HYPERLINK`](#xlv_w_unusual_hyperlink) | A sheet has hyperlinks whose external target uses a scheme other than `http`, `https` or `mailto`, for example `file:`, `javascript:` or … |
|
|
698
705
|
| [`XLV_W_DRAWING_CONTENT_NOT_READ`](#xlv_w_drawing_content_not_read) | The drawing of a sheet holds objects other than pictures: charts, shapes, connectors, group shapes, content parts or alternate content. |
|
|
699
706
|
| [`XLV_W_THREADED_COMMENTS`](#xlv_w_threaded_comments) | A sheet has threaded comments, the conversations of current Excel versions ([MS-XLSX] §2.3.7). |
|
|
700
707
|
| [`XLV_W_SHEET_PART_MISSING`](#xlv_w_sheet_part_missing) | A sheet listed in the workbook has no part (the relationship or the part itself is missing). |
|
|
708
|
+
| [`XLV_W_SHEET_PART_SHARED`](#xlv_w_sheet_part_shared) | Two or more sheets listed in the workbook lead to the same worksheet part, or relate to the same comments, VML or table part. |
|
|
701
709
|
| [`XLV_W_PART_MISSING`](#xlv_w_part_missing) | The workbook points to a styles or shared strings part that does not exist. |
|
|
702
710
|
| [`XLV_W_FORMULAS_NOT_RECALCULATED`](#xlv_w_formulas_not_recalculated) | Reported by `editCells` and `appendRows` when the workbook contains formulas. |
|
|
703
711
|
| [`XLV_W_INVALID_CELL_REF`](#xlv_w_invalid_cell_ref) | A worksheet contains a row whose number is not a whole number from 1 to 1048576, a cell whose `r` reference is not a valid A1 reference … |
|
|
@@ -721,6 +729,14 @@ An argument of a method of `@xlvane/compat` is not valid, in a case where excelj
|
|
|
721
729
|
### XLV_E_LIMIT_EXCEEDED
|
|
722
730
|
The file exceeds one of the resource limits (`ReadLimits`): input size, number of ZIP entries, decompressed size of one entry or of all entries, compression ratio, XML nesting depth, attribute count, name or text length, number of elements in a tree-parsed part, or number of cells. `details.limit` names the limit and `details.value` its current value. Sizes are measured on the bytes actually produced by decompression, so a file cannot avoid a limit by declaring false sizes.
|
|
723
731
|
|
|
732
|
+
Some limits also bound work derived from a small file (1.1.1, D-H01):
|
|
733
|
+
|
|
734
|
+
- `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/compat`'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.
|
|
735
|
+
- `maxXmlTextLength`: also the length of an XML comment or processing instruction.
|
|
736
|
+
- `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.
|
|
737
|
+
|
|
738
|
+
The MCP server (`@xlvane/mcp`) returns it as a tool error for a file larger than `--max-file-size` (`details.limit` `maxFileBytes`) and for a result longer than `--max-response-chars` (`details.limit` `maxResponseChars`; `read_table` instead returns the rows that fit).
|
|
739
|
+
|
|
724
740
|
`fromCSV` (and `xlvane convert`/`create` with CSV input) throws it for text with more fields than `maxCells` (default 5 000 000, `details.limit` `maxCells`), more than 16 384 fields on a line or more than 1 048 576 lines.
|
|
725
741
|
|
|
726
742
|
`NewSheet.validate` throws it when a sheet would get more than 65534 data validations ([MS-OI29500] §2.1.614 g; `details.limit` `dataValidations`). When reading, the conditional formatting and data validations of one sheet count against `maxXmlTreeElements`.
|
|
@@ -794,6 +810,7 @@ A part exists but has the wrong structure: for example the workbook part's root
|
|
|
794
810
|
| `target-mode` | `TargetMode` is neither `Internal` nor `External` |
|
|
795
811
|
| `internal-target` | an internal relationship target cannot be resolved to a part name |
|
|
796
812
|
| `equivalent-part-names` | two ZIP entries map to equivalent part names (e.g. a raw UTF-8 name and its percent-encoded form) |
|
|
813
|
+
|
|
797
814
|
**Fix:** check that the file is an Excel workbook (not a Word or PowerPoint document) and re-save it in a spreadsheet application.
|
|
798
815
|
|
|
799
816
|
### XLV_E_INVALID_CELL_REF
|
|
@@ -895,10 +912,18 @@ For `insertRows`/`deleteRows`, insert or delete the rows in a spreadsheet applic
|
|
|
895
912
|
The `xlvane` command line was used incorrectly: an unknown command or option, a missing or extra argument, an option without its value, or an option value that is not allowed. `details` names the command and the option or argument; `details.suggestions` lists close matches ("Did you mean ...?"). Exit code 2.
|
|
896
913
|
**Fix:** run `xlvane help <command>` for the usage and examples of the command.
|
|
897
914
|
|
|
915
|
+
### XLV_E_NOT_INSTALLED
|
|
916
|
+
`xlvane mcp` needs the separate package `@xlvane/mcp`, which could not be loaded. `details.package` names it.
|
|
917
|
+
**Fix:** install it next to xlvane, for example `npm install @xlvane/mcp`.
|
|
918
|
+
|
|
898
919
|
### XLV_E_INTERNAL
|
|
899
920
|
The `xlvane` command line caught an error that is not an `XlvError`. This is a bug in xlvane. `details.name` is the error's name; `--verbose` prints the stack trace.
|
|
900
921
|
**Fix:** report it with the command and, if possible, the input file (see SECURITY.md for files that must stay private).
|
|
901
922
|
|
|
923
|
+
### XLV_E_PATH_NOT_ALLOWED
|
|
924
|
+
The MCP server (`@xlvane/mcp`) was asked to read or write a path outside the directories it was started with (`--root`), including paths that leave them through `..` or a symbolic link, or to write through a symbolic link. Nothing was read or written. `details.path` is the path as given and `details.roots` lists the allowed directories.
|
|
925
|
+
**Fix:** use a path inside one of the listed directories, or restart the server with another `--root`.
|
|
926
|
+
|
|
902
927
|
## Warnings
|
|
903
928
|
|
|
904
929
|
### XLV_W_DIMENSION_MISMATCH
|
|
@@ -921,6 +946,10 @@ Some merged ranges have values in cells other than the top-left one. Spreadsheet
|
|
|
921
946
|
`editCells` or `appendRows` wrote a value into a cell of a merged range other than its top-left cell. The value is stored, but spreadsheet applications show only the top-left cell of a merged range, so the value is not visible. `cells` lists the cells written (up to ten); the message names the first one and its merged range.
|
|
922
947
|
**Fix:** write the value into the top-left cell of the range (named in the message), or unmerge the range first.
|
|
923
948
|
|
|
949
|
+
### XLV_W_LIMIT_REACHED
|
|
950
|
+
Reading stopped computing something derived from the file because the work would be far out of proportion to its data, and the file is read without it. Today: hyperlinks whose ranges cover far more positions than the sheet has cells (more than 16 visits per cell plus 1 000 000); `sheet.hyperlinks` lists every link, but `cell.hyperlink` is not set for the cells of the remaining links (D-H01).
|
|
951
|
+
**Fix:** nothing, if the file comes from an unknown source: this protects the reader. Look up a cell's link in `sheet.hyperlinks` by its range.
|
|
952
|
+
|
|
924
953
|
### XLV_W_VERY_HIDDEN_SHEET
|
|
925
954
|
A sheet has the state `veryHidden`: spreadsheet applications offer no menu command to unhide it, so users usually do not know it exists.
|
|
926
955
|
**Fix:** nothing, if the sheet is expected; `inspect` lists it with its state, and `workbook.sheets` includes it.
|
|
@@ -957,6 +986,10 @@ A sheet has threaded comments, the conversations of current Excel versions ([MS-
|
|
|
957
986
|
A sheet listed in the workbook has no part (the relationship or the part itself is missing). The sheet is returned with `part: null` and no cells.
|
|
958
987
|
**Fix:** re-save the file in the application that made it; the sheet's cells are not in the file.
|
|
959
988
|
|
|
989
|
+
### XLV_W_SHEET_PART_SHARED
|
|
990
|
+
Two or more sheets listed in the workbook lead to the same worksheet part, or relate to the same comments, VML or table part (part names compared without regard to case, as OPC requires). Spreadsheet applications write one such part per sheet; reading a shared part again for every sheet would decompress and parse it many times, outside the limit on decompressed bytes. The part is read for the first of these sheets only: for a worksheet part, the others are returned with `part: null` and no cells; for a comments, VML or table part, the others are read without its notes or table. A sheet that relates to one table part twice gets that table once. The location names the sheet and the part.
|
|
991
|
+
**Fix:** re-save the file in the application that made it, and check whether the sheets returned without cells should hold data.
|
|
992
|
+
|
|
960
993
|
### XLV_W_PART_MISSING
|
|
961
994
|
The workbook points to a styles or shared strings part that does not exist. Reading continues without it: without styles, date-formatted numbers are returned as numbers; without shared strings, shared-string cells are treated as empty.
|
|
962
995
|
**Fix:** re-save the file in the application that made it; check number formats and text cells of the result.
|
|
@@ -1184,7 +1217,7 @@ The error envelope is defined in [cli-json/common.schema.json](cli-json/common.s
|
|
|
1184
1217
|
| Code | Meaning |
|
|
1185
1218
|
|---|---|
|
|
1186
1219
|
| 0 | Success. |
|
|
1187
|
-
| 1 | The command ran, and a check found something: `diff` found differences, or `validate` found problems. |
|
|
1220
|
+
| 1 | The command ran, and a check found something: `diff` found differences, or `validate` found problems. `mcp` returns the exit code of the server (0, or 2 and 3 as below). |
|
|
1188
1221
|
| 2 | Usage error (`XLV_E_USAGE`): unknown command or option, missing or extra argument, invalid option value. |
|
|
1189
1222
|
| 3 | Input or file error: the file cannot be read, is not a valid workbook, the sheet does not exist, the output exists without `--force`, and so on. |
|
|
1190
1223
|
|
|
@@ -1200,6 +1233,7 @@ The error envelope is defined in [cli-json/common.schema.json](cli-json/common.s
|
|
|
1200
1233
|
| `diff` | [cli-json/diff.schema.json](cli-json/diff.schema.json) | The `diff()` result: `equal`, `sheetsAdded`, `sheetsRemoved`, `sheets` (cell changes with `before` and `after`), `summary`. Every change is included. |
|
|
1201
1234
|
| `validate` | [cli-json/validate.schema.json](cli-json/validate.schema.json) | `file`, `ok`, `sheet`, `rowsChecked`, `problems` (`kind`, `column`, `cell`, `row`, `message`), `warnings`. |
|
|
1202
1235
|
| `migrate` | [cli-json/migrate.schema.json](cli-json/migrate.schema.json) | `directory`, `packageJson`, `changes` (`section`, `from`, `to`), `alreadyMigrated`, `enginesNode`, `filesScanned`, `scanLimited`, `findings` (`file`, `line`, `column`, `api`, `status`), `written`. |
|
|
1236
|
+
| `mcp` | [cli-json/mcp.schema.json](cli-json/mcp.schema.json) | `--json` is refused with a usage error (exit code 2), printed as this document, because stdout carries the MCP protocol. |
|
|
1203
1237
|
|
|
1204
1238
|
<!-- file: docs/exceljs-compat.md -->
|
|
1205
1239
|
|
|
@@ -1243,7 +1277,7 @@ Status: **supported** means the same behaviour as exceljs for the cases covered
|
|
|
1243
1277
|
| `xlsx.write(stream)` | supported | | `lib/xlsx/xlsx.js` L643 |
|
|
1244
1278
|
| `xlsx.createInputStream()` | supported | Throws the deprecation error, as in exceljs 4. | `lib/xlsx/xlsx.js` L238 |
|
|
1245
1279
|
| `csv.read(stream, options)`, `csv.readFile(path, options)` | supported | Adds a worksheet, with exceljs's options (`sheetName`, `dateFormats`, `map`, `parserOptions`: `delimiter`, `quote`, `escape`, `trim`/`ltrim`/`rtrim`, `ignoreEmpty`, `comment`, `skipLines`, `skipRows`, `maxRows`, `headers`, `renameHeaders`, `encoding`) and its default conversion of fields (X4-23), on xlvane's own parser (no fast-csv). Accepts a Node.js readable stream, a Web `ReadableStream` or any (async) iterable of strings or bytes. Differences: text of white space only stays text (exceljs reads `' '` as 0), `-Infinity` stays text (it cannot be stored), a leading byte order mark is dropped (exceljs keeps it in the first field), `headers: true` skips the header line (exceljs throws `data.map is not a function`), a missing file or a malformed line throws `XLV_E_FILE_READ` / `XLV_E_CSV_MALFORMED`. `readFile` needs `node:fs` (Node.js, Bun, Deno). Dates are parsed as dayjs 1.11 customParseFormat parses them in strict mode (D-E06): letters that are no token, such as an unbracketed `T` or `dddd`, are skipped, and each token is searched in the rest of the text. An unclosed quote is reported on the line where it opens; a `quote` or `escape` longer than one character throws `XLV_E_INVALID_OPTION`. | `lib/csv/csv.js` L32–98 |
|
|
1246
|
-
| `csv.write(stream, options)`, `csv.writeFile(path, options)`, `csv.writeBuffer(options)` | supported | Writes one worksheet with exceljs's options (`sheetName`, `sheetId`, `dateFormat`, `dateUTC`, `map`, `includeEmptyRows`, `encoding`, `formatterOptions`: `delimiter`, `rowDelimiter`, `quote`, `escape`, `quoteColumns`, `headers`, `writeHeaders`, `includeEndRowDelimiter`, `writeBOM`) and fast-csv's quoting (X4-24); the cross-check sample gives the same text as exceljs 4.4.0. Differences: text that starts with `=`, `+`, `-`, `@`, tab, CR or
|
|
1280
|
+
| `csv.write(stream, options)`, `csv.writeFile(path, options)`, `csv.writeBuffer(options)` | supported | Writes one worksheet with exceljs's options (`sheetName`, `sheetId`, `dateFormat`, `dateUTC`, `map`, `includeEmptyRows`, `encoding`, `formatterOptions`: `delimiter`, `rowDelimiter`, `quote`, `escape`, `quoteColumns`, `headers`, `writeHeaders`, `includeEndRowDelimiter`, `writeBOM`) and fast-csv's quoting (X4-24); the cross-check sample gives the same text as exceljs 4.4.0. Differences: text that starts with `=`, `+`, `-`, `@`, tab, CR, LF or another control character, or with a full-width or small form of these signs, is written with a leading `'` (CSV injection, docs/facts/csv.md CSV-10, CSV-12; `formulaInjection: "off"` writes it unchanged, as exceljs); a formula result of 0 or `false` is written (exceljs writes an empty field), a date result is formatted as a date and an error result as its text; one blank line per missing row also before the first row (exceljs writes one too few there); a `sheetName` or `sheetId` that does not exist throws `XLV_E_SHEET_NOT_FOUND` (exceljs writes an empty file); header names in `formatterOptions.headers` are escaped like values. With `headers`, an array row gives one field per header (longer rows cut, shorter ones end in empty fields), as fast-csv writes it; `dateFormat: ''` uses the default format, as dayjs does (D-E06). `writeFile` writes `utf8`, `utf16le` or `latin1` and needs `node:fs`. | `lib/csv/csv.js` L109–186 |
|
|
1247
1281
|
| `csv.createInputStream()` | supported | Throws the deprecation error, as in exceljs 4. | `lib/csv/csv.js` L101 |
|
|
1248
1282
|
| `definedNames` (`add`, `addEx`, `remove`, `removeEx`, `removeAllNames`, `forEach`, `getNames`, `getNamesEx`, `getRanges`, `getMatrix`, `model`) | supported | As in exceljs, a name is a set of cells, written as rectangles with absolute references and no sheet scope; on reading, names that are not cell ranges (constants, formulas, `#REF!`) and the sheet scope (`localSheetId`) are dropped. Built-in `_xlnm.` names are not listed: print areas and titles are read into `pageSetup`, as in exceljs, and xlvane writes the autofilter name itself. Names exceljs accepts but Excel does not (for example `A1` or names starting with `_xl`) throw `XLV_E_INVALID_DEFINED_NAME` when the workbook is written. | `lib/doc/defined-names.js`; `lib/xlsx/xform/book/defined-name-xform.js`; `lib/xlsx/xform/book/workbook-xform.js` L187 |
|
|
1249
1283
|
| `addImage(image)`, `getImage(id)` | supported | PNG, JPEG and GIF given as `buffer`, `base64` (a data URL is accepted, as in exceljs) or `filename`; the format is recognised from the bytes, `extension` is kept but not used (exceljs writes `image/jpg` for `extension: 'jpg'`). As in exceljs, a `filename` is read when the workbook is written (`xlsx.writeBuffer`/`writeFile`/`write` and the streaming `WorkbookWriter`), so a missing file fails there; outside Node.js, Bun and Deno it gives `XLV_E_NOT_SUPPORTED`. Other formats throw `XLV_E_INVALID_IMAGE`. Read back, each image part is one media entry `{ type, name, extension, buffer }`, `buffer` a `Uint8Array`. Identical images are stored once, with one relationship per drawing (exceljs writes one per use). | `lib/doc/workbook.js` L142–151; `lib/xlsx/xlsx.js` L421–442 (L426–429: `filename` read at write) |
|
|
@@ -2637,6 +2671,52 @@ A workbook loaded with `xlsx.load()` is written again by `xlsx.writeBuffer()` (`
|
|
|
2637
2671
|
]
|
|
2638
2672
|
}
|
|
2639
2673
|
|
|
2674
|
+
<!-- file: docs/cli-json/mcp.schema.json -->
|
|
2675
|
+
|
|
2676
|
+
{
|
|
2677
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
2678
|
+
"$id": "mcp.schema.json",
|
|
2679
|
+
"title": "xlvane mcp --json (errors only; the server itself speaks MCP)",
|
|
2680
|
+
"oneOf": [
|
|
2681
|
+
{
|
|
2682
|
+
"type": "object",
|
|
2683
|
+
"properties": {
|
|
2684
|
+
"xlvane": {
|
|
2685
|
+
"const": 1
|
|
2686
|
+
},
|
|
2687
|
+
"command": {
|
|
2688
|
+
"const": "mcp"
|
|
2689
|
+
},
|
|
2690
|
+
"ok": {
|
|
2691
|
+
"const": true
|
|
2692
|
+
},
|
|
2693
|
+
"result": {
|
|
2694
|
+
"type": "object",
|
|
2695
|
+
"properties": {
|
|
2696
|
+
"exitCode": {
|
|
2697
|
+
"type": "integer"
|
|
2698
|
+
}
|
|
2699
|
+
},
|
|
2700
|
+
"required": [
|
|
2701
|
+
"exitCode"
|
|
2702
|
+
],
|
|
2703
|
+
"additionalProperties": false
|
|
2704
|
+
}
|
|
2705
|
+
},
|
|
2706
|
+
"required": [
|
|
2707
|
+
"xlvane",
|
|
2708
|
+
"command",
|
|
2709
|
+
"ok",
|
|
2710
|
+
"result"
|
|
2711
|
+
],
|
|
2712
|
+
"additionalProperties": false
|
|
2713
|
+
},
|
|
2714
|
+
{
|
|
2715
|
+
"$ref": "common.schema.json#/$defs/errorEnvelope"
|
|
2716
|
+
}
|
|
2717
|
+
]
|
|
2718
|
+
}
|
|
2719
|
+
|
|
2640
2720
|
<!-- file: docs/cli-json/migrate.schema.json -->
|
|
2641
2721
|
|
|
2642
2722
|
{
|
package/package.json
CHANGED
package/skills/xlvane/SKILL.md
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: xlvane
|
|
3
|
-
description: Read, inspect, write, edit, convert, compare and validate Excel XLSX files with the xlvane library
|
|
3
|
+
description: Read, inspect, write, edit, convert, compare and validate Excel XLSX files with the xlvane library, its xlvane command line or its MCP server. Use when a task involves .xlsx files, sheets turned into JSON or CSV, spreadsheet reports, or checking changes to a workbook.
|
|
4
4
|
license: MIT
|
|
5
|
-
compatibility: Node.js 22 or later. The library core works on Uint8Array and has no Node.js dependencies; the CLI
|
|
5
|
+
compatibility: Node.js 22 or later. The library core works on Uint8Array and has no Node.js dependencies; the CLI, the file helpers in xlvane/node and the MCP server need Node.js.
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# xlvane: XLSX files
|
|
9
9
|
|
|
10
10
|
xlvane reads, writes and edits `.xlsx` files. It treats input files as untrusted (size and ZIP limits, no external entities, macros are never run, links are never followed). It does not calculate formulas: it reads the cached results stored in the file and writes the formula text you give.
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Three ways to use it, with the same behaviour:
|
|
13
13
|
|
|
14
14
|
| Way | When | Start |
|
|
15
15
|
|---|---|---|
|
|
16
16
|
| Library `xlvane` | You write JavaScript or TypeScript code | `npm install xlvane` |
|
|
17
17
|
| Command line `xlvane` | You run shell commands | `npx xlvane help` |
|
|
18
|
+
| MCP server `@xlvane/mcp` | Your client calls MCP tools | `npx @xlvane/mcp --root <dir>` |
|
|
18
19
|
|
|
19
20
|
## Recommended order of work
|
|
20
21
|
|
|
@@ -190,6 +191,10 @@ xlvane validate report.xlsx --columns "Region:string,Revenue:number"
|
|
|
190
191
|
|
|
191
192
|
Add `--json` to any command for one JSON document with a documented schema (`docs/cli-json.md` in the package). Exit codes: 0 success, 1 a check found something, 2 usage error, 3 input or file error. Nothing is overwritten without `--force`; commands that write accept `--dry-run`.
|
|
192
193
|
|
|
194
|
+
## MCP server
|
|
195
|
+
|
|
196
|
+
`npx @xlvane/mcp --root ./data` serves the tools `inspect_workbook`, `read_table`, `diff` and `validate` for files inside `./data` only. With `--allow-write` it also serves `write_table`, `edit_cells` and `convert`; they create new files and replace an existing file only when the call passes `"overwrite": true`. Paths outside the roots, also through `..` or symbolic links, are refused with `XLV_E_PATH_NOT_ALLOWED`. A result is at most 1 Mi characters of JSON (`--max-response-chars`): `read_table` then returns the rows that fit, with `truncated: true` and `nextOffset` for the next call.
|
|
197
|
+
|
|
193
198
|
## Errors
|
|
194
199
|
|
|
195
200
|
Every error is an `XlvError` with a stable `code` (`XLV_E_*`), a `location` (sheet, cell, part), a `hint` that says what to do, and `details` (for example the list of available sheets). Read the hint and correct the call; the codes are described in `docs/errors.md` in the package. Warnings (`XLV_W_*`) never stop reading; check `workbook.warnings` or `inspect(...).warnings`.
|