import * as XLSX from 'xlsx-js-style'; // 另一种常见的导入方式 export const exportToExcel = (headers, list, fileName) => { // 定义自定义表头和数据映射 const headerData = headers.filter(item => !item.noExport).map(item => item.label); const bodyData = list.map(item => { let itemList = [] headers.forEach(header => { if (header.noExport) return itemList.push(item[header.value]) }) return itemList }); // 将表头和数据体组合成一个二维数组 const allData = [headerData, ...bodyData]; // 使用 aoa_to_sheet 方法,它接受二维数组 const ws = XLSX.utils.aoa_to_sheet(allData); const headerStyle = { font: { bold: true, sz: 12 }, alignment: { horizontal: 'center', vertical: 'center' }, } // 数据单元格样式:居中 const cellStyle = { alignment: { horizontal: 'center', vertical: 'center' } } // 3. 计算并设置列宽(核心:最大宽度限制下的自适应) const maxWidth = 30 // 设置最大列宽(单位:字符数) const colWidths = [] // 遍历每一列计算最大宽度 for (let col = 0; col < allData[0].length; col++) { let maxLen = 10 // 默认最小宽度 for (let row = 0; row < allData.length; row++) { const value = allData[row][col] if (value != null) { // 计算单元格内容长度(中文按2个字符算) let len = 0 const str = value.toString() for (let i = 0; i < str.length; i++) { const charCode = str.charCodeAt(i) len += (charCode > 255) ? 2 : 1 // 中文字符算2个宽度 } if (len > maxLen) maxLen = len } } // 应用最大宽度限制 colWidths.push({ wch: Math.min(maxLen + 2, maxWidth) }) } ws['!cols'] = colWidths // 4. 应用样式到所有单元格 const range = XLSX.utils.decode_range(ws['!ref']) for (let R = range.s.r; R <= range.e.r; R++) { for (let C = range.s.c; C <= range.e.c; C++) { const cellAddress = { c: C, r: R } const cellRef = XLSX.utils.encode_cell(cellAddress) if (!ws[cellRef]) ws[cellRef] = {} // 确保单元格存在 if (!ws[cellRef].s) ws[cellRef].s = {} // 确保样式对象存在 // 第一行(表头)应用headerStyle,其他行应用cellStyle ws[cellRef].s = R === 0 ? { ...ws[cellRef].s, ...headerStyle } : { ...ws[cellRef].s, ...cellStyle } } } // ... 后续创建工作簿和导出的步骤同上 const workbook = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(workbook, ws, 'Sheet1'); // 3. 生成Excel文件并保存 XLSX.writeFile(workbook, `${fileName || '导出数据'}.xlsx`); // 使用xlsx库的writeFile方法 };