99 lines
3.3 KiB
JavaScript
99 lines
3.3 KiB
JavaScript
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);
|
|
// // 创建一个隐藏的<a>标签并设置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) };
|
|
});
|
|
}; |