npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

large-excel

v0.1.0

Published

浏览器端大 Excel 读取和导出的 Rust Wasm 工具。

Readme

large-excel 使用说明

large-excel 是一个基于 Rust Wasm 的浏览器端 Excel 工具,支持读取 .xlsx、分块读取大 Excel、导出自定义 Excel,以及生成大体积 Excel 文件。

安装

pnpm add large-excel

如果是本地 .tgz 包测试:

pnpm add ./large-excel-0.1.0.tgz

基础初始化

使用任何方法前都需要先初始化 Wasm:

import init from "large-excel";

await init();

也可以按需导入方法:

import init, {
  get_workbook_info,
  read_preview,
  read_sheet,
  read_workbook,
  read_workbook_chunks,
  export_workbook,
  export_large_workbook,
} from "large-excel";

await init();

方法列表

get_workbook_info(bytes)

读取工作簿基础信息,包括工作表名称、行数、列数。

function get_workbook_info(bytes: Uint8Array): {
  sheets: Array<{
    name: string;
    rows: number;
    cols: number;
  }>;
};

示例:

const file = fileInput.files[0];
const bytes = new Uint8Array(await file.arrayBuffer());
const info = get_workbook_info(bytes);

console.log(info.sheets);

返回示例:

{
  sheets: [
    { name: "Sheet1", rows: 1000, cols: 12 },
    { name: "Sheet2", rows: 200, cols: 5 },
  ];
}

read_preview(bytes, preview_limit)

读取 Excel 前几行预览数据,适合上传后快速展示。

function read_preview(bytes: Uint8Array, preview_limit: number): {
  total: number;
  preview_count: number;
  rows: Array<{
    sheet_name: string;
    row_index: number;
    values: unknown[];
  }>;
};

示例:

const file = fileInput.files[0];
const bytes = new Uint8Array(await file.arrayBuffer());
const preview = read_preview(bytes, 20);

console.log("总行数", preview.total);
console.log("预览行", preview.rows);

read_sheet(bytes, sheet_name, start_row, row_limit)

读取指定工作表的指定行范围。

function read_sheet(
  bytes: Uint8Array,
  sheet_name: string,
  start_row: number,
  row_limit: number,
): {
  sheet_name: string;
  start_row: number;
  rows: unknown[][];
  total_rows: number;
  total_cols: number;
  has_more: boolean;
};

参数说明:

| 参数 | 说明 | | --- | --- | | bytes | Excel 文件字节 | | sheet_name | 工作表名称 | | start_row | 起始行,从 0 开始 | | row_limit | 读取行数,传 0 表示读取到末尾 |

示例:

const sheet = read_sheet(bytes, "Sheet1", 0, 100);

console.log(sheet.rows);
console.log(sheet.has_more);

read_workbook(bytes)

一次性读取整个 Excel 文件。

function read_workbook(bytes: Uint8Array): {
  sheets: Array<{
    sheet_name: string;
    start_row: number;
    rows: unknown[][];
    total_rows: number;
    total_cols: number;
    has_more: boolean;
  }>;
};

示例:

const file = fileInput.files[0];
const bytes = new Uint8Array(await file.arrayBuffer());
const workbook = read_workbook(bytes);

console.log(workbook.sheets);

注意:大 Excel 不建议使用该方法一次性读取,容易占用较多内存。大文件建议使用 read_workbook_chunks

read_workbook_chunks(bytes, chunk_size, callback)

分块读取 Excel,适合大文件。

function read_workbook_chunks(
  bytes: Uint8Array,
  chunk_size: number,
  callback: (chunk: {
    sheet_name: string;
    start_row: number;
    rows: unknown[][];
    loaded: number;
    total: number;
  }) => void,
): void;

示例:

const file = fileInput.files[0];
const bytes = new Uint8Array(await file.arrayBuffer());
const allRows = [];

read_workbook_chunks(bytes, 1000, (chunk) => {
  allRows.push(...chunk.rows);
  console.log(`已读取 ${chunk.loaded} 行`);
});

console.log("读取完成", allRows.length);

大文件推荐放到 Web Worker 中执行,避免阻塞页面。

Worker 示例:

import init, { read_workbook_chunks } from "large-excel";

let initPromise;

self.addEventListener("message", async (event) => {
  try {
    const { buffer, chunkSize = 1000 } = event.data;

    initPromise ||= init();
    await initPromise;

    const bytes = new Uint8Array(buffer);

    read_workbook_chunks(bytes, chunkSize, (chunk) => {
      self.postMessage({
        type: "chunk",
        payload: chunk,
      });
    });

    self.postMessage({ type: "done" });
  } catch (error) {
    self.postMessage({
      type: "error",
      message: error instanceof Error ? error.message : String(error),
    });
  }
});

