纯前端导出表格数据 -- csv格式 (含表格末尾的自动合计行)
核心代码详见代码中的注释
<template>
<div class="page">
<el-button type="primary" size="small" @click="exportOut">导出</el-button>
<div class="tableBox">
<el-table
:data="tableData"
border
:summary-method="getSummaries"
show-summary
>
<el-table-column
v-for="(item, index) in tableTitleList"
:key="index"
:prop="item.prop"
:label="item.label"
:width="item.width"
align="center"
>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script>
export default {
data() {
return {
sumRow: {},
tableTitleList: [
{
label: "序号",
prop: "id",
width: 100,
},
{
label: "姓名",
prop: "name",
},
{
label: "射击次数",
prop: "total",
},
{
label: "命中次数",
prop: "hitNum",
},
{
label: "命中率",
prop: "hitRate",
},
],
tableData: [
{
id: "1",
name: "张三",
total: 100,
hitNum: 10,
hitRate: "10%",
},
{
id: "2",
name: "王五",
total: 100,
hitNum: 20,
hitRate: "20%",
},
],
};
},
methods: {
// 导出为 csv 格式的文件
exportOut() {
// 生成时间戳,避免每次导出的文件重名
let timeStamp = new Date().getTime();
// 在数据末尾添加合计行
let data = [...this.tableData, this.sumRow];
downloadCsv(this.tableTitleList, data, `导出的数据_${timeStamp}.csv`);
},
// 自定义末尾的合计逻辑
getSummaries(param) {
const { columns, data } = param;
const sumDic = {};
columns.forEach((column, index) => {
// 第 1 列
if (index === 0) {
sumDic[column.property] = "合计";
return;
}
// 需特殊计算的列
if (column.property === "hitRate") {
sumDic[column.property] =
((sumDic["hitNum"] / sumDic["total"]) * 100).toFixed(2) + "%";
return;
}
// 其他列默认求和
const values = data.map((item) => Number(item[column.property]));
if (!values.every((value) => isNaN(value))) {
// 可以求和的列
sumDic[column.property] = values.reduce((prev, curr) => {
const value = Number(curr);
if (!isNaN(value)) {
return prev + curr;
} else {
return prev;
}
}, 0);
} else {
// 无法求和的列
sumDic[column.property] = "——";
}
});
// 指定列添加单位
sumDic["total"] += " 次";
sumDic["hitNum"] += " 次";
// 获取末尾的合计行
this.sumRow = sumDic;
return Object.values(sumDic);
},
},
};
// 纯js导出 csv 格式文件
function downloadCsv(header, data, fileName = "导出结果.csv") {
if (
!header ||
!data ||
!Array.isArray(header) ||
!Array.isArray(data) ||
!header.length ||
!data.length
) {
return;
}
var csvContent = "data:text/csv;charset=utf-8,\ufeff";
const _header = header.map((h) => h.label).join(",");
const keys = header.map((item) => item.prop);
csvContent += _header + "\n";
data.forEach((item, index) => {
let dataString = "";
for (let i = 0; i < keys.length; i++) {
dataString += item[keys[i]] + ",";
}
csvContent +=
index < data.length
? dataString.replace(/,$/, "\n")
: dataString.replace(/,$/, "");
});
const a = document.createElement("a");
a.href = encodeURI(csvContent);
a.download = fileName;
a.click();
window.URL.revokeObjectURL(csvContent);
}
</script>
<style scoped>
.page {
padding: 30px;
}
.tableBox {
margin: 20px 0px;
}
</style>