@rosperitus/excelerate-reader
v0.13.0
Published
Read spreadsheets in the browser or Node: xlsx, xls, ods, csv, html, SYLK, Gnumeric and SpreadsheetML, with cell styles. Reading only.
Downloads
672
Maintainers
Readme
excelerate-reader
Read spreadsheets in Node or the browser - xlsx, xls, ods, csv, html, SYLK, Gnumeric and SpreadsheetML 2003 - and read how their cells are painted. Rust compiled to WebAssembly, no native module to build and nothing to install alongside it.
This is the reading half of excelerate. The full package also writes files back out and carries a 518-function formula engine; if you need either, use that one. Here they are not compiled in at all, which is the point: a reader that cannot write cannot be made to write, and the binary is the smaller for it.
const { readFileSync } = require("node:fs");
const { Book } = require("@rosperitus/excelerate-reader");
// The format is worked out from the bytes; the name only settles what they
// cannot say themselves.
const book = Book.read(readFileSync("report.xlsx"), "report.xlsx");
for (const name of book.sheetNames()) {
const sheet = book.sheetIndex(name);
console.log(name, book.usedRange(sheet));
}
// A cell's value, the text Excel shows for it, and the formula behind it.
book.get(0, "B2"); // 1234.5
book.getFormatted(0, "B2"); // "1 234,50 ₽"
book.getFormula(0, "B2"); // "SUM(B3:B9)" - the text, not its answer
// A whole rectangle in one crossing of the wasm boundary.
book.getRange(0, "A1:D20");
// Or a whole row with its styling, which is one crossing instead of a dozen.
book.getRowAt(0, 3); // { values, formatted, bold, indent, hidden }
book.getRowAt(0, 3, false); // the same without the displayed text, which is
// a string per cell nobody asked forLayout
Reading a sheet usually means asking the same few things of every row, so each has an answer that does not build a whole style to get at one flag:
book.cellBoldAt(0, 3, 1); // true - the font flag on its own
book.rowHidden(0, 3); // false
book.mergedRanges(0); // ["A1:H1", "A2:H2", ...] - what the header spans
book.mergedRangesAt(0); // the same as numbers: [r1, c1, r2, c2] per area,
// one Uint32Array where a big sheet has 300k areas
book.sheetVisibility(0); // "visible" | "hidden" | "veryHidden"sheetNames lists every sheet, hidden ones included: the index every other
call takes is the sheet's position in the workbook, and skipping the hidden
ones would shift it.
usedRangeHint answers the same question as usedRange without ever walking
the rows (usedRange walks them only after a cell in an edge column was
removed, and the hint may then be wider), and columnWidth
and rowHeight come back undefined where the sheet leaves them to the
default.
What is on a sheet besides cells
book.comments(0); // [{ address: "B2", author: "Иванов", text: "сверить" }]
book.hyperlinks(0); // [{ range, target, external, display, tooltip }]
book.tables(0); // [{ name, displayName, range, columns, ... }]
book.charts(0); // [{ name, title, kinds: ["barChart"], seriesCount, anchor }]
book.images(0); // [{ name, format, byteLength, anchor }] - no bytes
book.imageData(0, 0); // Uint8Array, the picture itself
book.shapes(0); // [{ name, geometry, text, anchor }]An anchor is where the object sits, in the numbers a user sees:
{ kind: "twoCell", row: 3, column: 2 }. An absolute anchor is at a point on
the sheet rather than at a cell, so its row and column are null.
Beyond the cells, a file states rules and names, and those are here too:
definedNames(), dataValidations(sheet), conditionalFormats(sheet),
autoFilter(sheet), pivotTables(sheet), arrayFormulas(sheet),
externalBooks(), sheetView(sheet) (frozen rows and columns, zoom, grid
lines) and sheetProtection(sheet) with verifySheetPassword. Book.readCsv
reads CSV with the delimiter stated rather than guessed.
Styles
cellStyle answers with the number format, font, fill, borders and text
placement, as the file states them. A cell the file says nothing about answers
with Excel's own defaults, which is what Excel shows for it.
const style = book.cellStyle(0, "A1");
style.font.bold; // true
style.font.size; // 14 - points, not the hundredths the file stores
style.fill.foreground; // "#FFFFE699"
style.borders.bottom; // { style: "thin", color: "#FF000000" }
style.alignment.wrapText; // true
style.numberFormat; // "#,##0.00"Colours come as text: #AARRGGBB when the file names one outright, null
where it leaves the choice to the reader, and indexed:N or theme:N when it
points into the legacy palette or the workbook theme instead. A theme colour
carries its tint as theme:[email protected]. The two indirect forms are not resolved
for you - an indexed colour needs the palette of the file it came from, and a
theme colour needs the workbook theme, which the reader keeps but does not
interpret.
For a block of cells, getRangeStyles(sheet, "A1:H40") answers { styles,
grid }: each distinct style once and a grid of indexes into them, which is
one crossing instead of a cellStyle per cell. cellStyleAt and
getRangeStylesAt take 1-based numbers instead of an address.
Formulas
A formula's text is here (getFormula), and so is the value the file was
saved with - get on a formula cell answers with the cached result. What is
not here is the engine that would recompute it: evaluate, recalculate and
recalculateFrom exist only in the full package.
That cached value is worth exactly what the application that wrote the file is
worth. A package with no xl/calcChain.xml was not last saved by Excel, and
its cached values may be stale.
Reading a package that expands a long way
Book.read(bytes, name, maxExpanded) takes a ceiling on how far a zipped
package may unpack, which is what stops a zip bomb. It defaults to 512 MB; a
real workbook can outgrow that - a 100 MB package unpacking to 560 MB is not
unusual - so raise it when you know where the file came from.
A callback as the fourth argument hears about each sheet as it is read:
{ stage, done, total, what, fraction }, with total null until the
workbook part says how many sheets there are.
What is not here
Writing, in any format - including painting a cell, writing a note, a link or a table. Recalculation. Editing the grid - inserting and removing rows, columns and sheets - which only makes sense when the result can be saved. Everything else the full package can do with a workbook once it is open - the reading side of it - is.
MIT.
