✅ 支持多图片列导出✅ 自动识别Base64和DataURL格式✅ 精确控制图片位置✅ 异常处理与性能优化
// utils/excelExport.jsimport ExcelJS from 'exceljs';import { saveAs } from 'file-saver';/** * * @param headers 表头,[表头1,表头2,...] 必填 * @param tableData 内容 [data1,data2,...] 必填 * @param imageIndex 图片下标列 [0, 1, 2 , ...], 非必填 * @returns {Promise} */export const exportToExcel = async (headers, tableData, imageIndex = []) => { const workbook = new ExcelJS.Workbook(); const worksheet = workbook.addWorksheet('Sheet1'); // 添加表头 const headerRow = worksheet.addRow(headers); // 设置表头样式 headerRow.eachCell((cell) => { cell.font = { bold: true, color: { argb: 'FFFFFFFF' }, size: 12 }; cell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF007BFF' } }; cell.alignment = { horizontal: 'center', vertical: 'middle' }; }); // 设置列宽 headers.forEach((_, colIndex) => { let width = 20; // 默认列宽 if (imageIndex.includes(colIndex)) { width = 30; // 图片列更宽 } worksheet.getColumn(colIndex + 1).width = width; }); // 处理数据行(修改为异步) for (let rowIdx = 0; rowIdx < tableData.length; rowIdx++) { const row = tableData[rowIdx]; const dataRow = worksheet.addRow(row); if (imageIndex.length > 0) { // 使用Promise.all处理多列图片 await Promise.all(imageIndex.map(async (colIdx) => { const imgUrl = row[colIdx]; if (!imgUrl) return; try { const parsed = await parseImageData(imgUrl); if (!parsed) return; const imageId = workbook.addImage({ base64: parsed.base64, extension: parsed.extension, }); const colLetter = getExcelColumnLetter(colIdx); const excelRow = rowIdx + 2; worksheet.addImage(imageId, { tl: { col: colIdx, row: excelRow - 1 }, br: { col: colIdx + 1, row: excelRow }, editAs: 'oneCell' // 更稳定的定位方式 }); } catch (error) { console.error(`图片处理失败(行${rowIdx + 1}列${colIdx + 1}):`, error); } })); } } // 生成文件 const buffer = await workbook.xlsx.writeBuffer(); saveAs(new Blob([buffer]), `数据导出_${new Date().getTime()}.xlsx`);};// 列索引转Excel字母(如:0 -> A, 1 -> B)const getExcelColumnLetter = (column) => { let letter = ''; let col = column + 1; while (col > 0) { const remainder = (col - 1) % 26; letter = String.fromCharCode(65 + remainder) + letter; col = Math.floor((col - 1) / 26); } return letter;};// 新增:将图片URL转换为base64const urlToBase64 = async (url) => { try { const response = await fetch(url); const blob = await response.blob(); return new Promise((resolve) => { const reader = new fileReader(); reader.onloadend = () => resolve(reader.result); reader.readAsDataURL(blob); }); } catch (error) { console.error('图片转换失败:', error); return null; }};// 修改后的解析函数const parseImageData = async (imgData) => { if (!imgData) return null; // 处理URL情况 if (imgData.startsWith('http')) { const dataURL = await urlToBase64(imgData); if (!dataURL) return null; const [header, base64] = dataURL.split(';base64,'); const extension = header.split('/')[1]; return { base64, extension }; } // 原有处理dataURL的逻辑 if (imgData.startsWith('data:image')) { const [header, base64] = imgData.split(';base64,'); if (!header || !base64) return null; const extension = header.split('/')[1]; return { base64, extension }; } return null;}; headers.forEach((_, colIndex) => { let width = 20; // 默认列宽 if (imageIndex.includes(colIndex)) { width = 30; // 图片列更宽 } worksheet.getColumn(colIndex + 1).width = width; });
坐标转换
通过getExcelColumnLetter函数将数字索引转换为Excel字母坐标
// tl: 左上角定位(top-left)// br: 右下角定位(bottom-right){ tl: { col: 0, row: 0 }, // A1单元格 br: { col: 1, row: 1 } // B2单元格}
建议根据实际业务需求调整图片定位参数和样式配置,对于复杂报表建议结合后端生成方案。
到此这篇关于Vue3中使用exceljs和file-saver实现Excel导出(含图片导出)功能的文章就介绍到这了,更多相关Vue3导出Excel内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
本文地址: https://www.earthnavs.com/jishuwz/54a9083e3e53f8fcfd2a.html