高级特性
多工作表
sheets 是数组,一次调用即可生成多页工作簿:
await exportExcel({
filename: "department-report",
sheets: [
{ name: "销售", columns: [...], data: salesData },
{ name: "人员", columns: [...], data: staffData },
],
});工作表名需满足 ECMA-376 约束:非空、不超过 31 字符、不含 : \ / ? * [ ]、不得以单引号开头或结尾,且在 sheets 内不得重名——重名与违规一样走统一报错,而不会生成损坏文件或被静默改名。违反时不会生成损坏文件,也不会以异常形式抛出——输入在任何导出路由(及兜底链)运行前就被前置校验拦截,调用直接以 { success: false, error } 返回(错误信息明确)。
冻结行
freezeRows: 1 冻结表头(映射到 frozenPane),浏览大表时表头始终可见。多级表头建议 freezeRows >= 表头行数,让所有表头行都保持可见。
多级表头
列用 children 组成树形结构,即可生成多行表头;分组表头格会自动合并(跨其全部叶子列),叶子列表头自动纵向跨满剩余表头行——无需手工计算合并范围。
await exportExcel({
filename: "月度销售",
sheets: [
{
name: "销售",
freezeRows: 3,
columns: [
{ prop: "product", label: "产品" },
{
label: "收入情况",
children: [
{
label: "本月",
children: [
{ prop: "m_qty", label: "数量" },
{ prop: "m_amt", label: "金额" },
],
},
{
label: "本年累计",
children: [
{ prop: "y_qty", label: "数量" },
{ prop: "y_amt", label: "金额" },
],
},
],
},
],
data: [{ product: "A", m_qty: 1, m_amt: 2, y_qty: 3, y_amt: 4 }],
},
],
});生成 3 行表头:
| 行 | A | B | C | D | E |
|---|---|---|---|---|---|
| 1 | 产品 | 收入情况(合并 B–E) | |||
| 2 | 本月(合并 B–C) | 本年累计(合并 D–E) | |||
| 3 | 数量 | 金额 | 数量 | 金额 |
规则:
- 叶子列(无
children)必须有prop(或旧名key);分组列可省略,只贡献表头; width/style/format只对叶子列生效;- 分组表头样式用该列的
headerStyle,叶子表头样式同理(未设置时回退到表级headerStyle); - 任意路径(main / worker / stream,含流式兜底)都支持多级表头,stream 与兜底路径同样保留合并(样式除外)。
在线体验:下方是 sales-grouped 数据集的 mock 预览(两级分组表头,与导出文件的表头结构一致);到 play 演示站 的演示面板选择 sales-grouped 数据集即可导出带多级表头与数据区合并的真实文件。
| 订单信息 | 商品销售 | 金额 | 状态 | |||||
|---|---|---|---|---|---|---|---|---|
| 订单号 | 日期 | 区域 | 商品 | 渠道 | 数量 | 单价 | 金额 | |
| ORD-000001 | 2026-07-21 | 华东 | USB-C 扩展坞 | 线上 | 18 | 789.44 | 14209.92 | pending |
| ORD-000002 | 2026-07-28 | 西南 | 显示器支架 | 线上 | 5 | 1127.47 | 5637.35 | paid |
| ORD-000003 | 2026-07-15 | 东北 | 机械键盘 | 线下 | 1 | 898.61 | 898.61 | paid |
| ORD-000004 | 2026-07-25 | 华南 | 机械键盘 | 线上 | 4 | 360.06 | 1440.24 | refunded |
| ORD-000005 | 2026-07-14 | 华东 | 机械键盘 | 线下 | 7 | 643.8 | 4506.6 | paid |
合并单元格
{
name: "库存汇总",
columns: [...],
data: [...],
merges: [
{ row: 0, col: 0, rowspan: 1, colspan: 2 }, // 第一行数据跨两列
],
}MergeRange 相对数据区定位:row / col 从 0 开始(row 0 = 第一条数据行),rowspan / colspan 为跨度。
合并范围在所有路径上按同一规则校验:取值必须为整数,row/col ≥ 0,rowspan/colspan ≥ 1,范围不得超出数据区(叶子列数 / 数据行数),各合并范围之间不得重叠。非法输入最终以 { success: false, error } 返回并指明问题项——绝不生成 Excel 判定损坏的文件。
自动筛选
autoFilter: true 在最后一行表头添加筛选下拉,范围覆盖该行及其下全部数据行(Excel 的筛选语义)。
进度与阶段回调
await exportExcel({
...,
onProgress: (progress) => {
// 0 → 1;首尾 0 与 1 由 exportExcel 在所有路径(含流式兜底)各上报一次;
// 分段进度仅 stream 路径有(每 1000 行上报一次)
bar.style.width = `${progress * 100}%`;
},
onPhase: (phase, durationMs) => {
// phase: "init" | "build" | "download",严格按序执行
console.log(`${phase} took ${durationMs.toFixed(1)}ms`);
},
});各阶段语义:
| 阶段 | 说明 |
|---|---|
init | WASM 初始化;main 路径每次导出上报(已加载约 0ms);Node 主线程的 stream 路径不加载 WASM,但会上报一次 0ms 以保持阶段序列一致;Worker + Workbook 仅 Worker 初始化时上报;Worker + stream 不上报;流式兜底上报一次 0ms |
build | 工作簿构建(按实际构建次数报告,含兜底重试——失败后走流式兜底会再报告一次) |
download | 浏览器触发下载(download: false 时不报告;Node 下无此阶段) |
onPhase只反映各阶段耗时,不影响ExportResult.duration(主线程路由为整次导出总耗时;worker 路由的 duration 在主线程从调用exportInWorker起表,含 postMessage 前的序列化与 Worker 往返,直到 Blob 构造完成,因此比纯 Worker 内构建耗时更宽)。
基于这对回调开箱可用的全屏遮罩见进度遮罩。
关闭自动下载
const result = await exportExcel({ ..., download: false });
// result.blob 可直接使用导出结果
interface ExportResult {
success: boolean;
blob?: Blob;
engine?: "modern-xlsx"; // 实际使用的引擎
mode?: ExportMode; // 实际使用的模式
duration?: number; // 完整导出耗时 ms
rowCount?: number;
error?: Error;
}建议在失败分支展示 result.error 并提示用户重试;导出成功但 result.error 非空时提示已降级(无样式流式导出)。