目录
一、安装必要的库:
首先,你需要安装一个能够将数据转换为Excel文件的库。常用的库有xlsx和file-saver。
npm install xlsx file-saver
二、引入库:
下面有两种引入方法,区别就是引入地方不同,作用域不同,本篇文章后续使用全局引入写法,注意区别。
1.全局引入
在main.js文件中全局配置
// vue中导出excel表格模板
import FileSaver from 'file-saver'
import * as XLSX from 'xlsx';
//import XLSX from 'xlsx' //无效导入,XLSX是undefined
// 将excel表格模板设置全局
Vue.prototype.$FileSaver = FileSaver;
Vue.prototype.$XLSX = XLSX;
注意:这里XLSX的引入方式不是
import XLSX from 'xlsx'
而是import * as XLSX from 'xlsx'
,如果是import XLSX from 'xlsx'
写法,那么XLSX
打印内容是undefined,网上有import XLSX from 'xlsx'
的写法,可能是因为xlsx版本问题。
2.局部组件引入
import * as XLSX from 'xlsx';
import { saveAs } from 'file-saver';
三、编写导出逻辑函数:
1.方法一:利用XLSX中的json_to_sheet函数
//部分代码:
//已经全局导入xlsx和file-saver
exportHandle(){
// 将表格数据转换为工作表;
const worksheet = this.$XLSX.utils.json_to_sheet(this.ListTable);//this.ListTable是你定义的table表格数据
// 创建工作簿
const workbook = this.$XLSX.utils.book_new();
this.$XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
// 生成Excel文件
const excelBuffer = this.$XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
// 保存文件
const data = new Blob([excelBuffer], { type: 'application/octet-stream' });
this.$FileSaver.saveAs(data, '列表数据.xlsx');
}
将上面函数exportHandle绑定为导出按钮的点击事件函数,其中
this.ListTable
是你的表格数据。
注意:执行上面函数导出方法后你会发现导出的表格表头内容是你定义的英文变量名并不是table组件的label属性值;
如下图所示:
那么就需要对table数据进行处理,将table数据在导出excel时,将英文变量名替换成中文。
1.方法一调整:利用XLSX中的json_to_sheet函数 + 英文表头装换;
将上面代码做以下调整:
//data(){}中table数据示例如下:
staListTableData: [
{
certificationCategory: '不认证',
noise: '10%',
acceptNoiseRatio: '19.5%'
},
{
certificationCategory: '不认证',
noise: '10%',
acceptNoiseRatio: '19.5%'
}, {
certificationCategory: '不认证',
noise: '10%',
acceptNoiseRatio: '19.5%'
}, {
certificationCategory: '不认证',
noise: '10%',
acceptNoiseRatio: '19.5%'
}
],
//method方法
exportHandle(){
//表头数据切换
const changeTableHead = (
tableData = [],
// 表头数据转换,可根据需要更改
// 列举表格数据的中文枚举对象
fieldName = {
certificationCategory: '认证类别',
noise: '接受噪声(Noise)',
acceptNoiseRatio: '接受信噪比'
}
) => {
const list = tableData.map((item) => {
const obj = {};
for (const k in item) {
if (fieldName[k]) {
obj[fieldName[k]] = item[k];
}
}
return obj;
});
return list;
};
//表头数据切换,即把英文名字改为中文名字
//调用changeTableHead函数,将table数据作为参数传入,返回一个以中文名称为键值的对象数组
const list = changeTableHead(this.staListTableData); // +
//list的结构如下:
// [
// {
// '认证类别': '不认证',
// '接受噪声(Noise)': '10%',
// '接受信噪比': '19.5%'
// }
//]
//
// 将表格数据转换为工作表;
const worksheet = this.$XLSX.utils.json_to_sheet(list);
// 创建工作簿
const workbook = this.$XLSX.utils.book_new();
this.$XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
// 生成Excel文件
const excelBuffer = this.$XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
// 保存文件
const data = new Blob([excelBuffer], { type: 'application/octet-stream' });
this.$FileSaver.saveAs(data, '用户列表.xlsx');
}
2.方法二:利用XLSX中的table_to_book函数
利用
table_to_book
,需要获取DOM,所以先给table组件绑定id选择器(或类选择器,VUE自带 ref 没有尝试,可以试一试理论上一样),如下图所示:
//部分代码:
//已经全局导入xlsx和file-saver
exportHandle(){
var xlsxParam = { raw: true }; // 导出的内容只做解析,不进行格式转换
let tables = document.getElementById('table_excel'); //这里是绑定元素,输入你要导出的table表格的id
let table_book = this.$XLSX.utils.table_to_book(tables, xlsxParam);
const table_write = this.$XLSX.write(table_book, {
bookType: 'xlsx',
bookSST: true,
type: 'array'
});
try {
this.$FileSaver.saveAs(
new Blob([table_write], { type: 'application/octet-stream' }),
`列表数据.xlsx` //这里是文件名
);
} catch (e) {
if (typeof console !== 'undefined') console.log(e, table_write);
}
return table_write;
}
执行导出功能函数后表格结果如下:
重点:注意了!注意了!注意了注意了注意了注意了
首先说明上面导出的excel表为什么会把table数据导出两次?
之所以在一次导出功能中excel表出现两次重复数据,是因为你的table组件中el-table-column
使用了flexd
属性,如果你没有使用fixed
属性,那么就不会出现两次重复数据。
flexd
属性:
table组件-固定行或固定列的实现再DOM层面会复制一份table表格html内容;如下图所示;
因为table_to_sheet
实现导出功能的原理是:将HTML中的table元素转换为Excel工作表。它需要HTML表格元素作为输入,并处理这些表格元素来生成Excel文件。所以在使用固定列fixed
属性后,两个table html元素就会导致一个excel中导出重复的数据。
分析了问题,原因那么列举如下解决方案:
2.方法二调整:利用XLSX中的table_to_book函数
调整方案1:在使用table_to_book时规避flexd的使用;
调整方案2:动态删减重复table元素;
思路:在执行导出函数前先判断table组件是否有fixed属性,也就是看是否有复制的html table元素,然后如果有的情况先通过DOM操作,将其移除,然后再导出excel表格后再将 移除的DOM添加回去,规避重复数据问题。
具体调整后的代码如下:
exportHandle(){
var xlsxParam = { raw: true }; // 导出的内容只做解析,不进行格式转换
let fixDOM = document.querySelector('#table_excel .el-table__fixed-right');
// .el-table__fixed-right 类名是 fixed属性复制的table组件上的 类名
// fixDOM是flexd属性复制的table组件DOM
let table_book;
if (fixDOM) {
//判断要导出的节点中是否有fixed的表格,如果有,转换excel时先将该dom移除,然后append回去
table_book = this.$XLSX.utils.table_to_book(document.getElementById('table_excel').removeChild(fixDOM), xlsxParam);
//table_book 是移除fixed表格后的 实际表格DOM
document.getElementById('table_excel').appendChild(fixDOM);
//再将移除的fixed表格DOM添加回去
} else {
//如果没有fixed表格就直接执行
table_book = this.$XLSX.utils.table_to_book(document.getElementById('table_excel'), xlsxParam);
}
const table_write = this.$XLSX.write(table_book, {
bookType: 'xlsx',
bookSST: true,
type: 'array'
});
try {
this.$FileSaver.saveAs(
new Blob([table_write], { type: 'application/octet-stream' }),
`列表数据.xlsx` //这里是文件名
);
} catch (e) {
if (typeof console !== 'undefined') console.log(e, table_write);
}
return table_write;
}
运行后:导出文件如下:
通过调整处理后,导出数据就正常了
但是你会发现如果表格最后一列有操作按钮列,那么也会被导出,这个时候如果有所影响的话,可以手动删除表格中的内容,或者通过DOM操作再将其移除再添加,或使用第一种导出方式。
四、拓展:json_to_sheet 和table_to_sheet的区别
json_to_sheet和table_to_sheet的主要区别在于它们处理的数据源不同,以及它们在转换过程中对数据的处理方式不同。
-
数据源不同:
json_to_sheet:将一个由对象组成的数组转换为Excel工作表。这意味着它直接处理JSON格式的数据。
table_to_sheet:将HTML中的table元素转换为Excel工作表。它需要HTML表格元素作为输入,并处理这些表格元素来生成Excel文件。 -
数据处理方式不同:
json_to_sheet:直接处理JSON数据,将其转换为Excel工作表。这种转换方式适用于已经以JSON格式组织好的数据。
table_to_sheet:处理HTML表格元素,自动识别colspan和rowspan,并将其转换为对应的单元格合并。这种方式适用于从HTML页面中提取表格数据并转换为Excel。 -
应用场景不同:
json_to_sheet:适用于后端或前端应用中,已经以JSON格式存储或传输的数据。例如,从API获取的数据可以直接使用json_to_sheet转换为Excel。
table_to_sheet:适用于需要将网页上的表格数据导出为Excel的情况。例如,用户可以在网页上填写表格,然后使用table_to_sheet将填写的内容导出为Excel文件。 -
导出结果不同:
json_to_sheet:根据数据导出,不能直接导出汉字表头,需要中间自行做转换。
table_to_sheet:根据html结构内容导出,如遇额外不需要的表格或者列数据,需要单独做处理。