×

hucre:零依赖的 TypeScript 电子表格引擎

独孤求败 独孤求败 发表于2026-09-03 12:58:53 浏览26 评论0

抢沙发发表评论

hucre 是一个零依赖的 TypeScript 电子表格引擎,支持读写多种电子表格格式。

核心特点

✅ 零依赖:没有任何第三方依赖

✅ 多格式支持:XLSX、CSV、ODS、JSON、NDJSON、XML

✅ 旧格式支持:支持读取 XLS(Excel 97-2003)和 XLSB(二进制格式)

✅ 纯 TypeScript:原生 TypeScript 编写,类型安全

✅ Tree Shaking:按需导入,减小打包体积

✅ 流式处理:支持大文件的流式读写

✅ 跨平台:Node.js、Deno、Bun、浏览器、Edge Runtime

✅ 安全:不使用 eval,符合 CSP 要求

 

快速开始

安装

Bash                  npm install hucre

基本读写

TypeScript                  import { readXlsx, writeXlsx } from "hucre"                  // 读取 XLSX 文件                  const workbook = await readXlsx(buffer)                  console.log(workbook.sheets[0].rows)                  // 写入 XLSX 文件                  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:按需导入

只导入你需要的模块:

TypeScript                  // 只使用 XLSX                  import { readXlsx, writeXlsx } from "hucre/xlsx"                  // 只使用 CSV(仅 ~2 KB gzipped)                  import { parseCsv, writeCsv } from "hucre/csv"                  // 只使用 ODS                  import { readOds, writeOds } from "hucre/ods"                  // 只使用 JSON / NDJSON                  import { parseJson, writeNdjson } from "hucre/json"                  // 只使用 XML                  import { readXml, writeXml } from "hucre/xml"

包体积对比

导入内容

Gzipped 体积

CSV 读写

~3.7 KB

XLSX 读取

~34 KB

XLSX 读写

~68 KB

完整库

~129 KB

 

核心功能详解

1. 读取功能

支持多种数据类型:

TypeScript                  import { readXlsx } from "hucre/xlsx"                  const wb = await readXlsx(uint8Array, {                    sheets: [0, "Products"], // 按索引或名称过滤工作表                    readStyles: true,        // 解析单元格样式                    dateSystem: "auto",      // 自动检测日期系统(1900/1904)                  })                  for (const sheet of wb.sheets) {                    console.log(sheet.name)   // 工作表名称                    console.log(sheet.rows)   // CellValue[][]                    console.log(sheet.merges) // MergeRange[]                  }

2. 写入功能

基本写入

TypeScript                  import { writeXlsx } from "hucre/xlsx"                  const buffer = await writeXlsx({                    sheets: [                      {                        name: "Report",                        columns: [                          { header: "Date", key: "date", width: 15, numFmt: "yyyy-mm-dd" },                          { header: "Revenue", key: "revenue", width: 15, numFmt: "$#,##0.00" },                          { header: "Active", key: "active", width: 10 },                        ],                        data: [                          { date: new Date("2026-01-15"), revenue: 12500, active: true },                          { date: new Date("2026-01-16"), revenue: 8900, active: false },                        ],                        freezePane: { rows: 1 },                        autoFilter: { range: "A1:C3" },                      },                    ],                    defaultFont: { name: "Calibri", size: 11 },                  })

单元格级样式

TypeScript                  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)" }],                        ],                      },                    ],                  })

3. 自动列宽

根据内容自动计算最优列宽:

TypeScript                  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,                      },                    ],                  })

4. 数据验证

TypeScript                  const buffer = await writeXlsx({                    sheets: [                      {                        name: "Sheet1",                        rows: [                          ["Status", "Quantity"],                          ["active", 10],                        ],                        dataValidations: [                          {                            type: "list",                            values: ["active", "inactive", "draft"],                            range: "A2:A100",                            showErrorMessage: true,                            errorTitle: "Invalid",                            errorMessage: "Pick from the list",                          },                          {                            type: "whole",                            operator: "between",                            formula1: "0",                            formula2: "1000",                            range: "B2:B100",                          },                        ],                      },                    ],                  })

5. 超链接

TypeScript                  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" },                        ],                      },                    ],                  })

6. 流式处理:处理大文件

hucre 提供了完整的流式 API,可以处理超大文件而不占用过多内存。

流式读取

TypeScript                  import { streamXlsxRows } from "hucre/xlsx"                  // 逐行读取,不一次性加载整个文件                  for await (const row of streamXlsxRows(buffer)) {                    console.log(row.index, row.values)                  }                  // 从网络流读取                  const res = await fetch("https://example.com/huge.xlsx")                  for await (const row of streamXlsxRows(res.body!)) {                    console.log(row.index, row.values)                  }                  // 限制读取行数(预览/采样)                  for await (const row of streamXlsxRows(buffer, { maxRows: 100 })) {                    console.log(row.index, row.values)                  }                  // 读取指定范围                  for await (const row of streamXlsxRows(buffer, { range: "B2:D1000" })) {                    console.log(row.values) // 只包含 B/C/D 列                  }

流式写入

