vue excel 导出(vue框架使用xlsx导出excel表格)
刚接手一个项目 ,需要做表格导出 ,之前没用过 ,特做此记录 ,以备下次使用 。此模板适用于修改表格样式时使用 ,若只想简单的直接导出 ,可以参考另一篇:在vue中 ,使用xlsx配合FileSaver进行导出excel表格_郭小白呀的博客-CSDN博客
看到一篇文章 ,受益匪浅:如何使用JavaScript实现纯前端读取和导出excel文件-好记的博客
此项目中的表格数据 使用的是element ui 中的table 导入的 ,所以导出也是直接将已生成的表格导出为excel
表格导出的基本模板过程
1. 先下载插件
npm i xlsx npm i xlsx-style2. 在使用的页面中导入
import XLSX2 from xlsx import XLSX from xlsx-style3. 绑定要导出的表格 ,并设置列宽(不同内容的导出方式是不同的 ,这里直接是将表格导出为excel文件 ,用的是 utils.table_to_sheet,其他的用到了再补充)
这里对表格有无数据的判断 ,请看下边遇到的问题第三个来写!!!
var wb = XLSX2.utils.table_to_sheet(document.querySelector(#mytable))// mytable为表格的id名 if (!wb[!merges]) { this.$message.warning(无法导出:报表无数据) return } // 设置列宽(这里用到列的数量是用来设置不同列的不同宽度的) const sum = 1 + this.govMt.length * 7 + 2 // 列的数量 ,根据自身项目进行数据的更改 for (var i = 0; i < sum; i++) { if (i === sum - 1) { wb[!cols][i] = { wpx: 120 } // 设置列宽,只有最后一列的宽度是不同的 } else { wb[!cols][i] = { wpx: 60 } } }4. 设置单元格的样式
for (const key in wb) { if (key.indexOf(!) === -1) { // 排除带!的字段 ,只要单元格字段 wb[key].s = { font: {// 字体设置 sz: 13, bold: false, color: { rgb: 000000// 十六进制 ,不带# } }, border: { // 设置边框 top: { style: thin }, bottom: { style: thin }, left: { style: thin }, right: { style: thin } }, alignment: {// 文字居中 //字体水平居中 、垂直居中 、自动换行 horizontal: center, vertical: center, wrap_text: true } } } }基础设置就是这样 , 然后调用后边的三个函数即可
var data = this.addRangeBorder(wb[!merges], wb) // 合并项添加边框 var filedata = this.sheet2blob(data) // 将一个sheet转成最终的excel文件的blob对象 this.openDownloadDialog(filedata, 报表名字.xlsx) // 下载报表5. 由于有合并的单元格 ,所以要为 合并项 添加边框 ,具体解释看文末遇到的问题中的四!!
// 为合并项添加边框 addRangeBorder(range, ws) { const arr = [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z] range.forEach(item => { const startColNumber = Number(item.s.r); const endColNumber = Number(item.e.r) // 0-0 const startRowNumber = Number(item.s.c); const endRowNumber = Number(item.e.c) // 0-16 const test = ws[arr[startRowNumber] + (startColNumber + 1)] // 合并项第一个单元格中的内容 for (let col = startColNumber; col <= endColNumber; col++) { // 0-0 for (let row = startRowNumber; row <= endRowNumber; row++) { // 0-16 ws[arr[row] + (col + 1)] = test // A1-P1 } } }) return ws },6. 将一个sheet转成最终的excel文件的blob对象 ,然后利用URL.createObjectURL下载
// 将一个sheet转成最终的excel文件的blob对象 sheet2blob(sheet, sheetName) { // console.log(sheet, sheetName, sheet, sheetName) sheetName = sheetName || sheet1 console.log(sheetName, sheetName) var workbook = { SheetNames: [sheetName], Sheets: {} } workbook.Sheets[sheetName] = sheet // 生成excel的配置项 var wopts = { bookType: xlsx, // 要生成的文件类型 bookSST: false, // 是否生成Shared String Table ,官方解释是 ,如果开启生成速度会下降 ,但在低版本IOS设备上有更好的兼容性 type: binary } var wbout = XLSX.write(workbook, wopts) var blob = new Blob([s2ab(wbout)], { type: application/octet-stream }) // 字符串转ArrayBuffer function 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 } return blob },利用URL.createObjectURL下载 函数
openDownloadDialog(url, saveName) { if (typeof url === object && url instanceof Blob) { url = URL.createObjectURL(url) // 创建blob地址 } var aLink = document.createElement(a) aLink.href = url aLink.download = saveName || // HTML5新增的属性 ,指定保存文件名 ,可以不要后缀 ,注意,file:///模式下不会生效 var event if (window.MouseEvent) event = new MouseEvent(click) else { event = document.createEvent(MouseEvents) event.initMouseEvent(click, true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null) } aLink.dispatchEvent(event) }遇到的问题:
一 、在使用xlsx-style导出的时候 ,可能会报如下错误:
Can‘t resolve ‘./cptable‘ in ‘xxx\node_modules_xlsx\xxx
或者在npm run serve时出现:
This relative module was not found: * ./cptable in ./node_modules/xlsx-style/dist/cpexcel.js
解决方式有两种:
1. 在config.js中加入如下代码:
module.exports = { externals: { ./cptable: var cptable } }这段代码要写进config.js中 ,我发现我并没有这个文件(我用的是vue2.0),所以要在根目录中创建vue.config.js文件 ,并在内部写如下代码:
module.exports = { devServer: { port: 80, host: 0.0.0.0, }, };这时 ,我将externals: { ./cptable: var cptable }直接写进 module.exports 中 ,
module.exports = { devServer: { port: 80, host: 0.0.0.0, }, externals: { ./cptable: var cptable } };出现了如下错误:
ERROR Invalid optio
.0ns in vue.config.js: "externals" is not allowed
意思是vue.config.js里面没有这个字段 ,所以配置的这个webpack字段vue并没有把它映射到vue.config.js中 。所以我们要换一种引用方式:
configureWebpack: { externals: {./cptable: var cptable} } // 配置webpack的字段 。然后再重新运行就可以了 。
2. 第二种方式是修改 node_modules 中的代码 ,但是 ,每次拉取代码 npm i 后 ,都要去修改 ,这样是很不方便的 。
找到 ./node_modules/xlsx-style/dist/cpexcel.js 文件手动修改
将 var cpt = require(./cpt + able); 替换为 var cpt = cptable;二 、vue xlsx导出表格时间不全问题
可能为:进入时间一列显示年月日 ,时分秒被忽略掉 、有个别显示####
解决方式:
在代码中添加:{ raw: true }
var wb = XLSX2.utils.table_to_sheet(document.querySelector(#exportTab), { raw: true })// exportTab为表格的id名效果图:
三 、在代码的 3. 中 ,报表无数据的判断是可以灵活改变的
如下代码段是用来判断有没有合并项的 ,如果没有单元格合并 ,是不会有此选项的,所以就算表格中有数据 ,也会一直走无法导出的代码 ,所以可以再从wb中换一个字段来判断 。例如: !fullref
若有合并项可以写为:
if (!wb[!merges]) { this.$message.warning(无法导出:报表无数据) return }根据需要可以改写为:
if (!wb[!fullref]) { this.$message.warning(无法导出:报表无数据) return }四 、 对于合并项函数的需求解答
当我们的单元格是合并单元格时,如果不对合并项添加边框 ,导出的表格效果如图所示:
我们发现合并项的边框是有缺失的 ,在我们调用为合并项添加边框函数后 ,就可解决这个问题 ,效果图如下所示:
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!