最简单的前端导出(vue + xlsx)

需求

原本项目里导出都是后端写的接口,有某个业务页面table的内容需求前端导出到Excel即可。需要导出全部数据非当前页,无其他要求。

安装

cnpm install xlsx --save-dev

cnpm install file-saver --save-dev

dev按需要加或不加。

使用

image.png 弹窗页面如上图是分页的,但导出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结果一致,需要增加一点样式。这里根据项目里的情况,需要设置:

  1. 表头背景色及表头文字颜色。

要求如下: image.png 不要如下: image.png 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
image.png

image.png

其中,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 !

猜你喜欢

转载自juejin.im/post/7086382246852034568
今日推荐