把工作簿交给前端程序处理时,JSON 是与接口、缓存和组件都合得来的数据形态:一层数组对应一张工作表,一个对象对应一行,键名取自表头。转换为 JSON 之后,表格数据无需后端解析即可直接进入页面的数据流。Spire.XLS for JavaScript 基于 WebAssembly 在浏览器端直接完成转换,输入与输出文件通过虚拟文件系统(VFS)管理,无需后端服务支持。
本文介绍四个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.XLS for JavaScript。以下示例默认已安装 Spire.XLS 并完成 WebAssembly 模块初始化。
将整个工作簿转换为 JSON
工作簿里的每张工作表都是一组结构相同的记录:首行写着字段名,其下每行是一条数据。整簿转换一次交出全部工作表,键名为表名,键值是记录数组,既不必逐表调用,也不必事先挑好范围。示例工作簿中的销售台账、客户信息与说明三张表会被一并写出,每张表各占一个顶层键。
整簿转换只需在保存时指明目标格式:
| 写法 | 得到的结果 |
|---|---|
fileFormat: xlsModule.FileFormat.Json |
按 JSON 格式写出工作簿,每张工作表各成一个顶层键 |
具体操作步骤如下:
- 用
window.spire.FetchFileToVFS把字体与测试数据文件载入 VFS。 - 用
new Workbook()新建工作簿,并用workbook.LoadFromFile载入输入文件。 - 用
workbook.SaveToFile保存工作簿,把fileFormat指定为xlsModule.FileFormat.Json。 - 用
workbook.Dispose释放 workbook 对象以释放资源。
以下为完整的代码示例,演示如何将整个工作簿转换为 JSON:
function App() {
const workbookToJson = 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 });
// 将整个工作簿保存为 JSON
const outputFileName = 'WorkbookToJson.json';
workbook.SaveToFile({ fileName: outputFileName, fileFormat: xlsModule.FileFormat.Json });
// 释放 workbook 对象以释放资源
workbook.Dispose();
// 从 VFS 读取结果文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/json' });
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 转 JSON</h1>
<button id="workbook-to-json" onClick={workbookToJson}>将整个工作簿转换为 JSON</button>
</div>
);
}
export default App;
转换整个工作簿后的 JSON 文件:

将指定工作表转换为 JSON
多数时候只有一张表需要交给前端,其余的是内部台账或使用说明,一并写出既拖长响应,也让调用方多挑一次。做法是把目标工作表复制进一份只留着它的新工作簿,再照常保存,结果里便只剩这一张表。示例导出的是第三张表(说明),销售台账与客户信息两张表不会出现在结果中。
隔离出一张工作表,靠的是对 Worksheets 集合的三步操作:
| 写法 | 得到的结果 |
|---|---|
workbook.Worksheets.get(2) |
按索引取得第三张工作表,索引自 0 起算 |
workbook.Worksheets.Clear() |
清空工作簿中原有的工作表 |
workbook.Worksheets.AddCopy({ sheet }) |
把源工作表整张复制进已清空的工作簿 |
具体操作步骤如下:
- 用
window.spire.FetchFileToVFS把字体与测试数据文件载入 VFS。 - 用
new Workbook()新建源工作簿,用workbook.LoadFromFile载入输入文件,再用Worksheets.get(2)取得要导出的工作表。 - 再
new Workbook()新建目标工作簿,用Worksheets.Clear()清掉它默认带的三张空白工作表。 - 用
Worksheets.AddCopy({ sheet })把目标工作表复制进新工作簿,使其成为唯一的一张表。 - 用
SaveToFile保存新工作簿,fileFormat同样指定为xlsModule.FileFormat.Json。 - 用
Dispose释放源工作簿与目标工作簿对象。
以下为完整的代码示例,演示如何将指定工作表转换为 JSON:
function App() {
const worksheetToJson = 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 sourceWorkbook = new xlsModule.Workbook();
sourceWorkbook.LoadFromFile({ fileName: inputFileName });
const targetSheet = sourceWorkbook.Worksheets.get(2);
// 新建工作簿,先清空默认生成的 3 张工作表
const targetWorkbook = new xlsModule.Workbook();
targetWorkbook.Worksheets.Clear();
// 将目标工作表复制进新工作簿,使其成为唯一的一张表
targetWorkbook.Worksheets.AddCopy({ sheet: targetSheet });
// 仅保存这张工作表
const outputFileName = 'WorksheetToJson.json';
targetWorkbook.SaveToFile({ fileName: outputFileName, fileFormat: xlsModule.FileFormat.Json });
// 释放 workbook 对象以释放资源
sourceWorkbook.Dispose();
targetWorkbook.Dispose();
// 从 VFS 读取结果文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/json' });
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 转 JSON</h1>
<button id="worksheet-to-json" onClick={worksheetToJson}>将指定工作表转换为 JSON</button>
</div>
);
}
export default App;
转换指定工作表后的 JSON 文件:

