表格中常有一些行列需要移除:已经下架的商品、作废的记录、自外部粘贴而来却始终空着的一列。删除之后,余下的行列依次前移,表结构保持连续,引用该区域的位置也随之上移,无需另行排版。Spire.XLS for JavaScript 基于 WebAssembly 在浏览器端直接完成上述操作,通过虚拟文件系统(VFS)管理输入与输出文件,无需后端服务支持。
本文介绍三个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.XLS for JavaScript。以下示例默认已安装 Spire.XLS 并完成 WebAssembly 模块初始化。
删除指定的行和列
需要移除的往往只是表中一两处:一行作废的记录,或一列不再需要的分类。按行号、列号分别删除一次即可,被删位置之后的区域自动上移或左移,行高、列宽与单元格边框随内容一并迁移,原有的数字格式不受影响。示例工作簿的台账中含一行作废记录与一列多余的分类列,删除前后对比即可看出差别。
DeleteRow 与 DeleteColumn 按行号、列号删除整行整列:
| 写法 | 得到的结果 |
|---|---|
sheet.DeleteRow({ index }) |
删除第 index 行,其下各行依次上移 |
sheet.DeleteColumn({ index }) |
删除第 index 列,其右各列依次左移 |
具体操作步骤如下:
- 用
window.spire.FetchFileToVFS把字体文件与测试数据文件载入 VFS。 - 用
new Workbook()新建工作簿,用workbook.LoadFromFile载入输入文件,再用workbook.Worksheets.get(0)取得第一张工作表。 - 用
sheet.DeleteRow传入行号,删除该行。 - 用
sheet.DeleteColumn传入列号,删除该列。 - 用
workbook.SaveToFile保存工作簿,再用workbook.Dispose释放 workbook 对象以释放资源。
以下为完整的代码示例,演示如何在 React 中删除指定的行和列:
function App() {
const deleteRowAndColumn = 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 = 'Sample.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);
// 删除第 17 行的作废记录
sheet.DeleteRow({ index: 17 });
// 删除第 4 列的类别列
sheet.DeleteColumn({ index: 4 });
// 保存工作簿
const outputFileName = 'DeleteRowAndColumn.xlsx';
workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2016 });
// 释放 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>删除 Excel 行和列</h1>
<button id="delete-row-column" onClick={deleteRowAndColumn}>删除指定的行和列</button>
</div>
);
}
export default App;
删除指定的行和列后的工作表:

删除多行和多列
需要清除的若是连成一片的若干行或列,逐条调用既繁琐,又会因前一次删除使位置偏移而出错。在行号、列号之外给出要删的条数,即可一次删除从该位置起连续的若干行或列,余下内容自动补齐,无需反复推算新的位置。示例工作簿中含五件已下架商品与两列明细,删除前后对比即可看出差别。
两个方法都接受 count,一次删掉从该位置起连续的一段:
| 写法 | 得到的结果 |
|---|---|
sheet.DeleteRow({ index, count }) |
从第 index 行起删除 count 行 |
sheet.DeleteColumn({ index, count }) |
从第 index 列起删除 count 列 |
具体操作步骤如下:
- 用
window.spire.FetchFileToVFS把字体文件与测试数据文件载入 VFS。 - 用
new Workbook()新建工作簿,用workbook.LoadFromFile载入输入文件,再用workbook.Worksheets.get(0)取得第一张工作表。 - 用
sheet.DeleteRow传入起始行号与count,从该位置起删除连续的若干行。 - 用
sheet.DeleteColumn传入起始列号与count,从该位置起删除连续的若干列。 - 用
workbook.SaveToFile保存工作簿,再用workbook.Dispose释放 workbook 对象以释放资源。
以下为完整的代码示例,演示如何在 React 中一次删除多行和多列:
function App() {
const deleteMultiRowsAndColumns = 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 = 'Sample.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);
// 从第 9 行起删除 5 行已下架商品
sheet.DeleteRow({ index: 9, count: 5 });
// 从第 5 列起删除 2 列明细列
sheet.DeleteColumn({ index: 5, count: 2 });
// 保存工作簿
const outputFileName = 'DeleteMultiRowsAndColumns.xlsx';
workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2016 });
// 释放 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>删除 Excel 行和列</h1>
<button id="delete-multi-rows-columns" onClick={deleteMultiRowsAndColumns}>删除多行和多列</button>
</div>
);
}
export default App;
删除多行和多列后的工作表:

