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 | 可选,首行表头背景色,支持 #007aff 或 007aff |
| 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