纯前端导出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("");
  }

  • 增加缩放,设置纵横向 设置打印纸张大小 功能
    搜索关键词 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;
  }

搜索关键字 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] = '<sheetData/>';
    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] = ('</sheetData>'); 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] = ('</worksheet>'); o[1]=o[1].replace("/>",">"); }
    return o.join("");
  }

  • 增加页边距设置
    搜索关键词 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
  }

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

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

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 */

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
));

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' // 许可证信息
            }
            ...
          ]

在使用页面内 预置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
        })
      },

示例:

// 导出一个表格 
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 第一种模板
	}
}

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

需要在安装依赖 “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保存文件
          })

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

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值