本来甲方需求只有实现excel的导出,并无导出excel表格的美化需求,所以使用xlsx库来实现excel的导出。后期对接得知需要对导出excel表格进行美化,因为xlsx只能导出excel表格并不能对其美化,所以通过查阅资料选择使用xlsx-style库来实现导出excel表格并对其美化。在使用xlsx-style库的过程中遇到了很多问题,所以写这篇文章记录一下。
首先需要安装三个依赖:
npm install xlsx --save
npm install xlsx-style --save
npm install file-saver --save
需要注意,在安装xlsx-style之后执行项目大概率会出现以下问题:
1.This relative module was not found:./cptable in ./node_modules/xlsx-style@0.8.13@xlsx-style/dist/cpexcel.js 解决方案为在vue.config.js中的module.exports添加如下代码:
configureWebpack: {
externals:{
'./cptable': 'var cptable'
},
}
2.Error: Can't resolve 'fs' in 'E:\\xlsx-style' 解决方案为在本文上段代码中的configureWebpack配置项中添加如下代码:
resolve: {
fallback:{
fs: false,
}
},
3.BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default. 解决方案:手动引入node-polyfill-webpack-plugin
插件。首先执行以下代码:
npm install node-polyfill-webpack-plugin
npm install crypto-browserify
然后修改vue.config.js中的配置代码,以下附上解决上文提到的1,2,3问题之后的完整代码,可以对比解决1,2问题之后添加了哪些代码:
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin");
module.exports = {
configureWebpack: {
resolve: {
fallback: {
fs: false,
crypto: require.resolve("crypto-browserify"),
stream: require.resolve("stream-browserify"),
},
},
plugins: [new NodePolyfillPlugin()],
},
externals: {
'./cptable': 'var cptable',
},
};
错误和警告全部解决之后就可以成功执行项目,但是在成功执行项目下载并打开导出的excel文件时excel出现了提示,如下图:
其原因是因为项目中的合并单元格代码出现了问题,因为甲方提出的需求不涉及合并单元格,所以本文只是将这部分代码给注释掉,若是需要合并单元格功能可自行查阅资料解决(好吧,就是因为懒T.T)。
以下附上实现导出excel的函数完整代码:
exportToExcel(){
// 需要导出的数据
let excelData = [
['幼儿园课表', null, null, null], // 标题
['序号', '课程名称', '教师名称', '上课地点'], // 表头
['1', '体育', '大头老师', '操场']
]
// 导出的excel文件名
const filename = '幼儿园课程表.xlsx'
// Excel第一个sheet的名称
const ws_name = 'Sheet1'
const wb = XLSX.utils.book_new()
const ws = XLSX.utils.aoa_to_sheet(excelData)
XLSX.utils.book_append_sheet(wb, ws, ws_name) // 将数据添加到工作薄
// // 设置标题行单元格合并
// // s即start, e即end, r即row, c即column
// // 合并从--0行0列开始,到0行3列
// ws['!merges'] = [
// { s: { r: 0, c: 0 }, e: { r: 0, c: 3 } }
// ]
/*
设置单元格其他样式
这里列举一部分,其他样式大同小异,自行网上搜索
*/
// 可以遍历全部单元格,进行样式设置
for (let i in ws) {
if (i === 'B1') {
ws[i].s = {
// 字体
font: {
name: '仿宋',
sz: 14,
bold: true
}
}
} else if (i === 'B2') {
ws[i].s = {
// 居中
alignment: {
horizontal: 'center',
vertical: 'center',
wrapText: true
}
}
} else if (i === 'B3') {
ws[i].s = {
// 单元格边框
border: {
top: {
style: 'thin'
},
bottom: {
style: 'thin'
},
left: {
style: 'thin'
},
right: {
style: 'thin'
}
}
}
} else if(i=='A3'){
ws[i].s = {
// 居中
alignment: {
horizontal: 'center',
wrapText: true
},
font: {
name: '仿宋',
sz: 14,
bold: true
}
}
}
}
// 设置单元格宽度
ws['!cols'] = [{
wpx: 40
}, {
wpx: 40
}, {
wpx: 100
}, {
wpx: 100
}]
// 导出Excel, 注意这里用到的是XLSXS对象
let wbout = XLSXS.write(wb, {
bookType: 'xlsx',
bookSST: false,
type: 'binary'
})
FileSaver.saveAs(
new Blob([this.$options.methods.s2ab(wbout)], {
type: 'application/octet-stream'
}),
filename
)
},
s2ab(s) {
var buf = new ArrayBuffer(s.length)
var view = new Uint8Array(buf)
for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff
return buf
},