Baike.dev
All toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
H

hucre

> 编程语言
Open source

Zero-dependency spreadsheet engine. Read & write XLSX, CSV, ODS. Pure TypeScript, works everywhere.

1.5K stars0 likes0 views
WebsiteGitHub

About

Zero-dependency spreadsheet engine. Read & write XLSX, CSV, ODS. Pure TypeScript, works everywhere.




hucre

Zero-dependency spreadsheet engine.
Read & write XLSX, CSV, ODS, JSON, NDJSON, XML. Schema validation, streaming, round-trip preservation. Pure TypeScript, works everywhere.

## Quick Start ```sh npm install hucre ``` ```ts import { readXlsx, writeXlsx } from "hucre" // Read an XLSX file const workbook = await readXlsx(buffer) console.log(workbook.sheets[0].rows) // Write an XLSX file const xlsx = await writeXlsx({ sheets: [ { name: "Products", columns: [ { header: "Name", key: "name", width: 25 }, { header: "Price", key: "price", width: 12, numFmt: "$#,##0.00" }, { header: "Stock", key: "stock", width: 10 }, ], data: [ { name: "Widget", price: 9.99, stock: 142 }, { name: "Gadget", price: 24.5, stock: 87 }, ], }, ], }) ``` ## Tree Shaking Import only what you need: ```ts import { readXlsx, writeXlsx } from "hucre/xlsx" // XLSX only import { parseCsv, writeCsv } from "hucre/csv" // CSV only (~2 KB gzipped) import { readOds, writeOds } from "hucre/ods" // ODS only import { parseJson, writeNdjson } from "hucre/json" // JSON / NDJSON import { readXml, writeXml } from "hucre/xml" // Tabular XML ``` ## Why hucre? ### vs JavaScript / TypeScript Libraries | | hucre | SheetJS CE | ExcelJS | xlsx-js-style | | ----------------------- | -------------------- | ------------- | --------- | ------------- | | **Dependencies** | 0 | 0\* | 9 | 0\* | | **Bundle (gzip)** | 4–129 KB† | ~300 KB | ~500 KB | ~300 KB | | **ESM native** | Yes | Partial | No (CJS) | Partial | | **TypeScript** | Native | Bolted-on | Bolted-on | Bolted-on | | **Edge runtime** | Yes | No | No | No | | **CSP compliant** | Yes | Yes | No (eval) | Yes | | **npm published** | Yes | No (CDN only) | Stale | Yes | | **Read + Write** | Yes | Yes (Pro $) | Yes | Yes | | **Styling** | Yes | No (Pro $) | Yes | Yes | | **Cond. formatting** | 13 types‡ | No (Pro $) | Yes | No | | **Stream read + write** | Yes | CSV only | Yes | CSV only | | **ODS support** | Yes§ | Yes | No | Yes | | **Round-trip** | Yes | Partial | Partial | Partial | | **Sparklines** | Yes | No | No | No | | **Tables** | Yes | Yes | Yes | Yes | | **Images** | Yes | No (Pro $) | Yes | No | \* SheetJS removed itself from npm; must install from CDN tarball. † Depends on what you import — hucre is fully tree-shakeable, so there is no single number. Minified + gzipped, bundled with rolldown against `dist/`: `{ parseCsv, writeCsv }` from `hucre/csv` = **3.7 KB**, `{ readXlsx }` from `hucre/xlsx` = **34 KB**, `{ readXlsx, writeXlsx }` = **68 KB**, the entire library (`export * from "hucre"`) = **129 KB**. These four are measured by `pnpm size` and pinned in `scripts/size-budget.json`, so CI fails when one grows past its budget. They are in the README because they had already drifted once — the previous figures (2.3 / 32 / 64 / 114 KB) were true when written and were enforced by nothing. ‡ `cellIs`, `expression`, `colorScale`, `dataBar`, `iconSet`, `containsText`, `notContainsText`, `beginsWith`, `endsWith`, `containsBlanks`, `notContainsBlanks`, `duplicateValues`, `uniqueValues` — read and written. `top10` and `aboveAverage` round-trip in their default form only (the writer emits no `rank` / `percent` / `bottom` or `aboveAverage` / `equalAverage` / `stdDev` attributes), and `timePeriod` rules are dropped on read. § Values, formulas and merges round-trip in full; cell styling covers six facets (bold, italic, size, font colour, background colour, number format). Borders, alignment, column widths, freeze panes, validation, named ranges, images and page setup are not modelled in either direction, so ODS → ODS is lossless while XLSX → ODS drops them. See [What ODS carries](#what-ods-carries). ### vs Libraries in Other Languages | | hucre (TS) | openpyxl (Py) | XlsxWriter (Py) | rust_xlsxwriter | Apache POI (Java) | | --------------------- | ------------------- | ------------- | --------------- | --------------- | ----------------- | | **Read XLSX** | Yes | Yes | No | No | Yes | | **Write XLSX** | Yes | Yes | Yes | Yes | Yes | | **Streaming** | Read+Write | Read+Write | const_memory | const_memory | SXSSF (write) | | **Charts** | Round-trip | 15+ types | 9 types | 12+ types | Limited | | **Pivot tables** | Read + Write (skel) | Read-only | No | No | Limited | | **Cond. formatting** | 13 types (see ‡) | Yes | Yes | Yes | Yes | | **Sparklines** | Yes | Yes | Yes | Yes | No | | **Formula eval** | No | No | No | No | Yes | | **Multi-format** | XLSX/ODS/CSV | XLSX only | XLSX only | XLSX only | XLS/XLSX | | **Zero dependencies** | Yes | lxml optional | No | Yes | No | "Read + Write (skel)" for pivot tables: hucre writes the pivot cache, layout and relationships, but not the pre-computed value cells — Excel fills those in on first open. See [Pivot Tables](#pivot-tables). ## Features ### Reading ```ts import { readXlsx } from "hucre/xlsx" const wb = await readXlsx(uint8Array, { sheets: [0, "Products"], // Filter sheets by index or name readStyles: true, // Parse cell styles dateSystem: "auto", // Auto-detect 1900/1904 }) for (const sheet of wb.sheets) { console.log(sheet.name) // "Products" console.log(sheet.rows) // CellValue[][] console.log(sheet.merges) // MergeRange[] } ``` `sheets` also accepts a predicate that runs against lightweight metadata **before** each worksheet body is parsed — useful for visibility-based selection without paying the I/O cost of the full read: ```ts const wb = await readXlsx(buf, { sheets: (info) => !info.hidden && !info.veryHidden, }) // info: { name, index, hidden?, veryHidden? } ``` Supported cell types: strings, numbers, booleans, dates, formulas, rich text, errors, inline strings. ### Writing ``` … ``` A row entry may be a value or a cell object, so styling one cell does not mean naming its position again in a parallel map: ```ts await writeXlsx({ sheets: [ { name: "Report", rows: [ [{ value: "Region", style: { font: { bold: true } } }, "Revenue"], ["EU", { value: 12500, style: { numFmt: "$#,##0.00" } }], ["Total", { formula: "SUM(B2:B2)" }], ], }, ], }) ``` Anything a cell carries works there — `style`, `formula`, `richText`, `hyperlink`, `checkbox`. `cells` still takes a `"row,col"` map, and wins where both describe the same position. Features: cell styles, auto column widths, merged cells, freeze/split panes, auto-filter (with per-column value filters — ``; custom/dynamic/colour criteria are not emitted), data validation, hyperlinks, images (PNG/JPEG/GIF/SVG/WebP), comments, tables, conditional formatting (all 15 rule types, with their dxf styles), named ranges, print settings, page breaks, sheet protection, workbook protection, rich text, shared/array/dynamic formulas, sparklines, textboxes, background images, number formats, hidden sheets, Excel 2024 native checkboxes, HTML/Markdown/JSON/TSV export, template engine. ### Auto Column Width ```ts const buffer = await writeXlsx({ sheets: [ { name: "Products", columns: [ { header: "Name", key: "name", autoWidth: true }, { header: "Price", key: "price", autoWidth: true, numFmt: "$#,##0.00" }, { header: "SKU", key: "sku", autoWidth: true }, ], data: products, }, ], }) ``` Calculates optimal column widths from cell content — font-aware, handles CJK double-width characters, number formats, min/max constraints. ### Data Validation ``` … ``` ### Hyperlinks ```ts const buffer = await writeXlsx({ sheets: [ { name: "Links", rows: [["Visit Google", "Go to Sheet2"]], cells: new Map([ [ "0,0", { value: "Visit Google", type: "string", hyperlink: { target: "https://google.com", tooltip: "Open Google" }, }, ], [ "0,1", { value: "Go to Sheet2", type: "string", hyperlink: { target: "", location: "Sheet2!A1" }, }, ], ]), }, ], }) ``` For tabular reports, put links **inline in `data` rows** instead of a parallel `cells` map — keyed by the column's `key`. Use the `link()` helper (or a plain `{ text, hyperlink, tooltip? }` object). A `#`-prefixed target is treated as an internal reference (`#Sheet2!A1`). ```ts import { writeXlsx, link } from "hucre/xlsx" await writeXlsx({ sheets: [ { name: "Summary", columns: [ { header: "Link", key: "link" }, { header: "ID", key: "id" }, ], data: [ { link: link("Open", "https://example.com/items/abc-123"), id: "abc-123" }, { link: { text: "Open", hyperlink: "https://example.com/items/def-456" }, id: "def-456" }, ], }, ], }) ``` ### Streaming Process large files row-by-row without loading everything into memory: ``` … ``` #### Across the formats ``` … ``` | | whole read | whole write | stream read | stream write | incremental writer | | ------ | :--------: | :---------: | :---------: | :----------: | :----------------: | | XLSX | ✔ | ✔ | ✔ | ✔ (multi) | ✔ | | CSV | ✔ | ✔ | ✔ | ✔ | ✔ | | NDJSON | ✔ | ✔ | ✔ | ✔ | ✔ | | ODS | ✔ | ✔ | ✔ | ✔ | ✔ | | XML | ✔ | ✔ | ✔ | ✔ | — | `writeOdsStream` carries **values, not formatting**, and that follows from the format: ODF puts `` before the body, so a style first seen on row 900,000 has nowhere to be declared — the same shape as the shared-string table, which the XLSX streaming writer answers with inline strings and ODF has no equivalent for. Column widths and a header row are carried, because `columns` is known before the first row. `writeOds` remains the path for a document that needs styling. `streamXmlRows` differs from `readXml` in one way that follows from streaming rather than from a choice: **it yields the keys each row actually has.** `readXml` pads every row to the union of all headers, which needs the whole document —

GitHub Issues· 7 open

View all on GitHub
  • #567

    Every `xdr:colOff` and `xdr:rowOff` the drawing writer emits is a hardcoded `"0"`, so two images cannot sit side by side in one cell

    Updated Aug 17, 2026
  • #566

    ODF validator reports "All parts valid." when parts are missing, the ZIP can't be read, or the manifest check is skipped

    Updated Aug 14, 2026
  • #565

    The issue of Hucre reading cells with embedded images and auto-filtering

    Updated Aug 14, 2026
  • #464

    Test against files hucre did not write

    Updated Aug 13, 2026
  • #472

    Every writer builds the document as a tree of strings

    Updated Aug 13, 2026
  • #474

    Smaller consistency items left from the audit

    Updated Aug 11, 2026

Highlights

  • •TypeScript
  • •csv
  • •csv-parser
  • •esm
  • •excel

> Tags

TypeScriptcsvcsv-parseresmexcel

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言