TypeScript                  import { writeXlsxStream } from "hucre/xlsx"                  // 生成器函数提供数据源                  function* rows() {                    for (let i = 0; i < 5_000_000; i++) yield [i + 1, Math.random()]                  }                  // 流式写入,内存占用恒定                  return new Response(                    writeXlsxStream(                      rows(),                      {                        name: "BigData",                        columns: [{ header: "ID" }, { header: "Value" }],                        freezePane: { rows: 1 },                      },                    ),                    {                      headers: {                        "content-type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",                      },                    },                  )

性能对比

行数

writeXlsxStream 内存

XlsxStreamWriter 内存

300,000

41 MB

328 MB

1,000,000

67 MB

1,037 MB

3,000,000

70 MB

不可行

7. 密码保护

支持读写加密的 XLSX 文件(ECMA-376 Agile 加密):

TypeScript                  import { writeXlsx, readXlsx, EncryptedFileError, DecryptionError } from "hucre"                  // 写入加密文件                  const encrypted = await writeXlsx({                    sheets: [{ name: "Secret", rows: [["pin", 1234]] }],                    encryption: { password: "hunter2" },                  })                  // 读取加密文件                  const wb = await readXlsx(encrypted, { password: "hunter2" })                  // 错误处理                  try {                    await readXlsx(encrypted)                  } catch (e) {                    if (e instanceof EncryptedFileError) console.log("需要密码")                  }

8. 旧格式支持

XLSB(二进制 Excel)

读取 .xlsb 文件,比 .xlsx 更小更快:

TypeScript                  import { readXlsb } from "hucre"                  const wb = await readXlsb(bytes)

XLS(Excel 97-2003)

读取传统的 .xls 文件:

TypeScript                  import { readXls } from "hucre"                  const wb = await readXls(bytes)

注意:旧格式仅支持读取,支持单元格值和合并单元格。

9. 往返保留(Round-trip Preservation)

打开、修改、保存文件,而不丢失图表、宏等 hucre 不原生处理的功能:

TypeScript                  import { openXlsx, saveXlsx } from "hucre/xlsx"                  const workbook = await openXlsx(buffer)                  workbook.sheets[0].rows[0][0] = "Updated!"                  const output = await saveXlsx(workbook) // 图表、VBA、主题都被保留

重要区别

readXlsx / writeXlsx:创作路径,从模型重建工作簿

openXlsx / saveXlsx:编辑路径,保留 hucre 不建模的部分

10. 高级功能

数据透视表

TypeScript                  import { writeXlsx } from "hucre"                  const xlsx = await writeXlsx({                    sheets: [                      {                        name: "Data",                        rows: [                          ["Region", "Product", "Revenue"],                          ["EU", "A", 100],                          ["EU", "B", 50],                          ["US", "A", 200],                          ["US", "B", 75],                        ],                      },                      {                        name: "Pivot",                        pivotTables: [                          {                            name: "SalesPivot",                            sourceSheet: "Data",                            rows: ["Region"],                            columns: ["Product"],                            values: [{ field: "Revenue", function: "sum" }],                          },                        ],                      },                    ],                  })

图表

TypeScript                  import { addChart, writeXlsx } from "hucre"                  const dashboard = {                    name: "Dashboard",                    rows: [                      ["Quarter", "Revenue", "Forecast"],                      ["Q1", 12000, 11500],                      ["Q2", 15500, 15000],                      ["Q3", 14000, 14500],                      ["Q4", 17800, 17200],                    ],                  }                  addChart(dashboard, {                    type: "column",                    title: "Quarterly Revenue",                    series: [                      { name: "Revenue", values: "B2:B5", categories: "A2:A5", color: "1F77B4" },                      { name: "Forecast", values: "C2:C5", categories: "A2:A5", color: "FF7F0E" },                    ],                    axes: {                      x: { title: "Quarter" },                      y: { title: "Revenue (USD)", numberFormat: { formatCode: "$#,##0" } },                    },                    legend: "bottom",                    dataLabels: { showValue: true, position: "outEnd" },                  })                  await writeXlsx({ sheets: [dashboard] })

  

与其他库对比

vs JavaScript/TypeScript 库

特性

hucre

SheetJS CE

ExcelJS

xlsx-js-style

依赖数量

0

0*

9

0*

包体积(gzip)

4-129 KB†

~300 KB

~500 KB

~300 KB

原生 ESM

部分

❌(CJS)

部分

TypeScript

原生

后加

后加

后加

Edge Runtime

CSP 兼容

❌(eval)

npm 发布

❌(仅 CDN)

停滞

读写支持

✅(付费版 $)

样式

❌(付费版 $)

条件格式

13 种

❌(付费版 $)

流式读写

仅 CSV

仅 CSV

ODS 支持

✅§

往返保留

部分

部分

部分

迷你图

* SheetJS 已从 npm 下架,必须从 CDN 安装          † 取决于导入内容,完全可 Tree Shake          § ODS 支持值、公式、合并和六种样式属性

vs 其他语言库

特性

hucre (TS)

openpyxl (Py)

XlsxWriter (Py)

rust_xlsxwriter

Apache POI (Java)

读取 XLSX

写入 XLSX

流式处理

读写

读写

const_memory

const_memory

SXSSF(写)

图表

往返保留

15+ 种

9 种

12+ 种

有限

数据透视表

读写(骨架)

只读

有限

条件格式

13 种

迷你图

公式计算

多格式

XLSX/ODS/CSV

仅 XLSX

仅 XLSX

仅 XLSX

XLS/XLSX

零依赖

lxml 可选



群贤毕至

访客