将指定单元格区域转换为 JSON
一张表里往往还夹着别的东西:标题行、汇总公式、从别处贴进来的辅助列。整表导出会连它们一起带上,而调用方只想要其中那块规整的数据。把区域框定出来再导出,框外的单元格不会进入结果。示例取销售台账的 A1:D6 六行四列,单价、数量与金额三列留在原表里,未被写出。
区域导出与工作表导出同路,区别在于复制的对象由整张表换成了一块区域:
| 写法 | 得到的结果 |
|---|---|
sourceSheet.Range.get('A1:D6') |
按地址取得源单元格区域 |
workbook.Worksheets.Add('RangeData') |
在已清空的工作簿中新建一张名为 RangeData 的工作表 |
targetSheet.Range.get('A1:D6') |
取得与源区域大小一致的目标区域 |
sourceSheet.Copy({ sourceRange, destRange, copyStyle: true }) |
把源区域的值与样式复制到目标区域,copyStyle 为 true 时样式一并复制 |
具体操作步骤如下:
- 用
window.spire.FetchFileToVFS把字体与测试数据文件载入 VFS。 - 用
new Workbook()新建源工作簿,用workbook.LoadFromFile载入输入文件,再用Worksheets.get(0)取得源工作表。 - 用
sourceSheet.Range.get('A1:D6')框出要导出的单元格区域。 - 新建目标工作簿并用
Worksheets.Clear()清空默认工作表,再用Worksheets.Add('RangeData')新建一张用于承接区域的工作表。 - 用
targetSheet.Range.get('A1:D6')取得大小一致的目标区域,调用sourceSheet.Copy({ sourceRange, destRange, copyStyle: true })把值与样式复制过去。 - 用
SaveToFile保存新工作簿,fileFormat指定为xlsModule.FileFormat.Json,再用Dispose释放两个 workbook 对象。
以下为完整的代码示例,演示如何将指定单元格区域转换为 JSON:
function App() {
const rangeToJson = 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 sourceWorkbook = new xlsModule.Workbook();
sourceWorkbook.LoadFromFile({ fileName: inputFileName });
const sourceSheet = sourceWorkbook.Worksheets.get(0);
// 指定需要导出的单元格区域
const sourceRange = sourceSheet.Range.get('A1:D6');
// 新建工作簿,清空默认工作表后新建一张用于承接区域
const targetWorkbook = new xlsModule.Workbook();
targetWorkbook.Worksheets.Clear();
const targetSheet = targetWorkbook.Worksheets.Add('RangeData');
// 将源区域的值与样式复制到新工作表,目标区域大小需与源区域一致
const destRange = targetSheet.Range.get('A1:D6');
sourceSheet.Copy({ sourceRange, destRange, copyStyle: true });
// 保存新工作簿
const outputFileName = 'RangeToJson.json';
targetWorkbook.SaveToFile({ fileName: outputFileName, fileFormat: xlsModule.FileFormat.Json });
// 释放 workbook 对象以释放资源
sourceWorkbook.Dispose();
targetWorkbook.Dispose();
// 从 VFS 读取结果文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/json' });
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 转 JSON</h1>
<button id="range-to-json" onClick={rangeToJson}>将指定单元格区域转换为 JSON</button>
</div>
);
}
export default App;
转换指定单元格区域后的 JSON 文件:

