前端把数据导出xlsx格式表格文件(仅仅作为插件使用方法记录)

219 阅读1分钟
import XLSX from 'xlsx';
async downloadFile() { // 点击导出按钮
      const KEY_STORE = {
        'nickname': '昵称',
        'realname': '真实姓名',
        'user_id': '讲师ID',
        'phone_number': '电话号码',
        'created_at': '时间',
      }
      const KEY_MAP = Object.keys(KEY_STORE);
      const pageSize = 100;
      const page = Math.min(Math.ceil(this.total / pageSize), 100);
      const params = Object.assign({}, {
        page: 1,
        pageSize
      });
      // 拼接label
      const data = [KEY_STORE];
      // 循环获取数据
      for (let i = 1; i <= page; i++) {
        params.page = i;
        const { students } = await this.getDataForTabel(params);
        data.push(...students);
        this.excelPercent = Math.trunc((i / page).toFixed(2) * 100);
      }
      // 可以在下载文件名后加日期
      // const d = new Date();
      // const time = [];
      // time.push(d.getFullYear());
      // time.push(d.getMonth() + 1);
      // time.push(d.getDate())
      data.forEach((item, index) => {
        if (index !== 0) {
          item.created_at = formatDateTime(item.created_at)
        }
      })
      this.downloadExl(KEY_MAP, data, this.title);
    },
    downloadExl(keyMap, json, downName, type = 'xlsx') { // 导出到excel
      const tmpdata = []; // 用来保存转换好的json
      json
        .map((v, i) => {
          return keyMap.map((k, j) => {
            return Object.assign({}, {
              v: v[k],
              position: (j > 25 ? this.getCharCol(j) : String.fromCharCode(65 + j)) + (i + 1)
            })
          })
        })
        .reduce((prev, next) => {
          return prev.concat(next)
        })
        .forEach((v) => {
          tmpdata[v.position] = {
            v: v.v
          }
        });
      const outputPos = Object.keys(tmpdata) // 设置区域,比如表格从A1到D10
      const tmpWB = {
        SheetNames: ['Sheet1'], // 保存的表标题
        Sheets: {
          'Sheet1': Object.assign(
            {},
            tmpdata, // 内容
            {
              '!ref': outputPos[0] + ':' + outputPos[outputPos.length - 1] // 设置填充区域
            }
          )
        }
      }
      const tmpDown = new Blob(
        [
          this.s2ab(
            XLSX.write(
              tmpWB,
              {
                bookType: type,
                bookSST: false,
                type: 'binary'
              } // 这里的数据是用来定义导出的格式类型
            )
          )
        ]
      ); // 创建二进制对象写入转换好的字节流
      var href = URL.createObjectURL(tmpDown); // 创建对象超链接
      const a = document.createElement('a');
      a.download = downName + '.xlsx'; // 下载名称
      a.href = href;
      a.click();
      URL.revokeObjectURL(tmpDown); // 用URL.revokeObjectURL()来释放这个object URL
      // reset
      this.$message({
        message: '导出excel成功',
        type: 'success'
      })
      this.excelDialogVisible = false;
      this.excelPercent = 0;
    },
    getCharCol(n) { // 将指定的自然数转换为26进制表示。映射关系:[0-25] -> [A-Z]。
      let s = '';
      let m = 0;
      while (n > 0) {
        m = n % 26 + 1;
        s = String.fromCharCode(m + 64) + s;
        n = (n - m) / 26;
      }
      return s;
    },
    s2ab(s) { // 字符串转字符流
      const buf = new ArrayBuffer(s.length);
      const view = new Uint8Array(buf);
      for (let i = 0; i < s.length; i++) {
        view[i] = s.charCodeAt(i) & 0xFF;
      }
      return buf;
    },