/* eslint-disable */ /** 导出Excel需要依赖 * npm install xlsx file-saver -S * npm install script-loader -S -D */ import ExcelJS from 'exceljs'; import FileSaver from 'file-saver'; // export default exportExcel; // 导出excel文件 /** * * @param {*} tableColumns 表头 * @param {*} data 数据 * @param {*} fillName 文件名 * @param {*} isMerge 是否合并单元格 * @param {*} firstKey 第一个字段的key,用来判断序号列是否合并 * @param {*} start 合并单元格开始列 * @param {*} end 合并单元格结束列 * @returns */ export function exportExcel (tableColumns,data,fillName,isMerge = false, firstKey = '',start = 0, end = 0) { debugger if (!data || data.length == 0) { return; } if (isMerge) { // 需要合并序号 for (let i = 0; i < data.length; i++) { // 自定义单元格内容,这里返回序号 if (i == 0) { data[i].index = 1; // return 1; } else if (data[i - 1][firstKey] == data[i][firstKey]) { data[i].index = data[i - 1].index; // return data.value[index].index; } else { data[i].index = data[i - 1].index + 1; } } } else { // 不需要合并序号 for (let i = 0; i < data.length; i++) { data[i].index = i + 1; } } // 创建工作簿 const workbook = new ExcelJS.Workbook(); // 添加工作表,名为sheet1 const sheet1 = workbook.addWorksheet('sheet1'); // 导出的表头名 let tHeader = ['序号']; // 字段名 let filterVal = ['index']; // 表格columns let columns = [{ header: '序号', key: 'index', width: 10 }]; for (let i = 0; i < tableColumns.length; i++) { if (tableColumns[i].dataIndex) { tHeader.push(tableColumns[i].title); filterVal.push(tableColumns[i].dataIndex); columns.push({ header: tableColumns[i].title, key: tableColumns[i].dataIndex, width: tableColumns[i].width ? tableColumns[i].width / 5 : 20, }); } } //传入的数据 const list = data; //格式化数据 const datas = formatJson(filterVal, list); // 获取表头所有键 // const headers = Object.keys(data[0]); // 获取表头 sheet1.columns = columns; // 将数据写入工作表 datas.forEach((row) => { // const values = Object.values(row); sheet1.addRow(row); }); // 判断是否合并单元格 if (isMerge) { // 遍历列,从 start 列到 end 列 for (let col = start; col <= end; col++) { for (let row = 3; row <= datas.length + 1; row++) { const currentCellValue = sheet1.getCell(row, col).value; const previousCellValue = sheet1.getCell(row - 1, col).value; // 从第二列开始就要看前一列是否已经合并 let isMerged = true if (col > 1) { isMerged = ifMerged(sheet1,row - 1, col-1,row, col-1) } if (currentCellValue === previousCellValue && isMerged) { // 检查是上边需要合并的单元格是否已经合并 const mergeInfo = getMergeInfo(sheet1, row - 1, col) if ( mergeInfo.isMerged ) { sheet1.unMergeCells( mergeInfo.startRow, col, row - 1, col); sheet1.mergeCells(mergeInfo.startRow, col, row, col); } else { sheet1.mergeCells(row, col, row - 1, col); } } } } } // 修改所有单元格样式 // 遍历每一行 sheet1.eachRow((row, rowNumber) => { // 遍历每个单元格 row.eachCell((cell) => { // 设置边框样式 cell.border = { top: { style: 'thin' }, left: { style: 'thin' }, bottom: { style: 'thin' }, right: { style: 'thin' }, }; // 设置居中对齐 cell.alignment = { vertical: 'middle', horizontal: 'center', }; }); }); // 获取标题行数据 const titleCell = sheet1.getRow(1); // 设置行高为30 titleCell.height = 30; // 设置标题行单元格样式 titleCell.eachCell((cell) => { // 设置标题行背景颜色为黄色 cell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFFFFF' }, }; // 设置标题行字体 cell.font = { // color: { argb: 'FF0000' }, //颜色为红色 bold: true, // 字体粗体 size: 18, // 设置字体大小为18 }; }); // 获取第二行到最后一行的内容数据 const bodyRows = sheet1.getRows(2, sheet1.rowCount); // 处理内容行的数据 bodyRows.forEach((bodyRow) => { // 设置行高为20 bodyRow.height = 20; bodyRow.eachCell((cell) => { cell.font = { size: 16, // 设置内容行字体大小为16 }; }); }); // 导出表格文件 workbook.xlsx .writeBuffer() .then((buffer) => { let file = new Blob([buffer], { type: 'application/octet-stream' }); FileSaver.saveAs(file, fillName + '.xlsx'); }) .catch((error) => console.log('Error writing excel export', error)); }; /** * 格式化表格数据 * @filterVal 格式头 * @jsonData 用来格式化的表格数据 */ function formatJson (filterVal, jsonData) { return jsonData.map((v) => filterVal.map((j) => v[j])); }; /** * 获取给定行和列的单元格是否为合并单元格,并返回合并起始行 * @param {Worksheet} worksheet - ExcelJS 工作表对象 * @param {number} row - 单元格的行号 (从 1 开始) * @param {number} col - 单元格的列号 (从 1 开始) * @returns {Object} - 返回一个对象,包含 isMerged 和 startRow 属性 */ function getMergeInfo(worksheet, row, col) { // 遍历所有的合并范围 for (const mergeRange in worksheet._merges) { if (worksheet._merges.hasOwnProperty(mergeRange)) { const { top, left, bottom, right } = worksheet._merges[mergeRange]; // 检查行列是否在当前合并范围内 if (row >= top && row <= bottom && col >= left && col <= right) { return { isMerged: true, startRow: top }; // 找到合并范围,返回合并信息 } } } return { isMerged: false, startRow: null }; // 单元格不在任何合并范围内 } // 函数:检查两个单元格是否属于同一个合并区域 function ifMerged(worksheet, row1, col1, row2, col2) { const merges = worksheet._merges; // 获取所有的合并区域 for (let mergeAddress in merges) { const mergeRange = merges[mergeAddress]; const { top, left, bottom, right } = mergeRange; const isCell1InRange = (row1 >= top && row1 <= bottom && col1 >= left && col1 <= right); const isCell2InRange = (row2 >= top && row2 <= bottom && col2 >= left && col2 <= right); if (isCell1InRange && isCell2InRange) { return true; } } return false; }