主线程调用:

const worker = new Worker("./excel-worker.js", { type: "module" });

worker.addEventListener("message", (event) => {
  const { type, payload, message } = event.data;

  if (type === "chunk") {
    console.log("读取到分块", payload);
  }

  if (type === "done") {
    console.log("读取完成");
  }

  if (type === "error") {
    console.error(message);
  }
});

const buffer = await file.arrayBuffer();
worker.postMessage({ buffer, chunkSize: 1000 }, [buffer]);

export_workbook(sheets)

导出自定义 Excel 数据。

function export_workbook(
  sheets: Array<{
    name: string;
    headerBgColor?: string;
    rows: unknown[][];
  }>,
): Uint8Array;

参数说明:

| 字段 | 说明 | | --- | --- | | name | 工作表名称 | | headerBgColor | 可选,首行表头背景色,支持 #007aff007aff | | rows | 二维数组,第一行通常作为表头 |

示例:

import init, { export_workbook } from "large-excel";

await init();

const sheets = [
  {
    name: "订单数据",
    headerBgColor: "#007aff",
    rows: [
      ["订单号", "客户", "金额", "已付款"],
      ["SO-10001", "张三", 1299.5, true],
      ["SO-10002", "李四", 860, false],
    ],
  },
  {
    name: "汇总",
    headerBgColor: "#70AD47",
    rows: [
      ["指标", "值"],
      ["总订单", 2],
      ["总金额", 2159.5],
    ],
  },
];

const bytes = export_workbook(sheets);
downloadXlsx(bytes, "custom-export.xlsx");

下载方法:

function downloadXlsx(bytes, filename) {
  const blob = new Blob([bytes], {
    type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  });
  const url = URL.createObjectURL(blob);
  const link = document.createElement("a");
  link.href = url;
  link.download = filename;
  link.click();
  URL.revokeObjectURL(url);
}

export_large_workbook(row_count, col_count, chunk_size)

生成大体积 Excel 示例文件。

function export_large_workbook(
  row_count: number,
  col_count: number,
  chunk_size: number,
): Uint8Array;

参数说明:

| 参数 | 说明 | | --- | --- | | row_count | 生成行数 | | col_count | 生成列数 | | chunk_size | 内部生成分块大小 |

示例:

import init, { export_large_workbook } from "large-excel";

await init();

const bytes = export_large_workbook(300000, 20, 10000);
downloadXlsx(bytes, "large-export.xlsx");

大文件导出建议放到 Web Worker 中执行。

Worker 示例:

import init, { export_large_workbook } from "large-excel";

let initPromise;

self.addEventListener("message", async (event) => {
  try {
    const { rowCount, colCount, chunkSize } = event.data;

    initPromise ||= init();
    await initPromise;

    const bytes = export_large_workbook(rowCount, colCount, chunkSize);

    self.postMessage(
      {
        type: "done",
        bytes,
        size: bytes.byteLength,
      },
      [bytes.buffer],
    );
  } catch (error) {
    self.postMessage({
      type: "error",
      message: error instanceof Error ? error.message : String(error),
    });
  }
});

主线程调用:

const worker = new Worker("./export-worker.js", { type: "module" });

worker.addEventListener("message", (event) => {
  const { type, bytes, size, message } = event.data;

  if (type === "done") {
    downloadXlsx(bytes, "large-export.xlsx");
    console.log("导出完成", size);
  }

  if (type === "error") {
    console.error(message);
  }
});

worker.postMessage({
  rowCount: 300000,
  colCount: 20,
  chunkSize: 10000,
});

单元格值类型

导入和导出时支持以下基础类型:

type CellValue = string | number | boolean | null;

实际导出时:

  • string 会写入文本单元格
  • number 会写入数字单元格
  • boolean 会写入布尔单元格
  • 空值会写入空单元格

大文件建议

读取大 Excel

推荐:

read_workbook_chunks(bytes, 1000, callback);

并放入 Web Worker 执行。

不推荐:

read_workbook(bytes);

因为它会一次性把所有 sheet 和 rows 放入内存。

导出大 Excel

推荐把 export_large_workbook 放入 Web Worker:

worker.postMessage({
  rowCount: 300000,
  colCount: 20,
  chunkSize: 10000,
});

这样可以避免主线程卡顿。

发布相关命令

项目内已配置 npm 发布脚本:

pnpm build

构建 wasm 并更新 pkg/package.json

pnpm pack:pkg

构建并生成本地 npm 包。

pnpm publish:pkg:dry-run

模拟发布。

pnpm publish:pkg

正式发布到 npm。

正式发布前需要先登录 npm:

npm login