vue实战(11)——vue+element UI实现表格数据导出Excel功能

一、应用场景

按照需求导出功能分为勾选批量导出及按照查询结果导出,考虑到接口操作导出的复杂性,因此实现了js控制导出的功能


导出功能截图

二、安装相关依赖

cnpm install --save xlsx file-saver

具体插件使用参考https://github.com/SheetJS/js-xlsxhttps://github.com/eligrey/FileSaver.js

三、实现代码

考虑到多处使用导出功能,所以封装成公用组件形式
1、列表页

<template>
<div class="add-button">
      <span @click="exportExcelSelect">按勾选导出</span>
      <span @click="exportExcel">按查询结果导出</span>
 </div>
  <export-excel-common ref="myChild" :exportExcelInfo="exportExcelInfo" :tableData="tableAllData" :exportExcelArry="exportExcelArry"></export-excel-common>
</template>
<script>
  export default {
    components: {
      exportExcelCommon
    },
    data() {
      return {
        //导出表格字段及formatter信息
        exportExcelArry: [{
          prop: 'phoneNumber',
          label: '用户手机号',
          formatterFlag: false
        },{
          prop: 'userFundRedEnvelopRecord.status',
          label: '状态',
          formatterFlag: true,
          formatterType: 'common-type',
          formatterInfo: [{value: 0,label: '未完成'},{value: 1,label: '已完成'}]
        },{
          prop: 'userFundRedEnvelopRecord.name',
          label: '任务名称',
          formatterFlag: false
        }],
        //导出excel表格id及excel名称
        exportExcelInfo: {
          excelId: 'record-table',
          excelName: '红包获取记录.xlsx'
        },
        //需要导出的table数据
        tableAllData: [],
  },
  methods {
    exportExcelSelect () {
        if(this.selectListArry.length == 0){
          global.message('请勾选操作项')
          return;
        }
        //将选中项传给this. tableAllData
        this.tableAllData = this.selectListArry
        //需要延时调导出方法,为了等待数据初始化到列表中
        setTimeout(()=>{
          this.$refs.myChild.exportExcel();
        },500)
      },
      exportExcel () {
        this.initData('export-excel')
        //获取到表格数据的值并赋给this.tableAllData
        //同样延时调导出方法,需在initData('export-excel')方法执行成功后调this.$refs.myChild.exportExcel();方法
      }
  }
}

2、通用组件ExportExcelCommon.vue

<template>
   <transition name="fadeIn">
       <div v-show='false'>
           <el-table :id="exportExcelInfo.excelId" :data="tableData" highlight-current-row style="width: 100%">
             <template v-for="(item,index) in exportExcelArry">
         <el-table-column v-if="!item.formatterFlag" :prop="item.prop" :label="item.label">
         </el-table-column>
         <el-table-column v-else :prop="item.prop" :label="item.label">
             <template slot-scope="scope">
               <span>{{formatter(scope.row[item.prop],item,scope.row,item.prop)}}</span>
           </template>
         </el-table-column>
       </template>
     </el-table>
       </div>
   </transition>
</template>
<script>
 import FileSaver from 'file-saver'
 import XLSX from 'xlsx'
   export default {
       props: {
           exportExcelInfo: {
               type: Object,
               default: {}
           },
           exportExcelArry: {
       type: Array,
       default: []
     },
           tableData: {
       type: Array,
       default: []
     },
       },
       methods: {
         //excel导出
         exportExcel () {
       var xlsxParam = { raw: true } // 导出的内容只做解析,不进行格式转换
        var wb = XLSX.utils.table_to_book(document.querySelector('#'+this.exportExcelInfo.excelId),xlsxParam)
        var wbout = XLSX.write(wb, { bookType: 'xlsx', bookSST: true, type: 'array' })
        try {
           FileSaver.saveAs(new Blob([wbout], { type: 'application/octet-stream' }), this.exportExcelInfo.excelName)
        } catch (e) { 
          if (typeof console !== 'undefined') console.log(e, wbout) 
        }
        return wbout
     },
     //表格formatter数据格式化
         formatter (value,item,row,prop) {
           //针对table中item多层对象层级的情况
           if(prop.indexOf('.') > 0){
         let temp = prop.split('.')
         //item中嵌套两层
         if(temp.length == 2){
           let temp = prop.split('.')
           if(item.formatterType == 'common-type'){  //通用类型转换
             let arry = item.formatterInfo
             for(let i in arry){
               if(arry[i].value == row[temp[0]][temp[1]]){
                 return arry[i].label
               }
             }
           } else if(item.formatterType == 'time-type'){ //时间标准格式化
             if(!global.isNull(row[temp[0]][temp[1]])){
               return row[temp[0]][temp[1]].substring(0,row[temp[0]][temp[1]].length - 2)
             }
           } else if(item.formatterType == 'amount-type'){ //金额转换
             return (row[temp[0]][temp[1]] / 100).toFixed(2)
           }
         }
       } else{ //item中无嵌套对象
         let temp = prop.split('.')
           if(item.formatterType == 'common-type'){  //通用类型转换
             let arry = item.formatterInfo
             for(let i in arry){
               if(arry[i].value == value){
                 return arry[i].label
               }
             }
           } else if(item.formatterType == 'time-type'){ //时间标准格式化
             if(!global.isNull(row[temp[0]][temp[1]])){
               return value.substring(0,value.length - 2)
             }
           } else if(item.formatterType == 'amount-type'){ //金额转换
             return (value / 100).toFixed(2)
           }
       }
     },
 }
};
</script>

说明:
1、通常情况下列表中的字段不需要formatter,把exportExcelArry 对象中formatterFlag设成false;
2、需要formatter的数据主要有code对应label的转换(type='common-type'),金额的单位转换等,需要根据自己项目的需求封装成通用的组件;
3、针对后端返回的数据data多层的情况,需要对exportExcelArry中的prop字段进行分割来获取row中对应的值,一般情况下两层足够了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270