xlsx-style 前端js导出带样式的excel

前端导出excel

原来在项目中导出excel使用的是xlsx 库,使用中发现该库无法给要导出的excel添加样式(据说pro版可以,但并找到pro版  ̄□ ̄||),所以尝试了新的库xlsx-style,在使用xlsx-style库的过程中遇到了一下坑,特此记录一下📝

下载xlsx-style

直接使用npm下载就行

1
2
npm install --save xlsx-style
npm install --save file-saver

在项目中引用

1
2
import XLSX from 'xlsx-style'
import {saveAs} from 'file-saver';

😮 然后此时编译运行,居然就出错了……😭

报错如下

1
2
3
ERROR  Failed to compile with 1 errors     
This relative module was not found:
* ./cptable in ./node_modules/xlsx-style/dist/cpexcel.js

直接看 node_modules 文件下的xlsx-style我们可以发现 cptable.js文件确实是不存在存在的,这里其实源码有误,依赖中将:node_modules\xlsx-style\dist\cpexcel.js js文件里,第807行,var cpt = require(’./cpt’ + ‘able’);有误,改成var cpt = cptable;就可以正确启动程序了。

但是我们并不想修改源码,所以让我们通过修改webpack的配置达到这一目的。

修改方案:修改webpack的配置,在webpack的配置文件中添加如下代码(如果你使用的是vue,在webpack.base.conf.js中添加):

1
2
3
externals:{
'./cptable': 'var cptable'
},

导出文件

处理数据

xlsx-style 需要的数据格式大致如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
A1: {
v:'数据项1',
s:{
font: {color: {rgb: "FF0000"}},
}
},
B1: {
v:'数据项2',
s:{
font: {color: {rgb: "FF0000"}},
}
},
}

所以我们需要吧数据处理成这样的格式,这里我自己写了一个处理并导出表格的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import XLSX from 'xlsx-style'
import {saveAs} from 'file-saver';

function s2ab(s) {
const buf = new ArrayBuffer(s.length)
const view = new Uint8Array(buf)
for (let i = 0; i !== s.length; ++i) {
view[i] = s.charCodeAt(i) & 0xff
}
return buf
}

/**
* @param tableJson 原始数据
* @param keyMap 表头
* @param fileName 导出文件名
*/
export default function (tableJson,keyMap,fileName) {
for (let k in keyMap){
tableJson[0][k] = k;
}

let tmpdata = [];//用来保存转换好的json
tableJson.map((v, i) =>
keyMap.map((k, j) =>{
if(typeof v[k] === 'object'){
let data = Object.assign({}, v[k])
data.position = (j > 25 ? this.getCharCol(j) : String.fromCharCode(65 + j)) + (i + 1)
return data
}else {
return Object.assign({}, {
v: v[k],
position: (j > 25 ? this.getCharCol(j) : String.fromCharCode(65 + j)) + (i + 1)
})
}
})
).reduce((prev, next) => prev.concat(next))
.forEach((v, i) =>
tmpdata[v.position] = {v: v.v, s:v.s}
);
let outputPos = Object.keys(tmpdata);
let tmpWB = {
SheetNames: ['mySheet'], //保存的表标题
Sheets: {
'mySheet': Object.assign({},
tmpdata, //内容
{
'!ref': outputPos[0] + ':' + outputPos[outputPos.length - 1] //设置填充区域
})
}
};

let tmpDown = new Blob([
s2ab(XLSX.write(tmpWB, {bookType: 'xlsx', bookSST: false, type: 'binary'}//这里的数据是用来定义导出的格式类型
))], {
type: ""
});
saveAs(tmpDown, fileName+'.xlsx');
}