Excelレポートエクスポート


本稿では,現在比較的よく見られるexcelレポートの導出方式を3つまとめた.
  • の後端はexcelのバイナリを返し、フロントエンドはバイナリデータに基づいてurlを生成し、aのラベルと結合して
  • を導出する.
  • バックエンドはexcelレポートを生成し、レポートのリンクをフロントエンドに返し、フロントエンドはwindow.open()を使用して
  • をダウンロードする.
  • の後端は表データを返し、先端は表データを非表示のtableのラベルに入れ、表データをexcelに解析して
  • を導出する.
    エクスポートデータが小さい場合は、以上の3つの方法が可能です.エクスポートデータが比較的大きい場合、データ量が大きいとネットワーク要求が長くなり、フロントエンド生成excelもブラウザメモリを消費するため、第1および第3の方法は適切ではない.この場合、excelレポートをサービス側で生成するのが適切です.

    一、バイナリexcelエクスポートの処理

    
    
    
    import { exportRequest } from '@/service/request'
    
    export default {
      name: 'BinaryExcel',
      data () {
        return {}
      },
      methods: {
        /**
         * @description excel 
         * @param data excel 
         * @param name  
         */
        exportExcel (data, name = 'excel ') {
          if (window.navigator && window.navigator.msSaveOrOpenBlob) {
            //  IE11
            window.navigator.msSaveOrOpenBlob(data, name + '.xls')
          } else {
            const link = document.createElement('a')
            // xlxs 
            const blob = new Blob([data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
    
            // xls 
            // const blob = new Blob([data], { type: 'application/vnd.ms-excel' })
            link.style.display = 'none'
            link.href = URL.createObjectURL(blob)
            link.setAttribute('download', name + '.xlsx')
            // document.body.appendChild(link)
            link.click()
            // document.body.removeChild(link)
          }
        },
        //  excel
        doExport () {
          exportRequest('/excel/exportExcel', {}).then(res => {
            this.exportExcel(res.data)
          })
        }
      }
    }
    
    
    
    var express = require('express');
    var router = express.Router();
    var nodeExcel = require('excel-export') //  Excel xlsx 
    router.post('/exportExcel', async (req, res, next) => {
      //  
      var tableData = [
        { name: ' ', age: 20, school: ' ', date: '2020/12/12', safe: true },
        { name: ' ', age: 22, school: ' ', date: '2020/12/12', safe: true },
        { name: ' ', age: 23, school: ' ', date: '2020/12/12', safe: true }
      ]
      var conf ={};
      conf.name = "mysheet";
      conf.cols = [{
        caption:' ',
        type:'string',
      },{
        caption:' ',
        type:'number',
      },{
        caption:' ',
        type:'string',
        width: 50
      },{
        caption:' ',
        type:'string',
        width: 50
      },{
        caption:' ',
        type:'bool',
        width: 50
      }];
      conf.rows = tableData.reduce((init, item) => {
        init.push([item.name, item.age, item.school, item.date, item.safe])
        return init
      }, [])
      var result = nodeExcel.execute(conf);
      // xlsx 
      res.setHeader('Content-Type', 'application/vnd.openxmlformats;charset=utf-8');
      res.setHeader("Content-Disposition", "attachment; filename=" + "Report.xlsx");
    
      // xls 
      // res.setHeader('Content-Type', 'application/vnd.ms-excel;charset=utf-8');
      // res.setHeader("Content-Disposition", "attachment; filename=" + "Report.xls");
      res.end(result, 'binary');
    })

    二、サービス側がexcelを生成する

    
    
    
    import { post } from '@/service/request'
    
    export default {
      name: 'LinkExcel',
      data () {
        return {}
      },
      methods: {
        doExport () {
          post('/excel/linkExcel', {}).then(res => {
            console.log(res)
            window.open(res.data.downloadUrl) //  excel 
          })
        }
      }
    }
    
    
    var express = require('express');
    var router = express.Router();
    var xlsx = require('node-xlsx') //  excel
    var fs = require('fs')
    var path = require('path')
    router.post('/linkExcel', async (req, res, next) => {
      var tableData = [
        { name: ' ', age: 20, school: ' ', date: '2020/12/12', safe: true },
        { name: ' ', age: 22, school: ' ', date: '2020/12/12', safe: true },
        { name: ' ', age: 23, school: ' ', date: '2020/12/12', safe: true }
      ]
      var title = [' ', ' ', ' ', ' ', ' ']
      var excelData = []
      excelData = excelData.concat([title], tableData.reduce((init, item) => {
        init.push([item.name, item.age, item.school, item.date, item.safe])
        return init
      }, []))
      var buffer = xlsx.build([
        {
          name: 'mySheet', //  
          data: excelData //  
        }
      ])
      var timeStamp = new Date().getTime()
      fs.writeFileSync(`../source/${timeStamp}.xlsx`, buffer, {'flag':'w'})
      res.json({
        code: 1,
        downloadUrl: path.resolve(__dirname, `../source/${timeStamp}.xlsx`)
      })
    })

    三、フロントエンド解析table生成excelエクスポート

    
    
    
    import FileSaver from 'file-saver'
    import XLSX from 'xlsx'
    import { post } from '@/service/request'
    
    export default {
      name: 'DOMExcel',
      data () {
        return {
          tbodyHtml: ''
        }
      },
      mounted () {
        this.getData()
      },
      methods: {
        getData () {
          post('/excel/domExcel', {}).then(res => {
            if (res.data.code === 1) {
              var tbodyHtml = ''
              res.data.rows.forEach(e => {
                tbodyHtml += '<tr>'
                tbodyHtml += '<td>' + e.name + '</td>'
                tbodyHtml += '<td>' + e.age + '</td>'
                tbodyHtml += '<td>' + e.school + '</td>'
                tbodyHtml += '<td>' + e.date + '</td>'
                tbodyHtml += '<td>' + e.safe + '</td>'
                tbodyHtml += '<tr>'
              })
              this.tbodyHtml = tbodyHtml
            }
          })
        },
        doExport () {
          let wb = XLSX.utils.table_to_book(document.querySelector('#table'))
          /* get binary string as output */
          let wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: true, type: 'array'})
          try {
            FileSaver.saveAs(new Blob([wbout], {type: 'application/octet-stream'}), 'excel .xlsx')
          } catch (e) {
            if (typeof console !== 'undefined') {
              console.log(e, wbout)
            }
          }
          return wbout
        }
      }
    }
    
    
    var express = require('express');
    var router = express.Router();
    router.post('/domExcel', async (req, res, next) => {
      var tableData = [
        { name: ' ', age: 20, school: ' ', date: '2020/12/12', safe: true },
        { name: ' ', age: 22, school: ' ', date: '2020/12/12', safe: true },
        { name: ' ', age: 23, school: ' ', date: '2020/12/12', safe: true }
      ]
      res.json({
        code: 1,
        rows: tableData
      })
    })

    プロジェクトgitアドレス:https://github.com/Revelation...