在管理项目计划、财务报表等行列较多的数据时,常常需要对部分行进行分组(Group / Outline),把它们折叠成一层层的结构,从而只查看汇总行或某些阶段的内容。当结构不再需要时,也可以随时取消分组,恢复行数据的平铺显示。Spire.XLS for JavaScript 基于 WebAssembly 在浏览器端直接完成此操作,通过虚拟文件系统(VFS)管理输入输出文件,无需后端服务支持。
本文介绍两个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.XLS for JavaScript。以下示例默认已安装 Spire.XLS 并完成 WebAssembly 模块初始化。
创建多级(嵌套)分组
多级分组由"外层分组 + 内层分组"组成。例如在一份项目计划中,把整个执行阶段(若干行)作为一级分组,再把其中每个子阶段的明细行作为二级分组。创建时,应先对外层的大范围调用 GroupByRows(),再对嵌套在内的小范围调用 GroupByRows(),这样 Excel 才能生成不同层级的折叠按钮。具体操作步骤如下:
- 创建一个
Workbook对象并获取第一个工作表。 - 添加一个命名样式并设置字体(用于标题等单元格)。
- 通过
Worksheet.PageSetup.IsSummaryRowBelow = false让汇总行显示在明细行的上方。 - 将示例数据写入单元格。
- 先对外层行区域(第 2-9 行)调用
GroupByRows(),再对嵌套的内层行区域(第 4-5 行、第 8-9 行)分别调用GroupByRows()。 - 通过
Workbook.SaveToFile()方法保存工作簿。
下面是一个完整的代码示例,展示了在 React 中为工作表创建两级(嵌套)行分组:
function App() {
const createNestedGroup = async () => {
// 获取 Spire.XLS WASM 模块
const xlsModule = window.wasmModule?.spirexls;
// 检查模块是否就绪
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// 将字体载入 VFS,用于文本度量
await window.spire.FetchFileToVFS('simsun.ttc', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
// 创建一个新的工作簿并获取第一个工作表
const workbook = new xlsModule.Workbook();
const sheet = workbook.Worksheets.get(0);
// 添加一个命名样式,用于标题行
const style = workbook.Styles.Add("style");
style.Font.Color = xlsModule.Color.get_CadetBlue();
style.Font.IsBold = true;
// 让汇总行显示在明细行的上方
sheet.PageSetup.IsSummaryRowBelow = false;
// 写入示例数据
sheet.Range.get("A1").Value = "项目 X 实施计划";
sheet.Range.get("A1").CellStyleName = style.Name;
sheet.Range.get("A3").Value = "筹备";
sheet.Range.get("A3").CellStyleName = style.Name;
sheet.Range.get("A4").Value = "任务 1";
sheet.Range.get("A5").Value = "任务 2";
sheet.Range.get("A4:A5").BorderAround(xlsModule.LineStyleType.Thin);
sheet.Range.get("A4:A5").BorderInside(xlsModule.LineStyleType.Thin);
sheet.Range.get("A7").Value = "上线";
sheet.Range.get("A7").CellStyleName = style.Name;
sheet.Range.get("A8").Value = "任务 1";
sheet.Range.get("A9").Value = "任务 2";
sheet.Range.get("A8:A9").BorderAround(xlsModule.LineStyleType.Thin);
sheet.Range.get("A8:A9").BorderInside(xlsModule.LineStyleType.Thin);
// 先对外层行分组,再对嵌套的内层行分组,形成多级分组
sheet.GroupByRows(2, 9, false);
sheet.GroupByRows(4, 5, false);
sheet.GroupByRows(8, 9, false);
// 保存文档
const outputFileName = 'MultiLevelGroup.xlsx';
workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });
// 释放资源
workbook.Dispose();
// 从 VFS 读取转换后的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Create Nested Group</h1>
<button onClick={createNestedGroup}>
Start
</button>
</div>
);
}
export default App;
创建多级分组的效果

取消(删除)多级分组
如果工作簿中已经存在多层分组,需要把其中某个外层"大分组"或内层"小分组"取消时,可以直接加载文件后对相应范围调用 Worksheet.UngroupByRows() 方法。分组只是影响行的折叠显示,取消分组不会删除任何单元格内容;当外层大分组被取消后,原本嵌套在内的内层小分组会保留为独立的单级分组,可再单独取消。具体操作步骤如下:
- 创建一个
Workbook对象,并通过Workbook.LoadFromFile()方法加载已含多层分组的工作簿。 - 通过
Workbook.Worksheets.get()方法获取该工作表。 - 对外层行区域(第 2-9 行)调用
UngroupByRows(),取消外层大分组。 - 对内层行区域(第 4-5 行)调用
UngroupByRows(),取消内层小分组。 - 通过
Workbook.SaveToFile()方法保存工作簿。
下面是一个完整的代码示例,展示了在 React 中加载已分组的 Excel 文件,并取消大分组与小分组的操作:
function App() {
const ungroupRows = async () => {
// 获取 Spire.XLS WASM 模块
const xlsModule = window.wasmModule?.spirexls;
// 检查模块是否就绪
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// 将字体载入 VFS,用于文本度量
await window.spire.FetchFileToVFS('simsun.ttc', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
// 加载已有多层分组的 Excel 文件
const inputFileName = 'MultiLevelGroup.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
// 创建 Workbook 对象并加载该工作簿
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: inputFileName });
// 获取第一个工作表
const sheet = workbook.Worksheets.get(0);
// 取消外层的大分组(第 2-9 行)
sheet.UngroupByRows(2, 9);
// 取消内层的小分组(第 4-5 行)
sheet.UngroupByRows(4, 5);
// 保存文档
const outputFileName = 'UngroupRows_output.xlsx';
workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });
// 释放资源
workbook.Dispose();
// 从 VFS 读取转换后的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Ungroup Rows</h1>
<button onClick={ungroupRows}>
Start
</button>
</div>
);
}
export default App;
取消多级分组的效果

常见问题
为什么多次调用 GroupByRows 后没有形成多级分组
原因:多级分组要求内层分组的范围必须完全包含在外层分组范围内。如果两次分组的范围互不包含,Excel 会将其视为两个平级分组,而不是嵌套的多级分组。
解决:先对外层的大范围调用 GroupByRows(),再对其中嵌套的小范围调用 GroupByRows(),例如先 GroupByRows(2, 9, false),再 GroupByRows(4, 5, false)。
如何让分组默认折叠(或保持展开)?
原因:GroupByRows(startRow, endRow, isCollapsed) 的第三个布尔参数决定分组创建后是否默认折叠明细。true 表示默认折叠,false 表示默认展开(本文示例使用 false)。打开保存后的文件时即按该状态显示。
解决:需要默认折叠时把第三参数改为 true,例如 sheet.GroupByRows(4, 5, true);如需在运行时折叠或展开,可对分组范围调用 CollapseGroup() / ExpandGroup()。
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。