删除空白行和空白列
自外部粘贴而来的数据常夹着整行整列的空档,逐一查找既费时又容易遗漏。逐行逐列检查一遍,为空者即行删除,表格随之收紧。关键在于倒序遍历:每删掉一行,后面的行整体上移一位,若从前往后检查,紧邻其后的行会移至该位置而被跳过。示例工作簿中含两条空行与一列始终未填的列,清理前后对比即可看出差别。
清理要先把行、列取出来判断是否为空,再交回删除方法:
| 写法 | 得到的结果 |
|---|---|
sheet.Rows.get(i).IsBlank |
第 i + 1 行是否为空 |
sheet.Columns.get(j).IsBlank |
第 j + 1 列是否为空 |
sheet.DeleteRow(i + 1) |
删除第 i + 1 行 |
sheet.DeleteColumn(j + 1) |
删除第 j + 1 列 |
具体操作步骤如下:
- 用
window.spire.FetchFileToVFS把字体文件与测试数据文件载入 VFS。 - 用
new Workbook()新建工作簿,用workbook.LoadFromFile载入输入文件,再用workbook.Worksheets.get(0)取得第一张工作表。 - 用
sheet.Rows.length取得行数,从最后一行往前遍历;逐行用sheet.Rows.get(i)取出行,用它的IsBlank判断是否为空,为空则用sheet.DeleteRow(i + 1)删除。 - 用
sheet.Columns.length取得列数,从最后一列往前遍历;逐列用sheet.Columns.get(j)取出列,同样以IsBlank判断,为空则用sheet.DeleteColumn(j + 1)删除。 - 用
workbook.SaveToFile保存工作簿,再用workbook.Dispose释放 workbook 对象以释放资源。
以下为完整的代码示例,演示如何在 React 中删除空白行和空白列:
function App() {
const deleteBlankRowsAndColumns = 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 = 'Sample.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);
// 从下往上逐行检查,删掉空白行
for (let i = sheet.Rows.length - 1; i >= 0; i--) {
if (sheet.Rows.get(i).IsBlank) {
sheet.DeleteRow(i + 1);
}
}
// 从右往左逐列检查,删掉空白列
for (let j = sheet.Columns.length - 1; j >= 0; j--) {
if (sheet.Columns.get(j).IsBlank) {
sheet.DeleteColumn(j + 1);
}
}
// 保存工作簿
const outputFileName = 'DeleteBlankRowsAndColumns.xlsx';
workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2016 });
// 释放 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>删除 Excel 行和列</h1>
<button id="delete-blank-rows-columns" onClick={deleteBlankRowsAndColumns}>删除空白行和空白列</button>
</div>
);
}
export default App;
删除空白行和空白列后的工作表:

常见问题
带边框但没有内容的列会被当成空白列吗
原因:IsBlank 判断的是行或列中是否存在内容,与样式、边框、行高、列宽无关。示例工作簿中那一列没有填入任何数据,只是整张表统一描过边框而留有网格线,仍被判定为空白列。
解决:以 sheet.Columns.get(j).IsBlank 判断时,这类仅有格式的列会一并删除。若此类列需要保留,则不宜以整列是否为空作为判据,应逐格检查具体单元格中是否存在数据。
DeleteRow 的行号是从 0 开始还是从 1 开始
原因:DeleteRow、DeleteColumn 的行号、列号都从 1 起算,sheet.DeleteRow({ index: 17 }) 删掉的是第 17 行。而从 Rows、Columns 集合中取行列时下标是 0 基的,sheet.Rows.get(7) 拿到的是第 8 行。
解决:两处口径不同,从集合遍历出来的下标要加 1 再交给删除方法:
for (let i = sheet.Rows.length - 1; i >= 0; i--) {
// Rows.get(i) 是第 i + 1 行
if (sheet.Rows.get(i).IsBlank) {
sheet.DeleteRow(i + 1);
}
}
一次可以删除不连续的多行或多列吗
原因:DeleteRow 与 DeleteColumn 的 count 参数表示从 index 起连续的条数,一次删掉的是相邻的一段。
解决:不连续的几段分开调用,每段一次,并按行号(或列号)从大到小进行。先删靠后的段,前面各段的位置不受影响;从小到大删的话,后一段的起始位置会因前一段被删而前移,落在别处。
逐行删除空白行时,为什么从前往后遍历会漏删
原因:每调用一次 DeleteRow,其后各行的位置都会上移一行。从前往后检查时,删掉第 i 行之后,原本的第 i + 1 行移到了第 i 行,而遍历已经推进到 i + 1,这一行就被跳过了;空行相邻时便会漏删。
解决:改为从最后一行往前遍历,删除后前面各行的下标不受影响:
for (let i = sheet.Rows.length - 1; i >= 0; i--) {
if (sheet.Rows.get(i).IsBlank) {
sheet.DeleteRow(i + 1);
}
}
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。







