开篇
因最近业务需求,需要实现表格的导出功能,正常表格导出很容易实现自不必提,这里的表格因为是高度定制化的,牵扯到了行的合并,以及配置项的动态列设置(也就是根据配置来增减某些列),以及每个单元格中也会分为三行内容,所以这里的导出会比较麻烦。
具体实现
表格部分代码(这里的单元格我只写了两列)
<el-table :data="currTableData"borderstyle="width: 100%;":max-height="getMaxHeight()":cell-style="CellStyle" @cell-click="handleCellClick"
><!--姓名列--><el-table-column style="background-color: #fff;":align="'center'"prop="userName"label="姓名"fixed/><!--工号--><el-table-column v-for="(item, index) in filteredCfgColumns":key="index"style="background-color: #fff;":align="'center'":prop="item.prop":label="item.label"/><!--这一块牵扯到合并列及周期模式切换后的动态展示需要特殊处理,不要写死--><el-table-column v-for="(date, index) in dateHeaders" :key="index" :align="'center'":class-name="isWeekend(date)":label-class-name="isWeekend(date)"><!--星期几/日期--><template #header><div>{{ getWeekDay(date) }}</div><div>{{ parseDate(date) }}</div></template><!--表格内容 --><template #default="{row}"><div class="cell-content"v-if="row[date]":data-cell-content="JSON.stringify(row[date])":class="`${row[date].cellKey}`"><!-- 第一行 --><div v-if="pageSettingList.includes('显示附加班')" class="row"style="font-size: 8px;min-height: 12px; display: flex; align-items: center;"><el-row style="width: 100%;"><el-col :span="24" style="color: red;font-weight: 600;text-align: right;">{{ row[date]?.attchDetail || '' }}</el-col></el-row></div><!-- 第二行 --><div class="row"style="font-size: 12px;min-height: 20px; display: flex; align-items: center;"><el-row style="width: 100%;"><el-col :span="24" style="font-weight: 600;text-align: center;"><StyledText :colorAndSchedules="colorAndSchedules":styledTexts="row[date]?.mainDetail || ''" /></el-col></el-row></div></div></template></el-table-column>
</el-table>
如上图,这里不仅牵扯到了行的合并,而且每个单元格中的内容也比较复杂。
导出功能实现
const handleExportExcel = async () => {const workbook = new ExcelJS.Workbook();const worksheet = workbook.addWorksheet('表格数据');// 动态生成表头映射const colsMapping = [{ name: '姓名', key: 'userName' }];filteredCfgColumns.value.forEach(item => {colsMapping.push({ name: item.label, key: item.prop });});// 根据表格动态生成日期列const dateHeaders = props.dateHeaders.map(date => ({weekDay: getWeekDay(date),date: parseDate(date),key: date,}));// 生成第1行和第2行的表头内容const headerRow1 = colsMapping.map(col => col.name).concat(dateHeaders.map(date => date.weekDay));const headerRow2 = colsMapping.map(() => '').concat(dateHeaders.map(date => date.date));worksheet.addRow(headerRow1);worksheet.addRow(headerRow2);// 设置第一行和第二行的样式worksheet.getRow(1).alignment = { vertical: 'middle', horizontal: 'center', wrapText: true };worksheet.getRow(2).alignment = { vertical: 'middle', horizontal: 'center', wrapText: true };// 合并表头的姓名列单元格(动态合并)colsMapping.forEach((col, index) => {const cellAddress = String.fromCharCode(65 + index) + '1';const mergeRange = `${cellAddress}:${String.fromCharCode(65 + index)}2`;worksheet.mergeCells(mergeRange);const headerCell = worksheet.getCell(cellAddress);headerCell.alignment = { vertical: 'middle', horizontal: 'center', wrapText: true };});// 添加数据行currTableData.value.forEach(row => {const rowData = colsMapping.map(col => row[col.key]);const details = dateHeaders.map(date => {const cellData = row[date.key] || {};return [cellData.attchDetail || '', cellData.mainDetail || '', cellData.applyDetail || ''];});for (let i = 0; i < 3; i++) {const rowCells = rowData.map((value, index) => index === 0 && i === 0 ? value : '');details.forEach(detail => {rowCells.push(detail[i]);});worksheet.addRow(rowCells);}});// 合并姓名列的单元格并设置样式let rowIndex = 3;currTableData.value.forEach(() => {colsMapping.forEach((col, index) => {const cellAddress = String.fromCharCode(65 + index) + rowIndex;const mergeRange = `${cellAddress}:${String.fromCharCode(65 + index)}${rowIndex + 2}`;worksheet.mergeCells(mergeRange);const cell = worksheet.getCell(cellAddress);cell.alignment = { vertical: 'middle', horizontal: 'center', wrapText: true };});rowIndex += 3;});// 设置列宽colsMapping.forEach((_, index) => {worksheet.getColumn(index + 1).width = 20;});// 导出Excel文件const buffer = await workbook.xlsx.writeBuffer();const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });const link = document.createElement('a');link.href = URL.createObjectURL(blob);link.download = 'table-data.xlsx';link.click();
};
- 这里用到了一个三方库
“exceljs”: “^4.4.0”,
…
import ExcelJS from ‘exceljs’;
导出效果
注
以上便是对于此处导出功能实现的全部逻辑。记录,以便日后使用。
感谢阅读!