import * as XLSX from 'xlsx' /** * 导出Excel文件 * @param {Array} data - 导出的数据 * @param {String} filename - 文件名 * @param {String} sheetName - 工作表名称 */ export const exportToExcel = (data:any, filename:string = 'export.xlsx', sheetName:string = 'Sheet1') => { // 创建工作簿 const wb = XLSX.utils.book_new() // 创建工作表 const ws = XLSX.utils.json_to_sheet(data) // 添加工作表到工作簿 XLSX.utils.book_append_sheet(wb, ws, sheetName) // 导出文件 XLSX.writeFile(wb, filename) } /** * 导出多工作表Excel文件 * @param {Object} sheetData - 包含多个工作表数据的对象 {sheetName1: data1, sheetName2: data2} * @param {String} filename - 文件名 */ export const exportMultiSheetExcel = (sheetData:any, filename:string = 'export.xlsx') => { const wb = XLSX.utils.book_new() // 遍历添加多个工作表 Object.keys(sheetData).forEach(sheetName => { const ws = XLSX.utils.json_to_sheet(sheetData[sheetName]) XLSX.utils.book_append_sheet(wb, ws, sheetName) }) XLSX.writeFile(wb, filename) } /** * 自定义表头的Excel导出 * @param {Array} data - 数据 * @param {Array} headers - 表头配置 [{key: 'name', title: '姓名'}, ...] * @param {String} filename - 文件名 * @param {String} sheetName - 工作表名称 */ export const exportWithCustomHeaders = (data:any, headers:any, filename:string = 'export.xlsx', sheetName:string = 'Sheet1') => { // 准备导出数据,将key映射为title const exportData = data.map(item => { const row = {} headers.forEach(header => { row[header.title] = item[header.key] }) return row }) const wb = XLSX.utils.book_new() const ws = XLSX.utils.json_to_sheet(exportData) XLSX.utils.book_append_sheet(wb, ws, sheetName) XLSX.writeFile(wb, filename) } /** * 高级对象数组处理 - 支持展开模式 * @param {Array} data - 数据 * @param {Array} headers - 表头配置 * 普通字段: {key: 'name', title: '姓名'} * 对象数组展开: { * key: 'projects', * title: '项目', * arrayType: 'object', * expand: true, // 展开模式 * fieldMappings: { // 字段映射 * name: '项目名称', * role: '项目角色' * } * } * @param {String} filename - 文件名 * @param {String} sheetName - 工作表名称 */ export const exportWithExpandedObjectArrays = (data:any, headers:any, filename:string = 'export.xlsx', sheetName:string = 'Sheet1') => { // 首先处理展开的对象数组 let processedData = [...data] let processedHeaders = [...headers] // 找出需要展开的对象数组字段 const expandFields = headers.filter(header => header.arrayType === 'object' && header.expand ) if (expandFields.length > 0) { // 计算每个对象数组的最大长度 expandFields.forEach(field => { const maxLength = Math.max(...data.map(item => { const arr = item[field.key] return Array.isArray(arr) ? arr.length : 0 })) // 移除原始字段 processedHeaders = processedHeaders.filter(h => h.key !== field.key) // 添加展开后的字段 for (let i = 0; i < maxLength; i++) { const baseKey = `${field.key}[${i}]` const baseTitle = `${field.title}[${i + 1}]` if (field.fieldMappings) { // 使用字段映射 Object.keys(field.fieldMappings).forEach(sourceField => { processedHeaders.push({ key: `${baseKey}.${sourceField}`, title: `${baseTitle} - ${field.fieldMappings[sourceField]}` }) }) } else { // 默认所有字段 processedHeaders.push({ key: `${baseKey}`, title: baseTitle }) } } }) // 重新处理数据,展开对象数组 processedData = data.map(item => { const newItem = { ...item } expandFields.forEach(field => { const arr = item[field.key] if (Array.isArray(arr)) { for (let i = 0; i < arr.length; i++) { const obj = arr[i] if (typeof obj === 'object' && obj !== null) { if (field.fieldMappings) { // 使用字段映射 Object.keys(field.fieldMappings).forEach(sourceField => { newItem[`${field.key}[${i}].${sourceField}`] = obj[sourceField] }) } else { // 默认所有字段 Object.keys(obj).forEach(sourceField => { newItem[`${field.key}[${i}].${sourceField}`] = obj[sourceField] }) } } } } }) return newItem }) } // 处理其他字段 const exportData = processedData.map(item => { const row = {} processedHeaders.forEach(header => { if (header.arrayType === 'object' && !header.expand) { // 非展开的对象数组处理 const value = item[header.key] if (Array.isArray(value)) { if (header.extractFields && header.extractFields.length > 0) { const extractedValues = value.map(obj => { if (typeof obj === 'object' && obj !== null) { return header.extractFields.map(field => obj[field]).join(' ') } return obj }) row[header.title] = extractedValues.join(header.joinWith || ', ') } else { const extractedValues = value.map(obj => { if (typeof obj === 'object' && obj !== null) { return Object.keys(obj).map(key => `${key}: ${obj[key]}`).join(' ') } return obj }) row[header.title] = extractedValues.join(header.joinWith || ', ') } } else { row[header.title] = value } } else if (!header.expand) { // 普通字段或普通数组 const value = item[header.key] if (Array.isArray(value)) { row[header.title] = value.join(header.joinWith || ', ') } else { row[header.title] = value } } else { // 展开的字段,直接使用 row[header.title] = item[header.key] } }) return row }) const wb = XLSX.utils.book_new() const ws = XLSX.utils.json_to_sheet(exportData) XLSX.utils.book_append_sheet(wb, ws, sheetName) XLSX.writeFile(wb, filename) }