使用vxe-table的vxe-img-group组件在单元格可以很好的在web页面渲染多张图片,但是如果使用推荐的第三方导出excel插件plugin-export-xlsx(基于exceljs)的话,则只能导出第一张图片.
搜索全网,没找到类似需求的解决方法,问deepseek,倒是给出了通过配置偏移量实现的方案,但是实际测试才发现坑很大
const exportToExcel = async () => {data.search.rows = 999999await getDataList()const $table = tableRef.valueif ($table) {// 配置exportConfig的sheetMethod方法给 excel单元格添加 多张图片,实际上就是操作exceljs的接口exportConfig.sheetMethod = async (params) =>{console.log('配置exportConfig的sheetMethod方法');const dataList = data.dataListconst imageList = dataList[0].beforeRectificationImgsListconsole.log('图片===',imageList)const { worksheet, workbook } = params// // 1. 调整目标单元格的行高和列宽,为多张图片预留空间// const targetRow = 4; // 例如,第二行// const targetCol = 9; // 例如,B列// worksheet.getRow(targetRow).height = 150; // 设置行高// worksheet.getColumn(targetCol).width = 30; // 设置列宽// // // 2. 将图片添加到工作簿// const imageId1 = workbook.addImage({// filename: 'http://127.0.0.1:19000/donghai7s/CheckPhotos/2025/10/00_093351948.png', // 替换为你的图片路径// extension: 'png',// });// const imageId2 = workbook.addImage({// filename: 'http://127.0.0.1:19000/donghai7s/CheckPhotos/2025/10/00_093352238.png', // 替换为你的图片路径// extension: 'png',// });// // ... 可以添加更多图片// // // 3. 将图片定位到同一个单元格内的不同位置// // 获取单元格的起始位置(左上角)// // 注意:ExcelJS 的坐标是从 (1, 1) 开始的// const cellStartPos = {// col: targetCol,// row: targetRow// };// // // 定义图片在单元格内的偏移量和尺寸// worksheet.addImage(imageId1, {// tl: { col: cellStartPos.col, row: cellStartPos.row }, // 定位到单元格左上角// ext: { width: 50, height: 50 } // 设置图片显示尺寸// });// // worksheet.addImage(imageId2, {// tl: {// col: cellStartPos.col + 0.3, // 在单元格内水平偏移(可理解为向右移动)// row: cellStartPos.row + 0.3 // 在单元格内垂直偏移(可理解为向下移动)// },// ext: { width: 50, height: 50 }// });// 假设将4张图片排列成 2x2 的网格const imagesPerRow = 7; // 每行图片数const imageWidth = 60;const imageHeight = 30;// 获取单元格的起始位置(左上角)// 注意:ExcelJS 的坐标是从 (1, 1) 开始的const cellStartPos = {col: 8,row: 3};// 计算单元格总大小,并据此设置行高列宽// worksheet.getColumn(9).width = imageWidth * imagesPerRow;// 遍历所有图片,计算每个图片在网格中的位置for (const image of imageList) {const index = imageList.indexOf(image);console.log(index, image)// const buffer = await fetch(image).then(res => res.arrayBuffer())// // 2. 将图片添加到工作簿// const imageId = workbook.addImage({// buffer, // 替换为你的图片路径// // });const buffer1 = await fetch('http://127.0.0.1:19000/donghai7s/CheckPhotos/2025/10/00_093352238.png').then(res => res.arrayBuffer())const imageId = workbook.addImage({buffer: buffer1,extension: 'png'})const rowOffset = Math.floor(index / imagesPerRow*100)/100; // 计算行偏移console.log('=计算行偏移====',rowOffset)worksheet.addImage(imageId, {tl: {col: cellStartPos.col+ rowOffset, // 水平方向偏移row: cellStartPos.row // 垂直方向偏移 },ext: {width: imageWidth,height: imageHeight}});}}console.log('====开始导出');await $table.exportData({type: 'xlsx',useStyle: true})console.log('====导出完成');//高级导出// $table.openExport() }data.search.rows = 10await getDataList() }
如上图配置exportConfig的sheetMethod方法,这个坑实际上是微软excel的坑,它的列宽是基于字符宽度,也就是不是一个固定的值(并且因为留白之类的还要再多一点,比如默认是8个字符宽度,实际查看是8.23),而exceljs在计算偏移量的时候是把它当做像素计算的(也有说是exceljs自己的一套,见下面参考文章),导致导出后,即使你换算的非常精确,结果却是所有图片挤在单元格左侧的大概三分之一的空间,剩下的都是空白,所以,这种方法是不可行的,只少用exceljs不行,后端导出有可能行吧,不过嫌麻烦没试,根据deepseek的推荐,使用曲线实现的方法:设置成每个单元格一张图片,再设置合并单元格
参考文章:
ExcelJS 导出列宽行高失真?深度解析与实战修复 - ByteZoneX社区
将EXCEL单元格的宽度单位转换为像素单位。 - 知乎