import * as XLSX from 'xlsx'; export const domToExcel = (dom, name="data") => { const worksheet = XLSX.utils.table_to_sheet(dom); const workbook = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(workbook, worksheet); XLSX.writeFile(workbook, `${name}.xlsx`); } /** * eg: .columns = [ * { header: 'Id', key: 'id', wpx: 10 }, * { header: 'Name', key: 'name', wch: 32 }, * { header: 'D.O.B.', key: 'dob', width: 10, hidden: true } * ] * data: [{id: 1, name: 'John Doe', dob: new Date(1970,1,1)}] * @param columns 定义列属性数组 * @param data 数据 * @param name 文件名 */ export const dataToExcel = (columns = [], data = [], name = 'data') => { const headers = columns.map((item) => item.header); const dataList = data.map((item) => { let obj = {}; columns.forEach(col => { obj[col.header] = getNestedValue(item, col.key) ?? ''; }); return obj; }); const workbook = XLSX.utils.book_new(); // workbook.SheetNames.push(name); const worksheet = XLSX.utils.json_to_sheet(dataList, { header: headers, }); // 自动计算列宽 worksheet['!cols'] = calculateColumnWidths(columns, dataList); // const otherConfigs = columns.map(({ key, header, ...item }) => item); // worksheet['!cols'] = otherConfigs; XLSX.utils.book_append_sheet(workbook, worksheet); XLSX.writeFile(workbook, `${name}.xlsx`); // workbook.Sheets[name] = worksheet; // // 生成Blob数据 // const excelData = XLSX.write(workbook, { type: 'array', bookType: 'xlsx' }); // const blobData = new Blob([excelData], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); // // 创建Blob URL // const blobUrl = URL.createObjectURL(blobData); // // 创建一个隐藏的标签并设置href属性为Blob URL // const link = document.createElement('a'); // link.href = blobUrl; // link.target = '_blank'; // link.download = `${name}.xlsx`; // // 触发点击操作,开始下载文件 // link.click(); // // 释放Blob URL // URL.revokeObjectURL(blobUrl); }; const getNestedValue = (obj, path, defaultValue = '') => { if (!obj || !path) return defaultValue; const keys = path.split('.'); let result = obj; for (const key of keys) { if (result === null || result === undefined) { return defaultValue; } result = result[key]; } return result !== undefined ? result : defaultValue; }; const calculateColumnWidths = (columns, dataList) => { // 确保 dataList 有数据 if (!dataList || dataList.length === 0) { return columns.map(col => ({ wch: 15 })); // 返回默认宽度 } return columns.map(col => { // 固定宽度优先 if (col.wpx) return { wpx: col.wpx }; if (col.wch) return { wch: col.wch }; if (col.width) return { wch: col.width }; const header = col.header || ''; let maxWidth = header.length; // 遍历数据计算最大宽度 for (let i = 0; i < Math.min(dataList.length, 100); i++) { const item = dataList[i]; // 确保使用正确的键名 const value = item[header] !== undefined ? String(item[header]) : ''; if (value.length > maxWidth) { maxWidth = value.length; } } return { wch: Math.min(Math.max(maxWidth + 2, 8), 50) }; }); };