告别后端导出!前端Excel导出终极方案:el-table数据+图片完美融合,点击即下载
- 2026-09-24 21:53:37
告别后端导出!前端Excel导出终极方案:el-table数据+图片完美融合,点击即下载优点:轻量级,纯数据导出速度快缺点:不支持图片插入,样式控制弱❌ 优点:支持模板,功能强大缺点:体积较大(1MB+),学习成本高❌ 综合评分:★★★★★推荐理由:功能全面、文档完善、社区活跃、体积适中 3.2 两步走,分别导出表格数据和图片 3.3 核心功能解析 4.图表插入
一、为什么前端导出Excel这么难?
最近在项目中遇到了一个需求:将el-table中的数据导出为Excel,并且要在表格下方插入图片。
💡听起来很简单?实际开发中却遇到了这些问题:
图片处理难题:前端如何将图片插入到Excel中?
跨域限制:图片来自CDN,存在跨域问题
性能瓶颈:当数据量达到5000条时,浏览器直接卡死
格式混乱:导出的Excel列宽不一致,样式丑陋
传统的解决方案是让后端生成Excel文件,但这样会增加服务器压力,用户体验也不好。难道前端真的不能优雅地解决这个问题吗?
当然可以! 经过一周的探索和实践,我终于找到了一套完美的前端Excel导出方案!
二、方案对比
✨ 在找到最佳方案前,我们先看看常见的几种方案:
方案1:后端生成(传统方案)
// 前端请求后端接口axios.post('/api/export-excel', { data })
优点:功能强大,支持复杂格式缺点:服务器压力大,响应慢,用户体验差❌
方案2:SheetJS(社区版)
import XLSX from 'xlsx';XLSX.writeFile(workbook, '导出.xlsx');
方案3:xlsx-populate
// 可以操作已有的Excel模板workbook.toFileAsync('输出.xlsx');
方案4:exceljs(我们的选择)✅
import ExcelJS from 'exceljs';// 功能全面,支持图片、样式、公式等
三、核心实现:手把手教你实现el-table数据+图片导出
<el-button type="primary" @click="handleExport">导出</el-button>3.1 安装依赖
# 安装exceljs和文件保存工具npm install exceljs file-saver# 可选:如果处理大量数据,安装lodash提高性能npm install lodash
const handleExport = async () => {const tableRef = this.$refs['tableRef'];// 表头和数据let tableHeaders = [];let tableRows = [];const myChart = this.$refs['lineRef'].$refs['luEchartLine'].myChart;// 获取图表的 base64 URLlet imgDataURL = myChart.getDataURL({type: 'png', // 可以是 'png', 'jpeg' 等pixelRatio: 2, // 图片分辨率比例,默认为1backgroundColor: '#fff' // 背景颜色});const workbook = new ExcelJS.Workbook();const worksheet = workbook.addWorksheet('Sheet1');if(tableRef) {tableHeaders = tableRef.columns.map(col => col.label);tableRows = tableRef.data;} else {throw new Error('请提供列配置或tableRef');}// 添加表头const headerRow = worksheet.addRow(tableHeaders);headerRow.font = { bold: true };// headerRow.fill = {// type: 'pattern',// pattern: 'solid',// fgColor: { argb: '4472C4' }// };headerRow.alignment = { horizontal: 'center' };// 添加数据行tableRows.forEach(rowData => {console.log('rowData', rowData);const rowValue = tableRef.columns.map(col => {const value = rowData[col.property];return value;});worksheet.addRow(rowValue);});// 7. 自动调整列宽worksheet.columns.forEach((column, index) => {let maxLength = 0;column.eachCell({ includeEmpty: true }, cell => {const cellLength = cell.value ? cell.value.toString().length : 0;if(cellLength > maxLength) {maxLength = cellLength;}});column.width = Math.min(Math.max(maxLength, 10), 50);});const imageId = workbook.addImage({buffer: this.base64ToArrayBuffer(imgDataURL),extension: 'png',});console.log(imageId, 'imageId');// 指定图片位置(从B2单元格开始)worksheet.addImage(imageId, {tl: { col: 0, row: tableRows.length + 2, offsetX: 0, offsetY: 0 },br: { col: 16, row: tableRows.length + 16, offsetX: 0, offsetY: 0 }});// 生成文件const buffer = await workbook.xlsx.writeBuffer();// 下载const blob = new Blob([buffer], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});// FileSaver.saveAs(blob, '导出.xlsx');const url = URL.createObjectURL(blob);const a = document.createElement('a');a.href = url;a.download = '导出.xlsx';a.click();}
base64ToArrayBuffer(base64Str) {// 移除数据URI前缀(如果存在)并清理空白字符base64Str = base64Str.replace(/^data:.+;base64,/, '').replace(/\s/g, '');// 补充填充字符const padding = '='.repeat((4 - base64Str.length % 4) % 4);const base64 = base64Str + padding;// 解码并转换const binaryString = atob(base64);const bytes = new Uint8Array(binaryString.length);for (let i = 0; i < binaryString.length; i++) {bytes[i] = binaryString.charCodeAt(i);}return bytes.buffer;},
- 数据获取
通过 this.$refs获取表格组件和图表实例。图表通过 getDataURL()获取base64格式的PNG图片。表头数据和表格数据通过 tableRef.columns和tableRef.data获取- Excel生成
使用ExcelJS库创建工作簿(workbook)和工作表(worksheet) 自动根据内容长度调整列宽(10-50字符限制) 表格数据按行插入,表头加粗居中 - 图表插入
将base64图片转为ArrayBuffer后插入 图片位置通过 tl(左上角)和br(右下角)坐标控制图片放置在表格数据下方(行号=数据行数+2)
Blob生成Excel文件并创建a标签下载 通过FileSaver.saveAs()下载
本文来自网友投稿或网络内容,如有侵犯您的权益请联系我们删除,联系邮箱:wyl860211@qq.com 。