• 纯前端导出excel表格 使用xlsx-style 可自定义样式,行高,打印属性,页边距,多表格压缩包下载


    纯前端导出excel表格 使用 xlsx-style 可自定义样式,行高,打印属性,页边距和多表格导出打包成压缩包下载

    1.使用环境

    • vue: 2.6.10
    • xlsx-style: 0.8.13
    • file-saver: 2.0.5

    2. 先修改依赖以实现需求

    • 增加自定义行高功能
      node_modules里找到xlsx-style 找到 xlsx.js 搜索关键词 write_ws_xml_data 把此函数替换为
      // 增加行高设置
      var DEF_PPI = 96, PPI = DEF_PPI;
      function px2pt(px) { return px * 96 / PPI; }
      function pt2px(pt) { return pt * PPI / 96; }
      function write_ws_xml_data(ws, opts, idx, wb) {
        var o = [], r = [], range = safe_decode_range(ws['!ref']), cell="", ref, rr = "", cols = [], R=0, C=0, rows = ws['!rows'];
        var dense = Array.isArray(ws);
        var params = ({r:rr}), row, height = -1;
        for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
        for(R = range.s.r; R <= range.e.r; ++R) {
          r = [];
          rr = encode_row(R);
          for(C = range.s.c; C <= range.e.c; ++C) {
            ref = cols[C] + rr;
            var _cell = dense ? (ws[R]||[])[C]: ws[ref];
            if(_cell === undefined) continue;
            if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell);
          }
          if(r.length > 0 || (rows && rows[R])) {
            params = ({r:rr});
            if(rows && rows[R]) {
              row = rows[R];
              if(row.hidden) params.hidden = 1;
              height = -1;
              if (row.hpx) height = px2pt(row.hpx);
              else if (row.hpt) height = row.hpt;
              if (height > -1) { params.ht = height; params.customHeight = 1; }
              if (row.level) { params.outlineLevel = row.level; }
            }
            o[o.length] = (writextag('row', r.join(""), params));
          }
        }
        if(rows) for(; R < rows.length; ++R) {
          if(rows && rows[R]) {
            params = ({r:R+1});
            row = rows[R];
            if(row.hidden) params.hidden = 1;
            height = -1;
            if (row.hpx) height = px2pt(row.hpx);
            else if (row.hpt) height = row.hpt;
            if (height > -1) { params.ht = height; params.customHeight = 1; }
            if (row.level) { params.outlineLevel = row.level; }
            o[o.length] = (writextag('row', "", params));
          }
        }
        return o.join("");
      }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 增加缩放,设置纵横向 设置打印纸张大小 功能
      搜索关键词 write_ws_xml_pagesetup 把此函数改为
      // 打印属性设置
      function write_ws_xml_pagesetup(setup) {
        var pageSetup =  writextag('pageSetup', null, {
          paperSize: setup.pagesize || "9", // 纸张大小 9为A4纸
          scale: setup.scale || '100', // 缩放大小
          orientation: setup.orientation || 'portrait', // 纸张方向 landscape 为横向 portrait 为纵向
          horizontalDpi : setup.horizontalDpi || '4294967292',
          verticalDpi : setup.verticalDpi || '4294967292'
        })
        return pageSetup;
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    搜索关键字 write_ws_xml 替换为

      function write_ws_xml(idx, opts, wb) {
        var o = [XML_HEADER, WS_XML_ROOT];
        var s = wb.SheetNames[idx], sidx = 0, rdata = "";
        var ws = wb.Sheets[s];
        if(ws === undefined) ws = {};
        var ref = ws['!ref']; if(ref === undefined) ref = 'A1';
        o[o.length] = (writextag('dimension', null, {'ref': ref}));
    
        var sheetView = writextag('sheetView', null,  {
          showGridLines: opts.showGridLines == false ? '0' : '1',
          tabSelected: opts.tabSelected === undefined ? '0' :  opts.tabSelected,
          workbookViewId: opts.workbookViewId === undefined ? '0' : opts.workbookViewId
        });
        o[o.length] = writextag('sheetViews', sheetView);
    
        if(ws['!cols'] !== undefined && ws['!cols'].length > 0) o[o.length] = (write_ws_xml_cols(ws, ws['!cols']));
        o[sidx = o.length] = '';
        if(ws['!ref'] !== undefined) {
          rdata = write_ws_xml_data(ws, opts, idx, wb);
          if(rdata.length > 0) o[o.length] = (rdata);
        }
        if(o.length>sidx+1) { o[o.length] = (''); o[sidx]=o[sidx].replace("/>",">"); }
    
        if(ws['!merges'] !== undefined && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
    
        if (ws['!margins'] !== undefined) o[o.length] =  write_ws_xml_margins(ws['!margins']); // 页边距 !!! 必须要先设置页边距
    
        if (ws['!pageSetup'] !== undefined) o[o.length] =  write_ws_xml_pagesetup(ws['!pageSetup']); // 缩放 纵横向
        if (ws['!rowBreaks'] !== undefined) o[o.length] =  write_ws_xml_row_breaks(ws['!rowBreaks']);
        if (ws['!colBreaks'] !== undefined) o[o.length] =  write_ws_xml_col_breaks(ws['!colBreaks']);
    
        if(o.length>2) { o[o.length] = (''); o[1]=o[1].replace("/>",">"); }
        return o.join("");
      }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 增加页边距设置
      搜索关键词 write_ws_xml_pagesetup 在此函数下方 增加如下两个函数
     function write_ws_xml_margins(margin) {
        let margin2 = default_margins(margin);
        return writextag('pageMargins', null, margin2);
      }
      function default_margins(margins, mode) {
        if(!margins) return;
        var defs = [0.7, 0.7, 0.75, 0.75, 0.3, 0.3];
        if(mode == 'xlml') defs = [1, 1, 1, 1, 0.5, 0.5];
        if(margins.left   == null) margins.left   = defs[0];
        if(margins.right  == null) margins.right  = defs[1];
        if(margins.top    == null) margins.top    = defs[2];
        if(margins.bottom == null) margins.bottom = defs[3];
        if(margins.header == null) margins.header = defs[4];
        if(margins.footer == null) margins.footer = defs[5];
        return margins
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    write_ws_xml 函数里增加 调用 ,在上方 ““增加缩放,设置纵横向 设置打印纸张大小 功能”” 功能里 已经增加过了 注意 页边距 必须在缩放之前设置 不然会导致导出错误!!!

    if (ws['!margins'] !== undefined) o[o.length] =  write_ws_xml_margins(ws['!margins']); // 页边距 !!! 必须要先设置页边距
    
    • 1

    3. 需要一个调用文件 Export2Excel.js 内容如下 (跟Bolb.js 同放于项目src/assets/js 文件夹内)

    /* eslint-disable */
    require('script-loader!file-saver')
    // require('script-loader!../../assets/js/Blob');//该引入方式可能会报错
    require('../../assets/js/Blob')
    
    import XLSX from 'xlsx-style' // 样式
    function generateArray(table) {
      var out = []
      var rows = table.querySelectorAll('tr')
      var ranges = []
      for (var R = 0; R < rows.length; ++R) {
        var outRow = []
        var row = rows[R]
        var columns = row.querySelectorAll('td')
        for (var C = 0; C < columns.length; ++C) {
          var cell = columns[C]
          var colspan = cell.getAttribute('colspan')
          var rowspan = cell.getAttribute('rowspan')
          var cellValue = cell.innerText
          if (cellValue !== '' && cellValue === +cellValue) cellValue = +cellValue
    
          //Skip ranges
          ranges.forEach(function(range) {
            if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) {
              for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null)
            }
          })
    
          //Handle Row Span
          if (rowspan || colspan) {
            rowspan = rowspan || 1
            colspan = colspan || 1
            ranges.push({ s: { r: R, c: outRow.length }, e: { r: R + rowspan - 1, c: outRow.length + colspan - 1 } })
          }
    
    
          //Handle Value
          outRow.push(cellValue !== '' ? cellValue : null)
    
          //Handle Colspan
          if (colspan) for (var k = 0; k < colspan - 1; ++k) outRow.push(null)
        }
        out.push(outRow)
      }
      return [out, ranges]
    }
    
    function datenum(v, date1904) {
      if (date1904) v += 1462
      var epoch = Date.parse(v)
      return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000)
    }
    
    export function sheet_from_array_of_arrays(data, opts) {
      var ws = {}
      var range = { s: { c: 10000000, r: 10000000 }, e: { c: 0, r: 0 } }
      for (var R = 0; R !== data.length; ++R) {
        for (var C = 0; C !== data[R].length; ++C) {
          if (range.s.r > R) range.s.r = R
          if (range.s.c > C) range.s.c = C
          if (range.e.r < R) range.e.r = R
          if (range.e.c < C) range.e.c = C
          var cell = { v: data[R][C] }
          if (cell.v == null) continue
          var cell_ref = XLSX.utils.encode_cell({ c: C, r: R })
    
          if (typeof cell.v === 'number') cell.t = 'n'
          else if (typeof cell.v === 'boolean') cell.t = 'b'
          else if (cell.v instanceof Date) {
            cell.t = 'n'
            cell.z = XLSX.SSF._table[14]
            cell.v = datenum(cell.v)
          } else cell.t = 's'
    
          ws[cell_ref] = cell
        }
      }
      if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range)
    
      // XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], {range:1,defval:''});
      return ws
    }
    
    function Workbook() {
      if (!(this instanceof Workbook)) return new Workbook()
      this.SheetNames = []
      this.Sheets = {}
    }
    
    export 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
    }
    
    //导出
    export function export_json_to_excel({
                                           status = 1, // 状态 控制第几份模板
                                           multiHeader = [], // 多级表头
                                           header, // 表头
                                           data, // 数据
                                           sheetname, // sheet名称
                                           filename, // 文件名
                                           merges = [], // 合并列表
                                           width = [], // 自定义列宽
                                           height = [], // 自定义列高
                                           isreturn = false, // 是否返回blob
                                           autoWidth, // 自定义是否自动列高宽
                                           bookType = 'xlsx' // 文件类型
                                         } = {}) {
      // console.log('header', header, 'data', data, 'sheetname', sheetname, 'filename', filename)
      // console.log('multiHeader', multiHeader, 'merges', merges)
      filename = filename || 'excel-list'
      data = [...data]
    
      //先在数据里追加表头
      if (header.length > 0) {
        for (var k = 0; k < sheetname.length; k++) {
          data[k].unshift(header[k])
        }
      }
      // 追加多级表头
      if (multiHeader.length > 0) {
        for (var k = 0; k < sheetname.length; k++) {
          for (let i = multiHeader[k].length - 1; i > -1; i--) {
            data[k].unshift(multiHeader[k][i])
          }
        }
      }
      // 处理空行
      for (let i = 0; i < data.length; i++) {
        for (let j = 0; j < data[i].length; j++) {
          if (data[i][j].length === 0) {
            data[i].splice(j, 1)
          }
        }
      }
    
      var ws_name = sheetname || ['sheet1']
      var wb = new Workbook(),
        ws = []
      // 处理合并单元格
      for (var j = 0; j < sheetname.length; j++) {
        ws.push(sheet_from_array_of_arrays(data[j]))
        if (merges[j].length > 0) {
          if (!ws[j]['!merges']) ws[j]['!merges'] = []
          merges[j].forEach(item => {
            ws[j]['!merges'].push(XLSX.utils.decode_range(item))
          })
        }
      }
    
      // 处理自定义宽高
      for (let i = 0; i < autoWidth.length; i++) {
        if (autoWidth[i]) {
          let colWidth = []
          colWidth.push(
            data[i].map(row =>
              row.map(val => {
                /*先判断是否为null*/
                if (val === null || val === '' || val === undefined) {
                  return {
                    wch: 18
                  }
                } else if (val.toString().charCodeAt(0) > 255) {
                  /*再判断是否为中文*/
                  return {
                    wch: val.toString().length * 2 < 18 ? 18 : val.toString().length * 2
                  }
                } else {
                  return {
                    wch: val.toString().length < 18 ? 18 : val.toString().length
                  }
                }
              })
            )
          )
          // console.log('colWidth', i, autoWidth[i], data, colWidth)
          // console.log('colHeight', colHeight)
          /*以第一行为初始值*/
          let result = []
          if (colWidth[0][0]) {
            result = colWidth[0][0]
            for (let k = 1; k < colWidth[0].length; k++) {
              for (let j = 0; j < colWidth[0][k].length; j++) {
                if (result[j]['wch'] < colWidth[0][k][j]['wch']) {
                  result[j]['wch'] = colWidth[0][k][j]['wch']
                }
              }
            }
          }
          ws[i]['!cols'] = result
    
          let colHeight = []
          colHeight.push(
            data[i].map(row =>
              row.map(val => {
                if (val == null) {
                  return {
                    hpx: 25
                  }
                } else if (val.toString().charCodeAt(0) > 255) {
                  return {
                    hpx: val.toString().length > 18 ? 25 : 25
                  }
                } else {
                  return {
                    hpx: val.toString().length > 25 ? 25 : 25
                  }
                }
              })
            )
          )
          let result1 = []
          // for (var k = 0; k < colHeight.length; k++) {
          if (colHeight[0][0]) {
            result1 = colHeight[0][0]
            // console.log('result1[k]', result1[0], 'colHeight[0][0]', colHeight[0][0])
            for (let k = 1; k < colHeight[0].length; k++) {
              for (let j = 0; j < colHeight[0][k].length; j++) {
                if (result1[j]['hpx'] < colHeight[0][k][j]['hpx']) {
                  result1[j]['hpx'] = colHeight[0][k][j]['hpx']
                }
              }
            }
            // }
          }
          ws[i]['!rows'] = result1
    
        } else {
          if (width[i].length > 0) {
            ws[i]['!cols'] = width[i]
          } else {
            let colWidth = []
            colWidth.push(
              data[i].map(row =>
                row.map(val => {
                  /*先判断是否为null*/
                  if (val == null) {
                    return {
                      wch: 18
                    }
                  } else if (val.toString().charCodeAt(0) > 255) {
                    /*再判断是否为中文*/
                    return {
                      wch: val.toString().length * 2 < 18 ? 18 : val.toString().length * 2
                    }
                  } else {
                    return {
                      wch: val.toString().length < 18 ? 18 : val.toString().length
                    }
                  }
                })
              )
            )
            // console.log('colWidth', colWidth)
            let result = []
            if (colWidth[0][0]) {
              result = colWidth[0][0]
              // console.log('result[k]', result[k], 'colWidth[k][0]', colWidth[k][0])
              for (let k = 1; k < colWidth[0].length; k++) {
                for (let j = 0; j < colWidth[0][k].length; j++) {
                  if (result[j]['wch'] < colWidth[0][k][j]['wch']) {
                    result[j]['wch'] = colWidth[0][k][j]['wch']
                  }
                }
              }
            }
            ws[i]['!cols'] = result
          }
    
          if (height.length > 0) {
            ws[i]['!rows'] = height[i]
          } else {
            let colHeight = []
            colHeight.push(
              data[i].map(row =>
                row.map(val => {
                  if (val == null) {
                    return {
                      hpx: 80
                    }
                  } else if (val.toString().charCodeAt(0) > 255) {
                    return {
                      hpx: val.toString().length > 18 ? 80 : 40
                    }
                  } else {
                    return {
                      hpx: val.toString().length > 36 ? 80 : 40
                    }
                  }
                })
              )
            )
            let result1 = []
            if (colHeight[0][0]) {
              result1 = colHeight[0][0]
              // console.log('result1[k]', result1[0], 'colHeight[0][0]', colHeight[0][0])
              for (let k = 1; k < colHeight[0].length; k++) {
                for (let j = 0; j < colHeight[0][k].length; j++) {
                  if (result1[j]['hpx'] < colHeight[0][k][j]['hpx']) {
                    result1[j]['hpx'] = colHeight[0][k][j]['hpx']
                  }
                }
              }
            }
            ws[i]['!rows'] = result1
          }
        }
      }
    
    
      let target = dohandingexcel(status, wb, ws_name, sheetname, ws, data, header)
      wb = target.wb
      ws = target.ws
      console.log('wb', wb)
    
    
      // '!pageSetup': {scale: 67, orientation: 'landscape'}, //数据表打印时的页面配置,scale表示缩放比例,orientation是打印时的纸张方向landscape为横向打印
      // '!margins': {left:0.2, right: 0.2, top: 0.2, bottom: 0.2, header: 0.2, footer: 0.2}, //打印时的页面边距
    
      // //缩放100%,打印方向为纵向
      //   worksheet['!pageSetup'] = {
      //     scale: '100',
      //     orientation: 'portrait'
      //   }
      // // orientation 取值如下:
      // // 'portrait'  - 纵向
      // // 'landscape' - 横向
    
    
      // 导出Excel
      var wbout = XLSX.write(wb, {
        bookType: bookType,
        bookSST: false,
        type: 'binary'
      })
      let blobs = new Blob([s2ab(wbout)], {
        type: 'application/octet-stream'
      })
      if (isreturn) {
        return blobs
      } else {
        saveAs(blobs,
          filename + '.' + bookType
        )
      }
    }
    
    // 自定义表格样式
    // status 根据状态判断是哪种表格模板 
    function dohandingexcel(status, wb, ws_name, sheetname, ws, data, header) {
      // console.log('status', status,'ws_name',ws_name)
      // 模板样式自定义
      const borderAll = {
        //单元格外侧框线
        top: {
          style: 'thin'
        },
        bottom: {
          style: 'thin'
        },
        left: {
          style: 'thin'
        },
        right: {
          style: 'thin'
        }
      }
      let border = []
      let SZ9 = []
      let horight = []
      let holeft = []
      let A = ['A', 'C', 'E', 'G', 'I', 'K', 'M', 'O', 'Q', 'S', 'U', 'W', 'y'] // 奇数列
      let B = ['B', 'D', 'F', 'H', 'J', 'L', 'N', 'P', 'R', 'T', 'V', 'X', 'Z'] // 偶数列
    
      if (status === 1) {
        // 第一种模板
    
        // 设置页面大小 横纵向
        // for (var j = 0; j < sheetname.length; j++) {
        //   ws[j]['!pageSetup'] = {
        //     paperSize: '9', // 纸张大小
        //     scale: '80', // 缩放
        //     orientation: 'portrait' // 横纵向
        //   }
        //   ws[j]['!margins'] = { // 页边距 会根据缩放改变 自行调整
        //     left: 0.1,
        //     right: 0.1,
        //     top: 0.1,
        //     bottom: 0.1,
        //     header: 0.1,
        //     footer: 0.1
        //   }
        // }
        let blue = ['A3', 'E2', 'C8', 'E8', 'G15', 'V21', 'W21'] // 字体为蓝色
        let green = ['E13', 'G13', 'I15', 'I16', 'U21']  // 字体为绿色
        let yellow = ['AP21']  // 字体为绿色
        let italic = ['B2', 'B3', 'B4', 'B9', 'B10', 'B11', 'B17', 'B18', 'D17', 'D18', 'F5', 'F17', 'H17', 'H13', 'H5', 'J3', 'L5', 'J16', 'J17'] // 斜体
        SZ9 = ['B2', 'B3', 'B4', 'B5', 'H5', 'H13', 'J16', 'J3', 'L5'] // 字体为9号
        let SZ6 = ['B8', 'B9', 'B10', 'B11', 'B17', 'B18', 'D7', 'D17', 'D18', 'F17', 'H17', 'H14', 'J17'] // 字体为6
        horight = ['B2', 'B3', 'B4', 'B5', 'B8', 'B9', 'B10', 'B11', 'D7', 'F5', 'H5', 'H13', 'H14', 'J3', 'J16', 'L5'] // 水平靠右
        let wrapText = ['B8', 'B9', 'B10', 'B11', 'B18', 'D7', 'D17', 'D18', 'F17', 'H17', 'J17'] // 是否文字换行
        border = ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9', 'B10', 'B11', 'B12', 'B13', 'B14', 'B15', 'B16', 'B17', 'B18', 'B19',
          'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9', 'D10', 'D11', 'D12', 'D13', 'D14', 'D15', 'D16', 'D17', 'D18', 'D19',
          'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12', 'F13', 'F14', 'F15', 'F16', 'F17', 'F18', 'F19',
          'H2', 'H3', 'H5', 'H15', 'H16', 'H17', 'H18',
          'J2', 'J3', 'J5', 'J15', 'J16', 'J17', 'J18',
          'L5'] // 是否边框
    
        for (var k = 0; k < header.length; k++) {
          wb.SheetNames.push(ws_name[k])
          wb.Sheets[ws_name[k]] = ws[k]
          var dataInfo = wb.Sheets[wb.SheetNames[k]]
    
          //给所以单元格加上边框
          for (var i in dataInfo) {
            if (i === '!ref' || i === '!merges' || i === '!cols' || i === 'A1' || i === '!rows') {
    
            } else {
              const index = Number(i.match(/\d+/g)[0])
              if (k === 0) {
                if ((dataInfo[i + ''].v !== '' && index < 22) || border.includes(i)) {
                  if (index === 21) { // 表头
                    dataInfo[i + ''].s = {
                      border: borderAll,
                      font: {
                        name: '微软雅黑',
                        sz: 11,
                        color: { rgb: '000000' },
                        bold: false,
                        italic: false
                        // underline: false
                      },
                      alignment: {
                        horizontal: 'center', // 水平  "left"||"center"||"right"
                        vertical: 'bottom', // 垂直  "bottom"||"center"||"top"
                        wrapText: false // 文字换行  false || true
                        // readingOrder: 2, // 文字阅读顺序 默认2
                        // textRotation: 180 // 旋转 255 是垂直排列文字
                      }
                    }
                    //黄色
                    if (yellow.includes(i)) {
                      dataInfo[i + ''].s.font.color = { rgb: 'FFC000' }
                    }
                    //绿色
                    if (green.includes(i)) {
                      dataInfo[i + ''].s.font.color = { rgb: '00B050' }
                    }
                    //蓝色
                    if (blue.includes(i)) {
                      dataInfo[i + ''].s.font.color = { rgb: '538DD5' }
                    }
                  } else {
                    dataInfo[i + ''].s = {
                      border: borderAll,
                      font: {
                        name: '微软雅黑',
                        sz: 11, // 字体大小
                        color: { rgb: '000000' }, // 字体颜色
                        bold: false, // 是否加粗
                        italic: false // 是否斜体
                        // underline: false
                      },
                      alignment: {
                        horizontal: 'right', // 水平  "left"||"center"||"right"
                        vertical: 'bottom' // 垂直  "bottom"||"center"||"top"
                        // readingOrder: 2, // 文字阅读顺序 默认2
                        // textRotation: 180 // 旋转 255 是垂直排列文字
                      }
                    }
                    dataInfo[i + ''].t = 's'
                    if (border.includes(i)) {
                      dataInfo[i + ''].s.border = borderAll
                    }
                    if (B.includes(i.split('')[0])) {
                      dataInfo[i + ''].s.alignment.horizontal = 'left'
                    }
    
                    //蓝色
                    if (blue.includes(i)) {
                      dataInfo[i + ''].s.font.color = { rgb: '538DD5' }
                    }
                    //绿色
                    if (green.includes(i)) {
                      dataInfo[i + ''].s.font.color = { rgb: '00B050' }
                    }
                    if (italic.includes(i)) {
                      dataInfo[i + ''].s.font.italic = true
                    }
                    if (SZ9.includes(i)) {
                      dataInfo[i + ''].s.font.sz = 9
                    }
                    if (SZ6.includes(i)) {
                      dataInfo[i + ''].s.font.sz = 6
                    }
                    if (horight.includes(i)) {
                      dataInfo[i + ''].s.alignment.horizontal = 'right'
                    }
                    if (wrapText.includes(i)) {
                      dataInfo[i + ''].s.alignment.wrapText = true
                    }
    
                  }
    
    
                } else {
                  // 默认样式
                  dataInfo[i + ''].s = {
                    // border: borderAll,
                    font: {
                      name: '宋体',
                      sz: 11, // 字体大小
                      color: { rgb: '000000' }, // 字体颜色
                      bold: false, // 是否加粗
                      italic: false // 是否斜体
                      // underline: false
                    },
                    alignment: {
                      horizontal: 'left', // 水平  "left"||"center"||"right"
                      vertical: 'bottom' // 垂直  "bottom"||"center"||"top"
                      // readingOrder: 2, // 文字阅读顺序 默认2
                      // textRotation: 180 // 旋转 255 是垂直排列文字
                    }
                  }
                  dataInfo[i + ''].t = 's'
                  // if(i.includes('F')){
                  //   dataInfo[i + ''].s.alignment.horizontal = 'left'
                  // }
                  // 黄色
                }
              }
              if (k !== 0) {
                // console.log('a13', k, index, dataInfo[i + ''].v)
                if (dataInfo[i + ''].v !== '' && index === 2 && k !== 0) {
                  dataInfo[i + ''].s = {
                    border: borderAll,
                    font: {
                      name: '微软雅黑',
                      sz: 11,
                      color: { rgb: '000000' },
                      bold: false
                      // italic: false,
                      // underline: false
                    },
                    alignment: {
                      horizontal: 'center',
                      vertical: 'center'
                    }
                  }
                }
              }
            }
          }
          // 标题行
          // let arr = [
          //   'A1',
          //   'B1',
          //   'C1',
          //   'D1',
          //   'E1',
          //   'F1',
          //   'G1',
          //   'H1',
          //   'I1',
          //   'J1',
          //   'K1',
          //   'L1',
          //   'M1',
          //   'N1',
          //   'O1',
          //   'P1',
          //   'Q1',
          //   'R1',
          //   'S1',
          //   'T1',
          //   'U1',
          //   'V1',
          //   'W1',
          //   'X1',
          //   'Y1',
          //   'Z1'
          // ]
          // arr.some(function(v) {
          //   let a = merges[0].split(":");
          //   if (v == a[1]) {
          //     dataInfo[v].s = {};
          //     return true;
          //   } else {
          //     dataInfo[v].s = {};
          //   }
          // });
    
          //设置主标题样式
          let style = {
            font: {
              name: '微软雅黑',
              sz: 22,
              color: { rgb: '000000' },
              bold: true
              // italic: false,
              // underline: false
            },
            alignment: {
              horizontal: 'center',
              vertical: 'center'
            }
    
            // fill: {
            //   fgColor: {rgb: "008000"},
            // },
          }
          if (k === 0) {
            dataInfo['A1'].s = style
          } else {
            dataInfo['A1'].s = {
              font: {
                name: '宋体',
                sz: 14,
                color: { rgb: '000000' },
                bold: true
                // italic: false,
                // underline: false
              },
              alignment: {
                horizontal: 'center',
                vertical: 'center'
              }
    
              // fill: {
              //   fgColor: {rgb: "008000"},
              // },
            }
          }
    
          //excel标题样式
          // for (var i = 0; i < header.length; i++) {
          //   dataInfo[arr[i]].s = style
          // }
        }
      } else if (status === '3-1') {
        // 第二种模板
        // 设置页面大小 横纵向
        for (var j = 0; j < sheetname.length; j++) {
          ws[j]['!pageSetup'] = {
            paperSize: '9', // 纸张大小
            scale: '80', // 缩放
            orientation: 'portrait' // 横纵向
          }
          ws[j]['!margins'] = { // 页边距 会根据缩放改变 自行调整
            left: 0.1,
            right: 0.1,
            top: 0.1,
            bottom: 0.1,
            header: 0.1,
            footer: 0.1
          }
        }
    
        border = []
        let bold = ['B1', 'H3', 'H4']
        let SZ25 = ['B1']
        let SZ30 = ['G1']
        let fang = ['A1', 'A4', 'A5', 'G1', 'F3', 'F4', 'A5', 'B5', 'H5']
        for (let k = 0; k < sheetname.length; k++) {
          wb.SheetNames.push(ws_name[k])
          wb.Sheets[ws_name[k]] = ws[k]
          let length1 = data[k].length
          var dataInfo3 = wb.Sheets[wb.SheetNames[k]]
          // console.log('dataInfo3', dataInfo3)
          for (var i in dataInfo3) {
            if (i === '!ref' || i === '!merges' || i === '!cols' || i === '!rows' || i === '!pageSetup' || i === '!margins') {
            } else {
              const index = Number(i.match(/\d+/g)[0])
              dataInfo3[i + ''].s = {
                border: borderAll,
                font: {
                  name: 'Arial',
                  sz: 9, // 字体大小
                  color: { rgb: '000000' }, // 字体颜色
                  bold: false, // 是否加粗
                  italic: false // 是否斜体
                  // underline: false // 下划线
                },
                alignment: {
                  horizontal: 'center', // 水平  "left"||"center"||"right"
                  vertical: 'center' // 垂直  "bottom"||"center"||"top"
                  // wrapText:''  // 换行 true
                  // readingOrder: 2, // 文字阅读顺序 默认2
                  // textRotation: 180 // 旋转 255 是垂直排列文字
                }
              }
    
              if (i === 'A1') {
                dataInfo3[i + ''].s.alignment.wrapText = true
              }
              if (i === 'B4') {
                dataInfo3[i + ''].s.font.name = 39251
                dataInfo3[i + ''].s.font.sz = 16
              }
              if (fang.includes(i)) {
                dataInfo3[i + ''].s.font.name = '方正兰亭黑简体'
              }
              if (SZ25.includes(i)) {
                dataInfo3[i + ''].s.font.sz = 25
              }
              if (SZ30.includes(i)) {
                dataInfo3[i + ''].s.font.sz = 30
              }
              if (bold.includes(i)) {
                dataInfo3[i + ''].s.font.bold = true
              }
    
              if (index > 5 && index < length1 - 3) {
                // console.log('a', i, index, dataInfo3)
                if (i.includes('B')) {
                  dataInfo3[i + ''].s.alignment.horizontal = 'left'
                }
                if (i.includes('H')) {
                  dataInfo3[i + ''].t = 'n' // 字段类型
                  dataInfo3[i + ''].s.font.bold = true // 加粗
                }
                if (i.includes('A')) {
                  dataInfo3[i + ''].s.font.bold = true // 加粗
                }
              }
              if (index > length1 - 2) {
                dataInfo3[i + ''].s.border = {}
              }
              if (index === length1 - 3 && (i.includes('A') || i.includes('D'))) {
                dataInfo3[i + ''].s.font.bold = true
                dataInfo3[i + ''].s.font.name = '方正兰亭黑简体'
              }
              if (index === length1 - 3 && (i.includes('B') || i.includes('F'))) {
                dataInfo3[i + ''].t = 'n' // 字段类型
              }
              if (index === length1 - 2) {
                dataInfo3[i + ''].s.alignment.horizontal = 'right'
              }
    
            }
          }
        }
      }
      return {
        wb: wb,
        ws: ws
      }
    }
    
    
    // 备注:
    
    //属性	描述
    // v	原始数据
    // w	格式化的文本
    // t	单元格文本类型:b Boolean, n Number, e Error, s String, d Date
    // f	公式
    // r	富文本编码
    // h	富文本的HTML
    // c	与单元格关联的注释
    // z	与单元格关联的数字格式的字符串(已废弃)
    // l	单元格超链接,.Target holds link, .tooltip is tooltip
    // s	单元格具体的样式设置
    // 如: dataInfo.v 获取值
    
    // style属性
    // 顶级属性	子属性	       描述	     类型或可选值	        默认值
    // fill	  patternType	 填充模式	 “solid” or “none”	   -
    //        fgColor	     前景色	    COLOR_SPEC	         -
    //        bgColor	     背景色	    COLOR_SPEC	     {indexed: 64}
    
    // font	  name	       字体名称	  string	           “Calibri”
    //        sz	         字体大小	  number	            12
    //        color	       字体颜色	  COLOR_SPEC	         -
    //        bold	       加粗	      boolean	             -
    //        underline	   下划线	    boolean	             -
    //        italic	     斜体	      boolean	             -
    //        strike	     瞄边	      boolean	             -
    //        outline	     轮廓	      boolean	             -
    //        shadow	     阴影	      boolean	             -
    //        vertAlign	   垂直对齐	  boolean	             -
    
    // numFmt	  -	         数字格式化	   “0” // 内置格式的整数索引
    //                                 "0.00%" // 匹配内置格式的字符串,见下文
    //                                 "0.0%" // 格式化为自定义格式的字符串
    //                                 "0.00%;0.000.00;\-;@" // 格式化的时候转义特殊字符
    //                                 "m/dd/yy" // 格式化为日期	-
    
    // alignment	vertical	    垂直对齐	   “bottom”、“center”、“top”	       -
    //            horizontal	  水平对齐	   “left”、“center”、“right”      	 -
    //            wrapText	    换行	       boolean	                       -
    //            readingOrder	文字方向	   1、2 // for right-to-left	     -
    //            textRotation	旋转	        Number from 0 to 180 or 255	   0
    
    // border	top	           上边框	{ style: BORDER_STYLE, color: COLOR_SPEC }	-
    //        bottom	       下边框	{ style: BORDER_STYLE, color: COLOR_SPEC }	-
    //        left	         左边框	{ style: BORDER_STYLE, color: COLOR_SPEC }	-
    //        right	         右边框	{ style: BORDER_STYLE, color: COLOR_SPEC }	-
    //        diagonal	     对角线	{ style: BORDER_STYLE, color: COLOR_SPEC }	-
    //        diagonalUp	   上对角线	boolean	                                  -
    //        diagonalDown	 下对角线	boolean	                                  -
    // tips =>
    //  COLOR_SPEC   用于实现字体、边框以及填充的颜色,可以选择以下几种写法:
    //  { auto: 1} // 指定自动值
    //  { rgb: “FFFFAA00” } // 指定十六进制 ARGB 值
    //  { theme: “1”, tint: “-0.25”} 指定主题颜色的整数索引和色调值 (默认为 0)
    //  { indexed: 64} // fill.bgColor 的默认值
    
    // BORDER_STYLE  border_style 用于指定边框的样式,excel中边框样式有很多种,其中的可选值为:
    // thin
    // medium
    // thick
    // dotted
    // hair
    // dashed
    // mediumDashed
    // dashDot
    // mediumDashDot
    // dashDotDot
    // mediumDashDotDot
    // slantDashDot
    
    
    //  单元格对象
    //
    // 每一个单元格是一个对象(Cell Object),主要有t、v、r、h、w等字段(详见这里):
    //
    // t:表示内容类型,s表示string类型,n表示number类型,b表示boolean类型,d表示date类型,等等
    //
    // v:表示原始值;
    //
    // f:表示公式,如B2+B3;
    //
    // h:HTML内容
    //
    // w:格式化后的内容
    //
    // r:富文本内容rich text
    
    // ---------------------------------------------------------------------------------------------------------
    // 导出表格 包含图片 待做
    /* eslint-disable */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451
    • 452
    • 453
    • 454
    • 455
    • 456
    • 457
    • 458
    • 459
    • 460
    • 461
    • 462
    • 463
    • 464
    • 465
    • 466
    • 467
    • 468
    • 469
    • 470
    • 471
    • 472
    • 473
    • 474
    • 475
    • 476
    • 477
    • 478
    • 479
    • 480
    • 481
    • 482
    • 483
    • 484
    • 485
    • 486
    • 487
    • 488
    • 489
    • 490
    • 491
    • 492
    • 493
    • 494
    • 495
    • 496
    • 497
    • 498
    • 499
    • 500
    • 501
    • 502
    • 503
    • 504
    • 505
    • 506
    • 507
    • 508
    • 509
    • 510
    • 511
    • 512
    • 513
    • 514
    • 515
    • 516
    • 517
    • 518
    • 519
    • 520
    • 521
    • 522
    • 523
    • 524
    • 525
    • 526
    • 527
    • 528
    • 529
    • 530
    • 531
    • 532
    • 533
    • 534
    • 535
    • 536
    • 537
    • 538
    • 539
    • 540
    • 541
    • 542
    • 543
    • 544
    • 545
    • 546
    • 547
    • 548
    • 549
    • 550
    • 551
    • 552
    • 553
    • 554
    • 555
    • 556
    • 557
    • 558
    • 559
    • 560
    • 561
    • 562
    • 563
    • 564
    • 565
    • 566
    • 567
    • 568
    • 569
    • 570
    • 571
    • 572
    • 573
    • 574
    • 575
    • 576
    • 577
    • 578
    • 579
    • 580
    • 581
    • 582
    • 583
    • 584
    • 585
    • 586
    • 587
    • 588
    • 589
    • 590
    • 591
    • 592
    • 593
    • 594
    • 595
    • 596
    • 597
    • 598
    • 599
    • 600
    • 601
    • 602
    • 603
    • 604
    • 605
    • 606
    • 607
    • 608
    • 609
    • 610
    • 611
    • 612
    • 613
    • 614
    • 615
    • 616
    • 617
    • 618
    • 619
    • 620
    • 621
    • 622
    • 623
    • 624
    • 625
    • 626
    • 627
    • 628
    • 629
    • 630
    • 631
    • 632
    • 633
    • 634
    • 635
    • 636
    • 637
    • 638
    • 639
    • 640
    • 641
    • 642
    • 643
    • 644
    • 645
    • 646
    • 647
    • 648
    • 649
    • 650
    • 651
    • 652
    • 653
    • 654
    • 655
    • 656
    • 657
    • 658
    • 659
    • 660
    • 661
    • 662
    • 663
    • 664
    • 665
    • 666
    • 667
    • 668
    • 669
    • 670
    • 671
    • 672
    • 673
    • 674
    • 675
    • 676
    • 677
    • 678
    • 679
    • 680
    • 681
    • 682
    • 683
    • 684
    • 685
    • 686
    • 687
    • 688
    • 689
    • 690
    • 691
    • 692
    • 693
    • 694
    • 695
    • 696
    • 697
    • 698
    • 699
    • 700
    • 701
    • 702
    • 703
    • 704
    • 705
    • 706
    • 707
    • 708
    • 709
    • 710
    • 711
    • 712
    • 713
    • 714
    • 715
    • 716
    • 717
    • 718
    • 719
    • 720
    • 721
    • 722
    • 723
    • 724
    • 725
    • 726
    • 727
    • 728
    • 729
    • 730
    • 731
    • 732
    • 733
    • 734
    • 735
    • 736
    • 737
    • 738
    • 739
    • 740
    • 741
    • 742
    • 743
    • 744
    • 745
    • 746
    • 747
    • 748
    • 749
    • 750
    • 751
    • 752
    • 753
    • 754
    • 755
    • 756
    • 757
    • 758
    • 759
    • 760
    • 761
    • 762
    • 763
    • 764
    • 765
    • 766
    • 767
    • 768
    • 769
    • 770
    • 771
    • 772
    • 773
    • 774
    • 775
    • 776
    • 777
    • 778
    • 779
    • 780
    • 781
    • 782
    • 783
    • 784
    • 785
    • 786
    • 787
    • 788
    • 789
    • 790
    • 791
    • 792
    • 793
    • 794
    • 795
    • 796
    • 797
    • 798
    • 799
    • 800
    • 801
    • 802
    • 803
    • 804
    • 805
    • 806
    • 807
    • 808
    • 809
    • 810
    • 811
    • 812
    • 813
    • 814
    • 815
    • 816
    • 817
    • 818
    • 819
    • 820
    • 821
    • 822
    • 823
    • 824
    • 825
    • 826
    • 827
    • 828
    • 829
    • 830
    • 831
    • 832
    • 833
    • 834
    • 835
    • 836
    • 837
    • 838
    • 839
    • 840
    • 841
    • 842
    • 843
    • 844
    • 845

    4.需要一个Blob.js 内容如下 (跟Export2Excel.js 同放于项目src/assets/js 文件夹内)

    /* eslint-disable */
    /* Blob.js*/
    
    /*global self, unescape */
    /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
      plusplus: true */
    
    /*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */
    
    (function (view) {
      "use strict";
    
      view.URL = view.URL || view.webkitURL;
    
      if (view.Blob && view.URL) {
        try {
          new Blob;
          return;
        } catch (e) {
        }
      }
    
      // Internally we use a BlobBuilder implementation to base Blob off of
      // in order to support older browsers that only have BlobBuilder
      var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function (view) {
        var
          get_class = function (object) {
            return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
          }
          , FakeBlobBuilder = function BlobBuilder() {
            this.data = [];
          }
          , FakeBlob = function Blob(data, type, encoding) {
            this.data = data;
            this.size = data.length;
            this.type = type;
            this.encoding = encoding;
          }
          , FBB_proto = FakeBlobBuilder.prototype
          , FB_proto = FakeBlob.prototype
          , FileReaderSync = view.FileReaderSync
          , FileException = function (type) {
            this.code = this[this.name = type];
          }
          , file_ex_codes = (
            "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "
            + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
          ).split(" ")
          , file_ex_code = file_ex_codes.length
          , real_URL = view.URL || view.webkitURL || view
          , real_create_object_URL = real_URL.createObjectURL
          , real_revoke_object_URL = real_URL.revokeObjectURL
          , URL = real_URL
          , btoa = view.btoa
          , atob = view.atob
    
          , ArrayBuffer = view.ArrayBuffer
          , Uint8Array = view.Uint8Array
    
          , origin = /^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/
        ;
        FakeBlob.fake = FB_proto.fake = true;
        while (file_ex_code--) {
          FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
        }
        // Polyfill URL
        if (!real_URL.createObjectURL) {
          URL = view.URL = function (uri) {
            var
              uri_info = document.createElementNS("http://www.w3.org/1999/xhtml", "a")
              , uri_origin
            ;
            uri_info.href = uri;
            if (!("origin" in uri_info)) {
              if (uri_info.protocol.toLowerCase() === "data:") {
                uri_info.origin = null;
              } else {
                uri_origin = uri.match(origin);
                uri_info.origin = uri_origin && uri_origin[1];
              }
            }
            return uri_info;
          };
        }
        URL.createObjectURL = function (blob) {
          var
            type = blob.type
            , data_URI_header
          ;
          if (type === null) {
            type = "application/octet-stream";
          }
          if (blob instanceof FakeBlob) {
            data_URI_header = "data:" + type;
            if (blob.encoding === "base64") {
              return data_URI_header + ";base64," + blob.data;
            } else if (blob.encoding === "URI") {
              return data_URI_header + "," + decodeURIComponent(blob.data);
            }
            if (btoa) {
              return data_URI_header + ";base64," + btoa(blob.data);
            } else {
              return data_URI_header + "," + encodeURIComponent(blob.data);
            }
          } else if (real_create_object_URL) {
            return real_create_object_URL.call(real_URL, blob);
          }
        };
        URL.revokeObjectURL = function (object_URL) {
          if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {
            real_revoke_object_URL.call(real_URL, object_URL);
          }
        };
        FBB_proto.append = function (data/*, endings*/) {
          var bb = this.data;
          // decode data to a binary string
          if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
            var
              str = ""
              , buf = new Uint8Array(data)
              , i = 0
              , buf_len = buf.length
            ;
            for (; i < buf_len; i++) {
              str += String.fromCharCode(buf[i]);
            }
            bb.push(str);
          } else if (get_class(data) === "Blob" || get_class(data) === "File") {
            if (FileReaderSync) {
              var fr = new FileReaderSync;
              bb.push(fr.readAsBinaryString(data));
            } else {
              // async FileReader won't work as BlobBuilder is sync
              throw new FileException("NOT_READABLE_ERR");
            }
          } else if (data instanceof FakeBlob) {
            if (data.encoding === "base64" && atob) {
              bb.push(atob(data.data));
            } else if (data.encoding === "URI") {
              bb.push(decodeURIComponent(data.data));
            } else if (data.encoding === "raw") {
              bb.push(data.data);
            }
          } else {
            if (typeof data !== "string") {
              data += ""; // convert unsupported types to strings
            }
            // decode UTF-16 to binary string
            bb.push(unescape(encodeURIComponent(data)));
          }
        };
        FBB_proto.getBlob = function (type) {
          if (!arguments.length) {
            type = null;
          }
          return new FakeBlob(this.data.join(""), type, "raw");
        };
        FBB_proto.toString = function () {
          return "[object BlobBuilder]";
        };
        FB_proto.slice = function (start, end, type) {
          var args = arguments.length;
          if (args < 3) {
            type = null;
          }
          return new FakeBlob(
            this.data.slice(start, args > 1 ? end : this.data.length)
            , type
            , this.encoding
          );
        };
        FB_proto.toString = function () {
          return "[object Blob]";
        };
        FB_proto.close = function () {
          this.size = 0;
          delete this.data;
        };
        return FakeBlobBuilder;
      }(view));
    
      view.Blob = function (blobParts, options) {
        var type = options ? (options.type || "") : "";
        var builder = new BlobBuilder();
        if (blobParts) {
          for (var i = 0, len = blobParts.length; i < len; i++) {
            if (Uint8Array && blobParts[i] instanceof Uint8Array) {
              builder.append(blobParts[i].buffer);
            }
            else {
              builder.append(blobParts[i]);
            }
          }
        }
        var blob = builder.getBlob(type);
        if (!blob.slice && blob.webkitSlice) {
          blob.slice = blob.webkitSlice;
        }
        return blob;
      };
    
      var getPrototypeOf = Object.getPrototypeOf || function (object) {
        return object.__proto__;
      };
      view.Blob.prototype = getPrototypeOf(new view.Blob());
    }(
      typeof self !== "undefined" && self
      || typeof window !== "undefined" && window
      || this
    ));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210

    5. 调用

    解释一下模板

      const excelDatas = [
                {
                  tHeader: ['项号', '序号', '编号' ...], // 表头
                  filterVal: ['GNo', 'Item', 'Code' ...], // 对应字段
                  tableDatas: [{GNo:1,Item:2,Code:3 ...}], // 对应json数据 
                  width: [{ wch: 7.88 }, { wch: 7.5 }, { wch: 13.88 } ...], // 有几列就有几个宽 从左往右排
                  height: [{ hpx: 15.75 } ...], // 有几行就有几个高 从上往下排
                  multiHeader: [
                    ['', '', '', '', '', '项目', '签名', '日期'],
                    ['', '', '', '', '', '制单: ', '', ''],
                    ['', '', '', '', '', '初审: ', '', ''],
                    ['', '', '', '', '', '复审: ', '', ''],
                    ['No :', '', 'Date', 'Code', 'From', '', 'To', ''],
                    [list[i].entry, '', '0:00:00', '', '中国', '', '', 'by Air'],
                    ['', '', '', '', '', '', '', '']
                  ], // 在表头之上 的自定义数据摆放  如果不是规则的数据 请在次添加
                  autowidth: false, // 单元格是否自动宽高 如自动宽高 则 width  height 为空
                  merges: ['A1:D1', 'A5:H5', 'A6:H6', 'A13:B13', 'A14:B14', 'A16:C16', 'B8:D8', 'F8:H8', 'E13:F13', 'E14:F14', 'E15:F15', 'E16:F16', 'A15:C15', 'B17:C17'],// 合并单元格
                  sheetName: '清单'// sheet 名称
                }, 
                {
                  tHeader: [],
                  filterVal: [],
                  tableDatas: [],
                  width: [{ wch: 7.88 }, { wch: 7.5 }, { wch: 13.88 }, { wch: 11.63 }, { wch: 10.5 }, { wch: 11.38 }, { wch: 13.5 }, { wch: 10.38 }],
                  height: [{ hpx: 15.75 }, { hpx: 15 }, { hpx: 12.75 }, { hpx: 12.75 }, { hpx: 21 }, { hpx: 15 }, { hpx: 12.75 }, { hpx: 12.75 }, { hpx: 12.75 }, { hpx: 12.75 },
                    { hpx: 12.75 }, { hpx: 12.75 }, { hpx: 12.75 }, { hpx: 12.75 }, { hpx: 12.75 }, { hpx: 12.75 }, { hpx: 12.75 }, { hpx: 12.75 }],
                  autowidth: false,
                  multiHeader: [
                    [list[i].entry, '', '', '', '', '', '', ''],
                    ['', '', '', '', '', '', '', ''],
                    ['', '', '', '', 'FOB', '', '(1/1)', ''],
                    ['Item No..', 'Description of Goods', '', 'PO No.', 'Q\'TY(PCS)', 'ORIGIN', 'U/Price(USD)', 'TTL AMT(USD)'],
                    ['', '', '', '', '', '', '', '']
                  ],
                  merges: ['A1:D1', 'A5:H5', 'A6:H6', 'A13:B13', 'A14:B14', 'A16:C16', 'B8:D8', 'F8:H8', 'E13:F13', 'E14:F14', 'E15:F15', 'E16:F16', 'A15:C15', 'B17:C17'],
                  sheetName: '清单2' // 许可证信息
                }
                ...
              ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    在使用页面内 预置2个函数

    
     // 数据过滤,时间过滤
     formatJson (filterVal, jsonData) {
         return jsonData.map(v => filterVal.map(j => {
           if (j === 'timestamp') {
             return parseTime(v[j])
           } else {
             return v[j]
           }
         }))
       },
      json2excel (tableJson, filenames, bookTypes, status) {
            var that = this
            if (status === 1) {
              // do something
            }
            // 这个是引用插件
            import('@/assets/js/Export2Excel').then(excel => {
              var tHeader = []
              var dataArr = []
              var sheetnames = []
              var multiHeaderlsit = []
              var mergeslsit = []
              var widthlsit = []
              var heightlsit = []
              var autowidthlist = []
              for (var i in tableJson) {
                multiHeaderlsit.push(tableJson[i].multiHeader)
                mergeslsit.push(tableJson[i].merges)
                widthlsit.push(tableJson[i].width)
                heightlsit.push(tableJson[i].height)
                tHeader.push(tableJson[i].tHeader)
                autowidthlist.push(tableJson[i].autowidth)
                dataArr.push(that.formatJson(tableJson[i].filterVal, tableJson[i].tableDatas))
                sheetnames.push(tableJson[i].sheetName)
              }
              // console.log('dataArr', dataArr)
              excel.export_json_to_excel({
                multiHeader: multiHeaderlsit,
                header: tHeader,
                data: dataArr,
                width: widthlsit,
                height: heightlsit,
                merges: mergeslsit,
                sheetname: sheetnames,
                filename: filenames,
                autoWidth: autowidthlist,
                bookType: bookTypes,
                isreturn: false,
                status: status
              })
         	// do something
            })
          },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    示例:

    // 导出一个表格 
    dohandingB (){
    	for (let i = 0; i < list.length; i++) {
    	
    	const excelDatas = [
                {
                  tHeader: ['项号', '序号', '编号' ...], // 表头
                  filterVal: ['GNo', 'Item', 'Code' ...], // 对应字段
                  tableDatas: [...list[i]], // 对应json数据列表
                  width: [{ wch: 7.88 }, { wch: 7.5 }, { wch: 13.88 } ...], // 有几列就有几个宽 从左往右排
                  height: [{ hpx: 15.75 } ...], // 有几行就有几个高 从上往下排
                  multiHeader: [],
                  merges: ['A1:J1'],
                  width: [],
                  height: [],
                  autowidth: true,
                  sheetName: '信息'// 基本信息&商品信息
                  },
                  // 多张sheet 多个对象
              ]
          // 在这里excelDatas 可以追加新数据 
          
          const filename = '文件名'+ xxx
          // 下方调用 如有多张表格导出需要增加队列(一个一个排队导出) 并延迟300毫秒才不会导出错误
          this.json2excel(excelDatas, filename, 'xlsx', 1) // 1 为status 第一种模板
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    如果多个表格导出 可以打成压缩包再导出

    需要在安装依赖 “jszip”: “3.10.0”, 和 “file-saver”: “2.0.5”,
    页面引入 import JSZip from ‘jszip’ 和 import fileSaver from ‘file-saver’

          exportALL () {
            const that = this
            this.zip = new JSZip() 
            const list1 = [
            {
              data: excelDatas, // 导入数据模板(见上方详情)
              name: filename, //文件名
              status: 2 //
            },
            ...
            ]
            const list2 = [...list1]
            const list = list1.concat(list2)
            this.excelDataslist3 = []
            for (let i = 0; i < list.length; i++) {
              if (i === 0) { // 如果是第一个 直接导出
              	that.isdone4 = false //队列开始标识
                import('@/assets/js/Export2Excel').then(excel => {
                  var tHeader = []
                  var dataArr = []
                  var sheetnames = []
                  var multiHeaderlsit = []
                  var mergeslsit = []
                  var widthlsit = []
                  var heightlsit = []
                  var autowidthlist = []
                  for (var j in list[i].data) {
                    multiHeaderlsit.push(list[i].data[j].multiHeader)
                    mergeslsit.push(list[i].data[j].merges)
                    widthlsit.push(list[i].data[j].width)
                    heightlsit.push(list[i].data[j].height)
                    tHeader.push(list[i].data[j].tHeader)
                    autowidthlist.push(list[i].data[j].autowidth)
                    dataArr.push(that.formatJson(list[i].data[j].filterVal, list[i].data[j].tableDatas))
                    sheetnames.push(list[i].data[j].sheetName)
                  }
                  // console.log('dataArr', dataArr)
                  const a = excel.export_json_to_excel2({
                    multiHeader: multiHeaderlsit,
                    header: tHeader,
                    data: dataArr,
                    width: widthlsit,
                    height: heightlsit,
                    merges: mergeslsit,
                    sheetname: sheetnames,
                    filename: list[i].name,
                    autoWidth: autowidthlist,
                    isreturn: true,
                    bookType: 'xlsx',
                    status: list[i].status
                  }) // a 就是返回bolb数据
                  // console.log('a', a)
                  that.zip.file(list[i].name + '.xlsx', a, { binary: true })
                  that.isdone4 = true //队列每条结束标识
                })
                // console.log('this.zip', that.zip)
              } else {
                this.excelDataslist3.push({
                  data: list[i].data,
                  name: list[i].name,
                  status: list[i].status
                })
              }
            }
          },
    	 // 监听 isdone4 的开关 可以知道队列的开始与结束  判断之后this.excelDataslist3为空 调用下方代码下载压缩包即可
    	  this.zip.generateAsync({ type: 'blob' }).then(content => { // 生成二进制流
                // console.log('content', content)
                fileSaver.saveAs(content, '文件名' + '.zip') // 利用file-saver保存文件
              })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    整理到这里 如有错误可以指出,如有疑问可以评论询问

  • 相关阅读:
    企业电子招投标采购系统——功能模块&功能描述+数字化采购管理 采购招投标
    17-Spring AOP源码分析-AnnotationAwareAspectJAutoProxyCreator
    关于技术面试思考
    synchronized关键字的作用
    Java 24 Design Pattern 之 原型模式
    Ubuntu18.04 ROS Melodic的cv_bridge指向问题(四种方式,包括opencv4)(转载)
    JavaScript Json -笔记
    【大厂高频真题100题】《岛屿数量》 真题练习第12题 持续更新~
    Kafka部署、原理和使用介绍
    华为数字化转型之道 方法篇 第四章 用变革的方法确保规划落地
  • 原文地址:https://blog.csdn.net/qq_41299955/article/details/126384810