需求
原本项目里导出都是后端写的接口,有某个业务页面table的内容需求前端导出到Excel即可。需要导出全部数据非当前页,无其他要求。
安装
cnpm install xlsx --save-dev
cnpm install file-saver --save-dev
dev按需要加或不加。
使用
弹窗页面如上图是分页的,但导出Excel需要的是全部数据,所以另外单独写一个opacity
为0的el-table
用来做导出。
// .vue
// template
<el-table id="out-table" border :data="Pollutantlist" style="opacity:0;">
<el-table-column
v-for="coll in column"
:key="coll.value"
:label="coll.label"
align="center"
:prop="coll.value"
:min-width="coll.width"
>
<template slot-scope="scope">
...
</template>
</el-table-column>
</el-table>
Pollutatlist为全部数据。(ps:由于涉及到接口数据的行转列,所以才有column的循环,这点可以忽略。)
// script
import FileSaver from 'file-saver'
import XLSX from 'xlsx'
// script (method)
handleExport(){//导出按钮
/* 从表生成工作簿对象 */
var wb = XLSX.utils.table_to_book(document.querySelector('#out-table'))
/* 获取二进制字符串作为输出 */
var wbout = XLSXD.write(wb, {
bookType: 'xlsx',
bookSST: true,
type: 'array',
cellStyles: true,
})
try {
FileSaver.saveAs(
// Blob 对象表示一个不可变、原始数据的类文件对象。
// Blob 表示的不一定是JavaScript原生格式的数据。
// File 接口基于Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。
// 返回一个新创建的 Blob 对象,其内容由参数中给定的数组串联组成。
new Blob([wbout], { type: 'application/octet-stream' }),
// 设置导出文件名称
'xxxx数据.xlsx'
)
} catch (e) {
if (typeof console !== 'undefined') console.log(e, wbout)
}
return wbout
}
复制代码
over...
这样导出之后样式都是xlsx默认的,所以为了与项目里后端接口导出的Excel结果一致,需要增加一点样式。这里根据项目里的情况,需要设置:
- 表头背景色及表头文字颜色。
要求如下: 不要如下: 2. 设置边框border
3. 设置字体
4. 设置列宽
新增样式
cnpm install xlsx-style --save-dev
//vue.config.js
module.export = {
...
configureWebpack:{
externals:{
'./cptable': 'var cptable'
},
}
...
}
复制代码
这里一定要配置一下,要不然会报错。还可以改源码处理,由于我司参与的人较多且不在同一地点办公,所以不去改源码。另外再去调整js。
// script
import FileSaver from 'file-saver'
import XLSX from 'xlsx'
import XLSXD from 'xlsx-style' // 新增
// script (method)
1. handleExport(){
2. var wb = XLSX.utils.table_to_book(document.querySelector('#out-table'))
3. let blocks = wb.Sheets[wb.SheetNames[0]];//注释一
4. Object.keys(blocks).map((str)=>{
5. let res = str.match(/^[A-Z]+1$/g);//注释二
6. let cell = blocks[str];
7. if(res){
8. blocks['!cols'].push({wpx:cell.v.length*20+8});//注释三
9. cell.s = {
10. font: {
11. name: 'Arial',
12. bold: true,
13. color: { rgb:"FFFFFFFF" },
14. sz: 10
15. },
16. fill: { fgcolor:{ rgb:'FF808080'},fgColor:{ rgb:'FF808080'}},
17. alignment: { horizontal:'center' },
18. border: {
19. top: { style: 'thin' },
20. bottom: { style: 'thin' },
21. left: { style: 'thin' },
22. right: { style: 'thin' },
23. }
24. }
25. }else if(str.indexOf('!')==-1){// 注释四
26. cell.s = {
27. font: {
28. name: 'Arial',
29. sz: 10
30. },
31. alignment: { horizontal:'center' },
32. border: {
33. top: { style: 'thin' },
34. bottom: { style: 'thin' },
35. left: { style: 'thin' },
36. right: { style: 'thin' },
37. }
38. }
39. }
40. })
41. var wbout = XLSXD.write(wb, {//这里是XLSXD
42. bookType: 'xlsx',
43. bookSST: true,
44. type: 'buffer',//这里是buffer
45. cellStyles: true,
46. })
47. try {
48. FileSaver.saveAs(
49. new Blob([wbout], { type: 'application/octet-stream' }),
50. 'xxxx数据.xlsx'
51. )
52. } catch (e) {
53. if (typeof console !== 'undefined') console.log(e, wbout)
54. }
55. return wbout
56. }
复制代码
注释一:
先看一下第2
行代码的实例wb
:
其中,SheetNames
表示“工作表”的名称集合,Sheets
是“工作表”的内容的属性集合。SheetNames.Sheet1
下的!cols
表示存储列对象,!rows
表示存储行对象,!ref
表示工作表范围的字符串。其余的属性则是表示单元格,与Excel页面顶部及左侧的定位符对应,例如A2即表示第一列第二行。其他的一些属性可参考 这里。
注释二:
为了给表头设置样式,根据规则正则去匹配出SheetNames.Sheet1
表头,给表头设置一类样式,其他非表头的单元格设置另一种样式。样式挂载在SheetNames.Sheet1
下的属性对象下。例如A1对象里表示该单元格内容(t)是字符串,显示值(v)是马赛克。
v:单元格的值
t:单元格的类型 'b'布尔值、'n'数字、'e'错误、's'字符串、'd'日期
s:单元格的样式
注释三:
设置列宽,暂时性的将列宽设置为字符串长度*20个像素。!cols
所需要的格式为:[{wpx:20},...]
注释四:
剔除 SheetNames.Sheet1
下非单元格属性:!cols
、!fullref
、!ref
、 !rows
OVER !