• vue 利用xlsx、xlsxstyle、filesaver实现前端导出excel表格 (包括设置单元格居中、边框等样式) antdesignvue、elementui、vxetable 等都适用


    我用的方法是在表格的根组件外层赋一个div用来导出整个表格,所以antdesignvue、elementui、vxetable 或者原生的table写法应该全都适用,此处我用的框架为antdesignvue,包含合并单元格与二级标题,先看最终样式以及导出的效果:

     导出的excel:

     首先要引入三个库:

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

    vue 2.0版本xlsx-style ./cptable' 报错:Can't resolve './cptable' in 'xxxx\nautical-front\node_modules_xlsx 

    解决:在vue的config文件中加如下代码

    './cptable': 'var cptable'

    为了防止代码一致却有运行错误的情况 这里再列出我开发时用的插件的版本号:

    "file-saver": "^2.0.5",
    "xlsx": "^0.17.0",
    "xlsx-style": "^0.8.13"

    全部安装好后引入插件:

    import XLSX from "xlsx";
    import XLSXStyle from "xlsx-style";
    import FileSaver from "file-saver";

    先根据不同的框架渲染好表格的页面,外层套一层div:

    <template>
      <a-card :bordered="false">
        <a-button @click="exportToExcel" >导出</a-button>
        <div id="exportData"  class="css_page_body" ref="css_page_body">
          <a-table :columns="columns"
                   :data-source="data"
                   bordered
                   :pagination="false">
          </a-table>
    
        </div>
      </a-card>
    </template>

    下面是导出的方法:

     exportToExcel () {
          let ws = XLSX.utils.table_to_sheet(document.getElementById('exportData'))
          let ws2 = XLSX.utils.table_to_sheet(document.getElementById('exportData'))
          //创建一个workbook对象
          let wb = XLSX.utils.book_new()
          //把worksheet对象添加进workbook对象,第三个参数是excel中sheet的名字
          XLSX.utils.book_append_sheet(wb, ws, '月度统计报表')
          XLSX.utils.book_append_sheet(wb, ws2, '隔离库')
          this.setExlStyle(wb['Sheets']['月度统计报表']); // 设置列宽 字号等 如果无需多余的样式则省略
          this.addRangeBorder(wb['Sheets']['月度统计报表']['!merges'],wb['Sheets']['月度统计报表']) //设置合并行的border
          let wb_out = XLSXStyle.write(wb, { type: 'buffer'})
    
          try {
            FileSaver.saveAs(new Blob([wb_out], {
              type: 'application/octet-stream'
            }), 'WMS统计报表.xlsx');   // 导出的文件名
          } catch (e) {
            console.log(e, wb_out) ;
          }
          return wb_out;
        },
    setExlStyle(data) {
          let borderAll = {  //单元格外侧框线
            top: {
              style: 'thin',
            },
            bottom: {
              style: 'thin'
            },
            left: {
              style: 'thin'
            },
            right: {
              style: 'thin'
            }
          };
          data['!cols'] = [];
          for (let key in data) {
            // console.log(key)
            if (data[key] instanceof Object) {
              data[key].s = {
                border: borderAll,
                alignment: {
                  horizontal: 'center',   //水平居中对齐
                  vertical:'center'
                },
                font:{
                  sz:11
                },
                bold:true,
                numFmt: 0
              }
              data['!cols'].push({wpx: 115});
            }
          }
          return data;
        },
        addRangeBorder (range, ws) {
          let cols = ["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 => {
            console.log(item)
            let style = {
              s: {
                border: {
                  top: { style: 'thin' },
                  left: { style: 'thin' },
                  bottom: { style: 'thin' },
                  right: { style: 'thin' }
                }
              }
            }
            // 处理合并行
            for (let i = item.s.c; i <= item.e.c; i++) {
              ws[`${cols[i]}${Number(item.e.r) + 1}`] = ws[`${cols[i]}${Number(item.e.r) + 1}`] || style
              // 处理合并列
              for (let k = item.s.r + 2; k <= item.e.r + 1; k++) {
                ws[cols[i] + k] = ws[cols[k] + item.e.r] || style
              }
            }
          })
          return ws;
        },

    以上就是全部有关导出表格的内容,以下是全部的代码:

    <template>
      <a-card :bordered="false">
        <a-button @click="exportToExcel" >导出</a-button>
        <div id="exportData"  class="css_page_body" ref="css_page_body">
          <a-table :columns="columns"
                   :data-source="data"
                   bordered
                   :pagination="false">
          </a-table>
    
        </div>
      </a-card>
    </template>
    
    <script>
    import XLSX from "xlsx";
    import XLSXStyle from "xlsx-style";
    import FileSaver from "file-saver";
    
    export default {
      data () {
        return {
          columns:[
            {
              title: '学校', dataIndex: 'school',  '25%',
              scopedSlots: { customRender: 'school' }, align: 'center', key: 'school',
              customRender (_, row) {
                return {
                  children: row.school,
                  attrs: {
                    rowSpan: row.schoolRowSpan
                  }
                }
              }
            },
            {
              title: '年级', dataIndex: 'grade',  '25%',
              scopedSlots: { customRender: 'grade' }, align: 'center', key: 'grade',
              customRender (_, row) {
                return {
                  children: row.grade,
                  attrs: {
                    rowSpan: row.gradeRowSpan
                  }
                }
              }
            },
            {
              title: '班级', dataIndex: 'class',  '25%',
              scopedSlots: { customRender: 'class' }, align: 'center'
            },
            {
              title: '姓名', dataIndex: 'name',  '25%',
              scopedSlots: { customRender: 'name' }, align: 'center'
            },
            {
              title: '4月1日',
              children: [
                {
                  title: '周五',
                  dataIndex: 'companyAddress',
                   100,
                }
              ],
            },
            {
              title: '4月1日',
              children: [
                {
                  title: '周五',
                  dataIndex: 'companyAddress2',
                   100,
                }
              ],
            },
            {
              title: '4月1日',
              children: [
                {
                  title: '周五',
                  dataIndex: 'companyAddress3',
                   100,
                }
              ],
            },
            {
              title: '4月1日',
              children: [
                {
                  title: '周五',
                  dataIndex: 'companyAddress4',
                   100,
                }
              ],
            },
          ],
          data:[
    
          ]
        }
      },
      methods: {
        // 合并单元格
        rowSpan (key, data) {
          const arr = data
            .reduce((result, item) => {
              if (result.indexOf(item[key]) < 0) {
                result.push(item[key])
              }
              return result
            }, [])
            .reduce((result, keys) => {
              const children = data.filter(item => item[key] === keys)
              result = result.concat(
                children.map((item, index) => ({
                  ...item,
                  [`${key}RowSpan`]: index === 0 ? children.length : 0
                }))
              )
              return result
            }, [])
          return arr
        },
        // 表格合并
        mergeRowCell (data) {
          let tableData = this.rowSpan('school', data)
          tableData = this.rowSpan('grade', tableData)
          this.data = tableData
    
        },
        exportToExcel () {
          let ws = XLSX.utils.table_to_sheet(document.getElementById('exportData'))
          let ws2 = XLSX.utils.table_to_sheet(document.getElementById('exportData'))
          //创建一个workbook对象
          let wb = XLSX.utils.book_new()
          //把worksheet对象添加进workbook对象,第三个参数是excel中sheet的名字
          XLSX.utils.book_append_sheet(wb, ws, '月度统计报表')
          XLSX.utils.book_append_sheet(wb, ws2, '隔离库')
          this.setExlStyle(wb['Sheets']['月度统计报表']); // 设置列宽 字号等
          this.addRangeBorder(wb['Sheets']['月度统计报表']['!merges'],wb['Sheets']['月度统计报表'])
          let wb_out = XLSXStyle.write(wb, { type: 'buffer'})
    
          try {
            FileSaver.saveAs(new Blob([wb_out], {
              type: 'application/octet-stream'
            }), 'WMS统计报表.xlsx');   //trade-publish.xlsx 为导出的文件名
          } catch (e) {
            console.log(e, wb_out) ;
          }
          return wb_out;
        },
        setExlStyle(data) {
          let borderAll = {  //单元格外侧框线
            top: {
              style: 'thin',
            },
            bottom: {
              style: 'thin'
            },
            left: {
              style: 'thin'
            },
            right: {
              style: 'thin'
            }
          };
          data['!cols'] = [];
          for (let key in data) {
            // console.log(key)
            if (data[key] instanceof Object) {
              data[key].s = {
                border: borderAll,
                alignment: {
                  horizontal: 'center',   //水平居中对齐
                  vertical:'center'
                },
                font:{
                  sz:11
                },
                bold:true,
                numFmt: 0
              }
              data['!cols'].push({wpx: 115});
            }
          }
          return data;
        },
        addRangeBorder (range, ws) {
          let cols = ["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 => {
            console.log(item)
            let style = {
              s: {
                border: {
                  top: { style: 'thin' },
                  left: { style: 'thin' },
                  bottom: { style: 'thin' },
                  right: { style: 'thin' }
                }
              }
            }
            // 处理合并行
            for (let i = item.s.c; i <= item.e.c; i++) {
              ws[`${cols[i]}${Number(item.e.r) + 1}`] = ws[`${cols[i]}${Number(item.e.r) + 1}`] || style
              // 处理合并列
              for (let k = item.s.r + 2; k <= item.e.r + 1; k++) {
                ws[cols[i] + k] = ws[cols[k] + item.e.r] || style
              }
            }
          })
          return ws;
        },
      },
      mounted() {
        this.data = []
        for(let i=0;i<4;i++){
          this.data.push( { school: '林州一中', grade: '高一', class: '二班', name: '徐强' } )
          this.data.push( { school: '林州二中', grade: '高三', class: '一班', name: '徐强子' } )
        }
        this.mergeRowCell(this.data)
      }
    }
    </script>
    
    <style lang="less" scoped>
    </style>

     参考的文章:

    vue table复杂表格导出excel(支持多表头、合并单元格、边框、居中、背景等自定义样式)

    前端复杂表格导出excel,一键导出 Antd Table 看这篇就够了(附源码)

    vue页面table导出excel

    vue导出Excel表格,utils未定义是版本原因

    js xlsx使用说明(主要讲导出表格与设置表头相关)

    XLSX-STYLE 的用法

    JavaScript导出excel文件,并修改文件样式

  • 相关阅读:
    让 .Net 程序 脱离 .net framework框架 运行的方法 转
    MySpaces性能提高的过程转
    AskNet 内容查询系统 筹备中
    关于自定义表单的一些想法
    Url重写
    show一下我的办公桌
    IronRuby 初览
    微软将终止对SQL2000的支持
    WCF 消息交换 转
    感受刘德华的努力
  • 原文地址:https://www.cnblogs.com/lilelile/p/16186151.html
Copyright © 2020-2023  润新知