表格里真正的分隔线不是空白,而是边框:财务报表用粗细不同的框线区分表头与合计行,导出给下游系统的数据又需要把框线一并去掉,只留干净的数据区。这些操作靠手工点选「设置单元格格式」逐个完成,工作量大且难以复用。Spire.XLS for JavaScript 基于 WebAssembly 在浏览器端直接完成此操作,通过虚拟文件系统(VFS)管理输入输出文件,无需后端服务支持。
本文主要介绍以下四个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.XLS for JavaScript。以下示例默认已安装 Spire.XLS 并完成 WebAssembly 模块初始化。
为选定的单元格或单元格区域添加边框
拿到一份没有框线的数据表时,最直接的做法是靠 BorderAround 与 BorderInside 两个方法把框线补上:前者负责外框,后者负责区域内部的网格线。用它们既能给整片数据区域一次框好,也能把某个单元格单独框出来,例如把表头所在的单元格加粗加重,让它从一整片同样的框线里跳出来。
具体操作步骤如下:
- 用
Range.get按地址取到需要加边框的单元格区域 - 调用
BorderAround为区域加上外框,线型取值来自LineStyleType枚举 - 调用
BorderInside为区域内部补上单元格之间的分隔线 - 单独取到表头单元格,再对它调用一次
BorderAround,并改用中等粗细的线型
为区域与单元格设置边框时,线型通过对象写法 { borderLine } 传入。
function App() {
const addBorderToCells = 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 inputFileName = 'CellBorders.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
// 加载工作簿,取第一张工作表
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: inputFileName });
const sheet = workbook.Worksheets.get(0);
// 取 B2:E6 区域,先加细线外框,再加内部细线
const dataRange = sheet.Range.get('B2:E6');
dataRange.BorderAround({ borderLine: xlsModule.LineStyleType.Thin });
dataRange.BorderInside({ borderLine: xlsModule.LineStyleType.Thin });
// 单独给表头所在的 B2 单元格加中等粗细的四周框线
sheet.Range.get('B2').BorderAround({ borderLine: xlsModule.LineStyleType.Medium });
// 保存结果文件
const outputFileName = 'AddBorderToCells.xlsx';
workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });
// 释放 workbook 对象以释放资源
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>添加或删除单元格边框</h1>
<button onClick={addBorderToCells}>为单元格或区域添加边框</button>
</div>
);
}
export default App;
运行后,数据区域与表头单元格加上边框的效果:

为包含数据的单元格区域添加边框
上一节按地址写死了 B2:E6,一旦表格增删行列就要跟着改地址。AllocatedRange 属性直接返回工作表中已分配的范围,也就是真正存放数据的矩形区域,用它取范围可以省去手工维护地址的麻烦,并且在表头之外再套一层样式不同的外框,让表格和正文区分得更清楚。
具体操作步骤如下:
- 通过
AllocatedRange取到工作表中包含数据的单元格区域,无需手动指定地址 - 调用
BorderAround给外圈换上中等粗细的虚线,与外框实线形成对比 - 调用
BorderInside为区域内部补上细线,让每一行数据之间保持分隔
function App() {
const addBorderToDataRange = async () => {
const xlsModule = window.wasmModule?.spirexls;
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
await window.spire.FetchFileToVFS('simsun.ttc', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'CellBorders.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: inputFileName });
const sheet = workbook.Worksheets.get(0);
// 用 AllocatedRange 直接取到含数据的单元格区域,不必手动指定地址
const dataRange = sheet.AllocatedRange;
// 外圈加中等粗细的虚线,内部加细线
dataRange.BorderAround({ borderLine: xlsModule.LineStyleType.MediumDashed });
dataRange.BorderInside({ borderLine: xlsModule.LineStyleType.Thin });
const outputFileName = 'AddBorderToDataRange.xlsx';
workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });
workbook.Dispose();
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>添加或删除单元格边框</h1>
<button onClick={addBorderToDataRange}>为数据区域添加边框</button>
</div>
);
}
export default App;
运行后,数据区域加上虚线外框与内部细线的效果:

