带图的报表攒到一定数量,麻烦的往往不是文字而是图片:几百 KB 的产品图直接插进工作表,工作簿体积迅速膨胀,发送、归档都变得吃力;从别处复制过来的图片尺寸又不统一,大的盖住整块数据区,小的缩在角落里看不清。这些调整在 Excel 里逐张手动拖拽尚可应付,一旦换成程序批量处理就没有可用的入口。Spire.XLS for JavaScript 基于 WebAssembly 在浏览器端直接完成这些操作,通过虚拟文件系统(VFS)管理输入输出文件,无需后端服务支持。
本文介绍三个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.XLS for JavaScript。以下示例默认已安装 Spire.XLS 并完成 WebAssembly 模块初始化。
压缩 Excel 中的图片
Compress() 按指定的质量比例重新编码图片,传入 50 即把图片质量降到原来的 50%。质量越低,图片所占的数据量越小,工作簿也就越轻。压缩只作用于图片本身的数据,图片在工作表中的位置和显示尺寸都保持不变,因此适合在不改动版面的前提下给文件瘦身。具体操作步骤如下:
- 加载工作簿。
- 遍历所有工作表中的所有图片。
- 通过
Compress将每张图片压缩到 50% 的质量。 - 保存工作簿。
下面是一个完整的代码示例,展示了在 React 中压缩 Excel 中的图片:
function App() {
const compressPictures = 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 文件载入 VFS
const inputFileName = 'ResizeAndMovePictures.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/static/data/`);
// 加载工作簿
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile(inputFileName);
// 遍历所有工作表中的所有图片
for (const sheet of workbook.Worksheets) {
for (const picture of sheet.Pictures) {
// 将图片质量压缩到 50%
picture.Compress(50);
}
}
// 保存工作簿
const outputFileName = "CompressPictures.xlsx";
workbook.SaveToFile(outputFileName);
// 释放资源
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 onClick={compressPictures}>Start</button>
</div>
);
}
export default App;
运行后,压缩 Excel 中图片的效果:

调整 Excel 中图片的大小
图片在工作表中的显示尺寸由 Width 和 Height 两个属性决定,单位是像素。给这两个属性重新赋值即可把图片改到指定大小——缩小的图不再压住旁边的数据区,放大的图也能填满预留的图片位。具体操作步骤如下:
- 加载工作簿,获取第一个工作表。
- 通过
sheet.Pictures.get(0)获取工作表中的第一张图片。 - 设置
Width和Height调整图片大小。 - 保存工作簿。
下面是一个完整的代码示例,展示了在 React 中调整 Excel 中图片的大小:
function App() {
const resizePicture = 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 文件载入 VFS
const inputFileName = 'ResizeAndMovePictures.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/static/data/`);
// 加载工作簿
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile(inputFileName);
// 获取第一个工作表
const sheet = workbook.Worksheets.get(0);
// 获取工作表中的第一张图片
const picture = sheet.Pictures.get(0);
// 调整图片大小
picture.Width = 140;
picture.Height = 140;
// 保存工作簿
const outputFileName = "ResizePicture.xlsx";
workbook.SaveToFile(outputFileName);
// 释放资源
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 onClick={resizePicture}>Start</button>
</div>
);
}
export default App;
Width 与 Height 分别对应图片的宽度和高度,两者独立生效,赋值后图片立即按新尺寸显示。需要注意的是,这里设置的是图片框的尺寸而非等比缩放——宽高与原图比例不一致时图片会被拉伸,处理办法见下文常见问题。
运行后,调整 Excel 中图片大小的效果:

移动 Excel 中图片的位置
图片在 Excel 中是被锚定在某个单元格上的浮动对象,仅设置尺寸并不能改变它出现的位置。Left 和 Top 两个属性以像素为单位,指定图片左上角相对于工作表左上角的距离,赋值后图片便会移动到新的坐标处,用于把图片挪出数据区、或统一对齐到同一列图片位。具体操作步骤如下:
- 加载工作簿,获取第一个工作表。
- 通过
sheet.Pictures.get(0)获取工作表中的第一张图片。 - 设置
Left和Top移动图片位置。 - 保存工作簿。
下面是一个完整的代码示例,展示了在 React 中移动 Excel 中图片的位置:
function App() {
const movePicture = 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 文件载入 VFS
const inputFileName = 'ResizeAndMovePictures.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/static/data/`);
// 加载工作簿
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile(inputFileName);
// 获取第一个工作表
const sheet = workbook.Worksheets.get(0);
// 获取工作表中的第一张图片
const picture = sheet.Pictures.get(0);
// 调整图片位置
picture.Left = 360;
picture.Top = 180;
// 保存工作簿
const outputFileName = "MovePicture.xlsx";
workbook.SaveToFile(outputFileName);
// 释放资源
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 onClick={movePicture}>Start</button>
</div>
);
}
export default App;
Left 与 Top 描述的是图片左上角在工作表中的绝对坐标,与图片原先锚定在哪一行、哪一列无关。
运行后,移动 Excel 中图片位置的效果:

常见问题
调整图片大小时图片被拉变形了?
原因:Width 和 Height 是两个彼此独立的属性,分别赋值时不会保留图片原有的宽高比。若把一张长方形图片的宽和高都设成同一个值,图片就会被强制拉成正方形。
解决:先读取图片当前的宽高算出比例,再按比例换算另一个方向的值:
// 读取图片当前的宽高,算出宽高比
const picture = sheet.Pictures.get(0);
const ratio = picture.Height / picture.Width;
// 固定宽度,按比例算出高度,图片不会被拉变形
picture.Width = 140;
picture.Height = Math.round(140 * ratio);
IsLockAspectRatio 能保证图片不变形吗?
原因:不能。这个属性默认就是 true,它设置的是图片的锁定标记,约束的是在 Excel 里手动拖拽时的行为;用代码给 Width / Height 赋值时,它不会替你换算另一条边。实测把 Width 改成 140,无论 IsLockAspectRatio 是 true 还是 false,Height 都停在原来的 300。
解决:等比缩放仍然要自己按比例算。这个属性可以读写,改完能随文件保存下来,需要与文件里的锁定状态对齐时再设置:
// 锁定标记:默认 true,改为 false 会写进文件,重新打开后读回仍是 false
picture.IsLockAspectRatio = false;
// 但它不参与宽高换算:只改 Width,Height 会停在原值
picture.Width = 140;
// 要等比缩放,还是先算比例再赋值
const ratio = picture.Height / picture.Width;
picture.Width = 140;
picture.Height = Math.round(140 * ratio);
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。







