import FileSaver from 'file-saver'
|
import * as XLSX from 'xlsx'
|
// 自动计算col列宽
|
function auto_width(ws, data) {
|
/*set worksheet max width per col*/
|
const colWidth = data.map(row => row.map(val => {
|
/*if null/undefined*/
|
if (val == null) {
|
return { 'wch': 10 }
|
}
|
/*if chinese*/
|
else if (val.toString().charCodeAt(0) > 255) {
|
return { 'wch': val.toString().length * 2 }
|
} else {
|
return { 'wch': val.toString().length }
|
}
|
}))
|
/*start in the first row*/
|
let result = colWidth[0]
|
for (let i = 1; i < colWidth.length; i++) {
|
for (let j = 0; j < colWidth[i].length; j++) {
|
if (result[j]['wch'] < colWidth[i][j]['wch']) {
|
result[j]['wch'] = colWidth[i][j]['wch']
|
}
|
}
|
}
|
ws['!cols'] = result
|
}
|
// 将json数据转换成数组
|
function json_to_array(key, jsonData) {
|
return jsonData.map(v => key.map(j => {
|
return v[j]
|
}))
|
}
|
/**
|
* @param header Object,表头
|
* @param data Array,表体数据
|
* @param key Array,字段名
|
* @param title String,标题(会居中显示),即excel表格第一行
|
* @param filename String,文件名
|
* @param autoWidth Boolean,是否自动根据key自定义列宽度
|
*/
|
export const exportJsonToExcel = ({
|
header,
|
data,
|
key,
|
title,
|
filename,
|
autoWidth
|
}) => {
|
const wb = XLSX.utils.book_new()
|
if (header) {
|
data.unshift(header)
|
}
|
if (title) {
|
data.unshift(title)
|
}
|
const ws = XLSX.utils.json_to_sheet(data, {
|
header: key,
|
skipHeader: true
|
})
|
// 合并单元格以覆盖整个第一行
|
// ws['!merges'] = [{ s: {r:0, c:0}, e: {r:0, c:header.length - 1} }];
|
if (autoWidth) {
|
const arr = json_to_array(key, data)
|
auto_width(ws, arr)
|
}
|
XLSX.utils.book_append_sheet(wb, ws, filename)
|
XLSX.writeFile(wb, filename + '.xlsx')
|
}
|
|
/**
|
* 自动计算并设置列宽
|
* @param {Object} ws - 工作表对象
|
* @param {Array} data - 表格数据(二维数组)
|
*/
|
function autoWidth(ws, data) {
|
// 初始化每列宽度为默认值10
|
const colWidths = Array(data[0].length).fill(10);
|
|
// 遍历数据以计算最大宽度
|
data.forEach(row => {
|
row.forEach((val, index) => {
|
let length = val ? (typeof val === 'string' ? getStrLen(val) : String(val).length) : 10;
|
if (colWidths[index] < length) {
|
colWidths[index] = length; // 更新最大宽度
|
}else{
|
colWidths[index] = 20; // 更新最大宽度
|
}
|
});
|
});
|
|
// 设置列宽
|
ws['!cols'] = colWidths.map(width => ({ wch: width }));
|
}
|
/**
|
* 计算字符串长度,考虑多字节字符(如中文)
|
* @param {string} str - 输入字符串
|
* @returns {number} 字符串长度
|
*/
|
function getStrLen(str) {
|
return [...str].reduce((len, char) => len + (char.charCodeAt(0) > 255 ? 2 : 1), 0);
|
}
|
export const exportTableToExcel=(divId:string,name:string)=>{
|
var wb = XLSX.utils.table_to_book(document.querySelector(divId));//关联dom节点
|
console.log(wb)
|
// 获取第一个工作表
|
const ws = wb.Sheets[wb.SheetNames[0]];
|
|
// 获取表格数据作为二维数组
|
const data = XLSX.utils.sheet_to_json(ws, { header: 1 });
|
|
// 设置列宽
|
autoWidth(ws, data);
|
var wbout = XLSX.write(wb, {
|
bookType: 'xlsx',
|
bookSST: true,
|
type: 'array'
|
})
|
try {
|
FileSaver.saveAs(new Blob([wbout], {
|
type: 'application/octet-stream'
|
}), `${name}.xlsx`)//自定义文件名
|
} catch (e) {
|
if (typeof console !== 'undefined') console.log(e, wbout);
|
}
|
return wbout
|
}
|
|
export const exportTableToExcel2 = async (divId: string, name: string): Promise<Uint8Array | null> => {
|
try {
|
// 关联 DOM 节点
|
const tableElement = document.querySelector(divId);
|
if (!tableElement) {
|
console.error("Table element not found");
|
return null;
|
}
|
|
// 转换表格为工作簿
|
const wb = XLSX.utils.table_to_book(tableElement);
|
console.log(wb);
|
|
// 将工作簿写入文件
|
const wbout = XLSX.write(wb, {
|
bookType: 'xlsx',
|
bookSST: true,
|
type: 'array',
|
});
|
|
// 保存文件
|
await new Promise<void>((resolve, reject) => {
|
try {
|
FileSaver.saveAs(
|
new Blob([wbout], { type: 'application/octet-stream' }),
|
`${name}.xlsx`
|
);
|
resolve();
|
} catch (e) {
|
console.error("Error saving file:", e);
|
reject(e);
|
}
|
});
|
|
// 返回生成的二进制数组
|
return wbout;
|
} catch (error) {
|
console.error("Error exporting table to Excel:", error);
|
return null;
|
}
|
};
|
export default {
|
exportJsonToExcel,
|
exportTableToExcel
|
}
|