为单元格添加左侧、顶部、右侧、底部和对角线边框
BorderAround 一次给四条边设成同样的样式,遇到「左边加粗标红、下边用双线」这类需求就不够用了。这时改成逐条边处理:通过 Borders.get 按 BordersLineType 枚举取出其中的一条边,再分别设置它的 LineStyle 与 Color,每条边的线型和颜色都可以不同,对角线的两个方向同样能单独设置。
具体操作步骤如下:
- 用
Range.get取到需要设置的单元格 - 用
Borders.get(BordersLineType.EdgeLeft)等取出左侧、顶部、右侧、底部四条边 - 对每条边设置
LineStyle,分别取粗线、点线、斜划线点、双线四种线型 - 对每条边设置
Color,分别取红、棕、深灰、橙红四种颜色 - 另取一个单元格,用
BordersLineType.DiagonalDown取出对角线下边框并设置线型
function App() {
const addEdgeBorders = async () => {
const xlsModule = window.wasmModule?.spirexls;
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
await window.spire.FetchFileToVFS('simsun.ttc', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'CellBorders.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: inputFileName });
const sheet = workbook.Worksheets.get(0);
// 为 B4 单元格的四条边分别设置线型与颜色
const cell = sheet.Range.get('B4');
const edgeSpecs = [
['EdgeLeft', xlsModule.LineStyleType.Thick, xlsModule.Color.get_Red()],
['EdgeTop', xlsModule.LineStyleType.Dotted, xlsModule.Color.get_Brown()],
['EdgeRight', xlsModule.LineStyleType.SlantedDashDot, xlsModule.Color.get_DarkGray()],
['EdgeBottom', xlsModule.LineStyleType.Double, xlsModule.Color.get_OrangeRed()],
];
for (const [edge, lineStyle, color] of edgeSpecs) {
const border = cell.Borders.get(xlsModule.BordersLineType[edge]);
border.LineStyle = lineStyle;
border.Color = color;
}
// 为 E6 单元格添加对角线下边框
const diagonal = sheet.Range.get('E6').Borders.get(xlsModule.BordersLineType.DiagonalDown);
diagonal.LineStyle = xlsModule.LineStyleType.Thin;
const outputFileName = 'AddEdgeBorders.xlsx';
workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });
workbook.Dispose();
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>添加或删除单元格边框</h1>
<button onClick={addEdgeBorders}>设置四条边与对角线边框</button>
</div>
);
}
export default App;
运行后,单元格四条边分别使用不同线型与颜色、并对角线加线的效果:

删除单元格或单元格区域的边框
把内部报表导出给外部使用、或者把数据喂给下游系统时,框线往往属于多余信息:它会让数据看起来像一张已经定稿的报表,下游按区域解析时也可能把框线当成有效内容。删除的做法与设置一样简单,把 Borders.LineStyle 批量设为 LineStyleType.None 即可一次清空区域内的全部边框。
具体操作步骤如下:
- 取到保存着带框线报表的那张工作表
- 用
Range.get取到需要清理的单元格区域 - 把区域的
Borders.LineStyle设为LineStyleType.None,清空其中的全部边框
function App() {
const removeBorders = async () => {
const xlsModule = window.wasmModule?.spirexls;
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
await window.spire.FetchFileToVFS('simsun.ttc', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'CellBorders.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: inputFileName });
// 第二张工作表里保存的是一份已经带框线的报表
const sheet = workbook.Worksheets.get(1);
// 把 B2:E6 区域内所有单元格的边框样式设为 None
sheet.Range.get('B2:E6').Borders.LineStyle = xlsModule.LineStyleType.None;
const outputFileName = 'RemoveBorders.xlsx';
workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });
workbook.Dispose();
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>添加或删除单元格边框</h1>
<button onClick={removeBorders}>删除单元格边框</button>
</div>
);
}
export default App;
运行后,区域内的边框被清空的效果:

常见问题
给整片区域设置上边框,每一行上方都多出一条线
原因:Borders.get(BordersLineType.EdgeTop) 取到的是「区域内每个单元格的上边」,而不是整个区域的外沿。把它直接用在 B2:E6 上,区域内的每一行都会各自得到一条上边线,表格内部因此凭空多出四条线。
解决:把区域收窄到一行或一列,取到的那条边才会落在表格外沿。上边取首行、下边取末行、左边取首列、右边取末列:
// 上边:只取首行
sheet.Range.get('B2:E2').Borders.get(xlsModule.BordersLineType.EdgeTop).LineStyle = xlsModule.LineStyleType.Thin;
// 下边:只取末行
sheet.Range.get('B6:E6').Borders.get(xlsModule.BordersLineType.EdgeBottom).LineStyle = xlsModule.LineStyleType.Thin;
// 左边:只取首列
sheet.Range.get('B2:B6').Borders.get(xlsModule.BordersLineType.EdgeLeft).LineStyle = xlsModule.LineStyleType.Thin;
// 右边:只取末列
sheet.Range.get('E2:E6').Borders.get(xlsModule.BordersLineType.EdgeRight).LineStyle = xlsModule.LineStyleType.Thin;
给单个单元格调用 BorderInside 报错
原因:BorderInside 表示「区域内部的分隔线」,至少要两个单元格才谈得上内部,因此传入单个单元格时会抛出 This method doesn't support for single cell.,结果文件同样不会生成。
解决:单个单元格改用 BorderAround 框住四周,或者按上一节的办法逐条边设置:
sheet.Range.get('B2').BorderAround({ borderLine: xlsModule.LineStyleType.Thin });
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。