自定义 JSON 输出格式
前面三种做法写出的结构都是固定的:字段名原样取自表头,取值一律按字符串处理,金额写成 "186400",布尔写成 "TRUE",日期写成 "2021/3/15 上午12:00:00",空单元格干脆不生成字段。这样的结果交给接口或组件绑定还得再洗一遍。改为逐个单元格读取,就可以自己决定字段名、每个值的数据类型,以及空值怎么表示。
自行读取单元格时会用到下列取值方式:
| 写法 | 得到的结果 |
|---|---|
sheet.get(row, column) |
按行列号取单元格,行列号均自 1 起算 |
sheet.LastRow / sheet.LastColumn |
已用区域的末行号与末列号 |
cell.Text |
单元格中的文本内容,空单元格返回空字符串 |
cell.NumberValue |
数值列的数值,返回数字类型;空单元格返回 null |
cell.BooleanValue |
布尔列的 true 或 false,返回布尔类型 |
cell.DateTimeValue |
日期列的 Date 对象,可由代码自行格式化 |
JSON.stringify(records, null, 2) |
序列化为带两空格缩进的 JSON 文本 |
具体操作步骤如下:
- 用
window.spire.FetchFileToVFS把字体与测试数据文件载入 VFS,用new Workbook()与workbook.LoadFromFile加载工作簿,再用Worksheets.get(1)取得客户信息工作表。 - 把需要的字段写成数组,每项记下列标题、输出字段名与取值方式。
- 用
sheet.get(1, column)读表头行,配合sheet.LastColumn建立列标题到列号的对照。 - 从第 2 行遍历到
sheet.LastRow,按取值方式分别用cell.Text、cell.NumberValue、cell.BooleanValue与cell.DateTimeValue取值,空单元格记为null。 - 用
Date对象的年月日拼出yyyy-MM-dd形式的日期。 - 用
JSON.stringify加两空格缩进写出 JSON 文本,再用FS.writeFile写入 VFS。 - 用
workbook.Dispose释放 workbook 对象以释放资源。
以下为完整的代码示例,演示如何自定义 JSON 输出格式:
function App() {
const customJsonFormat = 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(1);
// 需要的字段:列标题、输出字段名、取值方式
const fields = [
{ header: '客户编号', key: 'customerId', type: 'text' },
{ header: '客户名称', key: 'customerName', type: 'text' },
{ header: '所在城市', key: 'city', type: 'text' },
{ header: '首次合作日期', key: 'firstOrderDate', type: 'date' },
{ header: '是否续约', key: 'renewed', type: 'boolean' },
{ header: '累计订单额(元)', key: 'totalAmount', type: 'number' },
{ header: '备注', key: 'remark', type: 'text' },
];
// 读取表头行,建立列标题到列号的对照
const columnOf = {};
for (let column = 1; column <= sheet.LastColumn; column++) {
columnOf[sheet.get(1, column).Text] = column;
}
// 日期统一输出为 yyyy-MM-dd
const pad = (value) => String(value).padStart(2, '0');
const formatDate = (date) =>
`${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
// 逐行读取,空单元格输出 null
const records = [];
for (let row = 2; row <= sheet.LastRow; row++) {
const record = {};
for (const field of fields) {
const cell = sheet.get(row, columnOf[field.header]);
if (field.type === 'number') {
record[field.key] = cell.NumberValue;
} else if (field.type === 'boolean') {
record[field.key] = cell.BooleanValue;
} else if (field.type === 'date') {
record[field.key] = formatDate(cell.DateTimeValue);
} else {
const text = cell.Text;
record[field.key] = text === '' ? null : text;
}
}
records.push(record);
}
// 缩进两个空格写出,便于直接查看
const json = JSON.stringify(records, null, 2);
// 将 JSON 字符串写入 VFS
const outputFileName = 'CustomJsonFormat.json';
window.dotnetRuntime.Module.FS.writeFile(outputFileName, new TextEncoder().encode(json));
// 释放 workbook 对象以释放资源
workbook.Dispose();
// 从 VFS 读取结果文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/json' });
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 转 JSON</h1>
<button id="custom-json-format" onClick={customJsonFormat}>自定义 JSON 输出格式</button>
</div>
);
}
export default App;
自定义输出格式后的 JSON 文件:

常见问题
导出的 JSON 里数值、布尔值和日期都是字符串
原因:SaveToFile 按单元格的存储值写出,既不套用单元格的数字格式,也不推断类型,因此金额写成 "186400",布尔写成 "TRUE",日期写成 "2021/3/15 上午12:00:00"。
解决:需要真实类型时改为自己读取单元格,用 cell.NumberValue 取数值、cell.BooleanValue 取布尔值、cell.DateTimeValue 取日期,再交给 JSON.stringify 序列化。
空单元格没有出现在 JSON 里
原因:整簿导出与工作表导出都以表头行作为字段名,空单元格不生成对应字段,该行对象的键数因此比别的行少。
解决:若调用方要求每行的字段齐全,改为自己读取单元格,在 cell.Text 返回空字符串时写入 null,让每行的键保持一致。
导出的 JSON 顶层多了一个 Evaluation Warning 键
原因:试用版会在工作簿中额外插入一张评估警告工作表,整簿导出时它与其他工作表一样成为顶层的一个键。
解决:改用按指定工作表或按单元格区域导出,结果里就只剩需要的数据;若整簿导出无法避免,可该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取临时许可证去掉评估信息。
只想导出其中几列
原因:整簿导出与工作表导出都会带上工作表里的全部列,区域导出则只能取连续的一段,像 A、C、E 这样跳选的列无法用区域表达。
解决:用自定义 JSON 输出格式的做法按字段自行读取,只保留需要的列;列恰好连续时,也可以直接用区域导出把范围收窄。
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。







