文章目录
前言
开发过程中,后端反馈无法实现导出的Excel表格文件宽度根据数据进行宽度自适应,故实现此方案。
- 前端根据返回数据结合表格字头实现导出下载Excel文件,Excel文件每列的宽度根据数据长度进行自适应。
- 还可以增加最后一行的 "合计" 数据。
- 还可以自定义Excel表格的文件名称。
一、导出效果

二、直接上代码
方法如下:
js
/**
* 表格导出(自适应导出列)
* params
* title: 标题
* tableData 表格数据
* columns 表头展示列 如:[{ label: '单位名称', prop: 'ZGDWMC' }]
* removeProps 导出表格去除列 如 ['ZGDWMC', 'JDJC'] 会过滤掉 ZGDWMC 和 JDJC
* sumObj
* bottomSum 是否需要底部合计
*/
export const adaptiveTableExport = (params = {}, sumObj = { bottomSum: false }) => {
if(!params.tableData) return console.log('没有表格数据!');
if(!params.columns) return console.log('没有自定义表头展示列!');
const excel = XLSX.utils.book_new();
let demo = [];
let columns = deepClone(params.columns);
let tableData = deepClone(params.tableData);
// 删除去除列
if(params.removeProps){
columns = params.columns.filter(item => {
if(!params.removeProps.includes(item.prop)){
return item;
}
})
}
// 判断是否需要合计添加合计列
if(sumObj.bottomSum && tableData.length > 0){
let sums = {};
columns.forEach((column, index) => {
if (index === 0) {
sums[columns[index].prop] = '合计';
return;
}
const values = tableData.map(item => Number(item[column.prop]));
if (!values.every(value => isNaN(value))) {
sums[columns[index].prop] = values.reduce((prev, curr) => {
const value = Number(curr);
if (!isNaN(value)) {
return prev + curr;
} else {
return prev;
}
}, 0);
sums[columns[index].prop] += '';
} else {
sums[columns[index].prop] = '0';
}
});
tableData.push(sums);
}
// 开始计算
if(tableData.length > 0){
for (let i = 0; i < tableData.length; i++) {
const object = tableData[i];
let obj = {}
for (const key in object) {
if (Object.hasOwnProperty.call(object, key)) {
for (let index = 0; index < columns.length; index++) {
const element = columns[index];
obj[element.label] = String(object[element.prop]) || ' '
}
}
}
demo.push(obj);
}
} else {
let obj = {};
for (let index = 0; index < columns.length; index++) {
const element = columns[index];
obj[element.label] = element[element.label] || ' ';
}
demo.push(obj);
}
let data = XLSX.utils.json_to_sheet(demo, {});
data["A1"].s = {
font: {
bold: true,
},
alignment: {
horizontal: "center",
vertical: "center",
},
};
// 1.所有表头的宽度
const headsWidth = Object.keys(demo[0]).map((value) => {
if (/.*[\u4e00-\u9fa5]+.*$/.test(value)) {
return parseFloat(value.toString().length * 2.1);
} else {
return parseFloat(value.toString().length * 1.1)
}
});
// 2.所有表体值的宽度
const rowsWidth = demo.map((item) => {
// 每行数据中值的宽度
const maxValue = Object.values(item).map((value, index) => {
let valueWidth;
if (/.*[\u4e00-\u9fa5]+.*$/.test(value)) {
valueWidth = parseFloat(value.toString().length * 2.1);
} else {
if (value) {
valueWidth = parseFloat(value.toString().length * 1.1);
}
}
// 对比出表头和表体值的最大数
return Math.max(valueWidth, headsWidth[index]);
});
return maxValue;
})
// 3.对比每列最大值
let aotuWidth = []
rowsWidth.map((row, index) => {
let maxWidth = [];
row.map((value, i) => {
if (index === 0) {
maxWidth.push({
wch: value
});
} else {
maxWidth.push({
wch: Math.max(value, aotuWidth[i].wch)
})
}
})
aotuWidth = maxWidth;
});
// 4.给excel设置自适应宽度
data["!cols"] = aotuWidth;
XLSX.utils.book_append_sheet(excel, data);
XLSX.writeFile(excel, `${ params.title || '自适应表格导出' }.xlsx`);
}
三、感谢
如果觉得有用欢迎点赞关注收藏。
有问题私信我!!~~