vxe-table导出excel插件,即exceljs导出多张图片的坑

使用vxe-table的vxe-img-group组件在单元格可以很好的在web页面渲染多张图片,但是如果使用推荐的第三方导出excel插件plugin-export-xlsx(基于exceljs)的话,则只能导出第一张图片.

搜索全网,没找到类似需求的解决方法,问deepseek,倒是给出了通过配置偏移量实现的方案,但是实际测试才发现坑很大

const exportToExcel = async () => {
    data.search.rows = 999999
    await getDataList()
    const $table = tableRef.value
    if ($table) {
        // 配置exportConfig的sheetMethod方法给 excel单元格添加 多张图片,实际上就是操作exceljs的接口
        exportConfig.sheetMethod = async (params) =>{
            console.log('配置exportConfig的sheetMethod方法');
            const dataList = data.dataList

            const imageList = dataList[0].beforeRectificationImgsList
            console.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 = 10
    await getDataList()
}

如上图配置exportConfig的sheetMethod方法,这个坑实际上是微软excel的坑,它的列宽是基于字符宽度,也就是不是一个固定的值(并且因为留白之类的还要再多一点,比如默认是8个字符宽度,实际查看是8.23),而exceljs在计算偏移量的时候是把它当做像素计算的(也有说是exceljs自己的一套,见下面参考文章),导致导出后,即使你换算的非常精确,结果却是所有图片挤在单元格左侧的大概三分之一的空间,剩下的都是空白,所以,这种方法是不可行的,只少用exceljs不行,后端导出有可能行吧,不过嫌麻烦没试,根据deepseek的推荐,使用曲线实现的方法:设置成每个单元格一张图片,再设置合并单元格

参考文章:

ExcelJS 导出列宽行高失真?深度解析与实战修复 - ByteZoneX社区

将EXCEL单元格的宽度单位转换为像素单位。 - 知乎

posted @ 2025-10-29 09:00  dirgo  阅读(15)  评论(0)    收藏  举报