前端用xlsx实现导出表格数据到excel的功能

之前做导出表格功能时,都是后端进行实现,最近,领导要求前端实现导出,经过一番查找资料终于实现。

普通方式

下包

npm i -S file-saver xlsx

在util文件夹新建类

建立to_xlsx.js

 1 import FileSaver from 'file-saver';
 2 import XLSX2 from 'xlsx';
 3 
 4 class ToXlsx {
 5   // id指的是绑定数据的table的id,
 6   // title指的是导出表格的名称,记得带后缀xlsx,例如:title='重复导.xlsx';
 7   constructor (id, title) {
 8     this.id = id;
 9     this.title = title;
10   }
11   
12   async createTable() {
13
    // 判断要导出的节点中是否有fixed的表格,如果有,转换excel时将该dom移除
      let table = document.querySelector(this.id).cloneNode(true);
      let fix = table.querySelector(".el-table__fixed");
      let fix_left = table.querySelector(".el-table__fixed-left");
      let fix_right = table.querySelector(".el-table__fixed-right");

      fix && table.removeChild(fix);
      fix_left && table.removeChild(fix_left);
      fix_right && table.removeChild(fix_right);
      let wb;
      wb = XLSX2.utils.table_to_book(table);
22   
23     
24     /* get binary string as output */
25     let wBout = XLSX2.write(wb, {
26       bookType: 'xlsx',
27       bookSST: true,
28       type: 'array'
29     });
30     try {
31       FileSaver.saveAs(
32         new Blob([wBout], {
33           type: 'application/octet-stream'
34         }),
35         this.title
36       );
37     } catch (e) {
38       if (typeof console !== 'undefined') console.log(e, wBout);
39     }
40     return wBout;
41   }
42 }
43 
44 export default ToXlsx

使用

在js页面直接import,然后使用

import ToXlsx from "../../utils/to_xlsx";

// 参数1 表格id
// 参数2 保存的excel文件名
let xlsx = new ToXlsx('#table-data', '下载.xlsx');
xlsx.createNormalTable()

自定义样式

下包

npm i -S xlsx-style xlsx

xlsx-style报错修改

 

 

 

个时候需要修改源码

在\node_modules\xlsx-style\dist\cpexcel.js 807行把 var cpt = require('./cpt' + 'able'); 改成 var cpt = cptable;

如果还报错 在\node_modules\xlsx-style\ods.js 10行和13行把路径改为 require('./ xlsx')

在util文件夹新建类

建立to_xlsx.js

import XLSX2 from 'xlsx';
import XLSX from 'xlsx-style';

class ToXlsx {
  // id指的是绑定数据的table的id,
  // title指的是导出表格的名称,记得带后缀xlsx,例如:title='重复导.xlsx';
  constructor (id, title) {
    this.id = id;
    this.title = title;
  }
  
  /**
   * 自定义表格
   * @returns {Promise<void>}
   */
  async createCustomizeTable() {
  
   // 判断要导出的节点中是否有fixed的表格,如果有,转换excel时将该dom移除
    let table = document.querySelector(this.id).cloneNode(true);
    let fix = table.querySelector(".el-table__fixed");
    let fix_left = table.querySelector(".el-table__fixed-left");
    let fix_right = table.querySelector(".el-table__fixed-right");

    fix && table.removeChild(fix);
    fix_left && table.removeChild(fix_left);
    fix_right && table.removeChild(fix_right);

    let sheet = XLSX2.utils.table_to_sheet(table);
    // 设置单个单元格样式 ,A2对应的是excel表格的A2
    // sheet["A2"].s = {
    //   alignment: {
    //     horizontal: "center",
    //     vertical: "center",
    //     wrap_text: true
    //   }
    };
    
    // sheet居然是个对象,所以遍历就用for in
    // 偷个懒,因为要所有的表格都居中,所以这里就用for in 遍历设置了,如果只是单个设置,那就用上面的单独设置就行
    for (let key in sheet){
      if (new RegExp('^[A-Za-z0-9]+$').exec(key)) {
        let cell = key.toString();
        sheet[cell].s = {
          alignment: {
            horizontal: "center", // 水平对齐-居中
            vertical: "center", // 垂直对齐-居中
            wrap_text: true
          }
        }
      }
    }
    
    // wpx 字段表示以像素为单位,wch 字段表示以字符为单位
    // 注意,必须从第一个开始设置,不能只设置单独一个
    // !cows是列宽
    sheet['cols'] = [
          {wch: 16}, // A列
          {wch: 16}, // B列
          {wch: 16}, // C列
          {wch: 16}, // D列
    ];
   
    // !rows设置的行高
    sheet['!rows'] = [
          {wpx: 40,}, // 1行
          {wpx: 40}, // 2行
          {wpx: 40}, // 3行
          {wpx: 40}, // 4行
    ];
    try {
      this.openDownloadDialog(this.sheet2blob(sheet), this.title);
    } catch (e) {
     console.log('自定义表格报错', e);
    }
  }
  
  /**
   * 将表转换为最终excel文件的blob对象,并使用URL.createObjectUR下载它
   * @param sheet 表格配置项
   * @param sheetName 表格名称
   * @returns {Blob}
   */
  sheet2blob(sheet, sheetName) {
    sheetName = sheetName || 'sheet1';
    let workbook = {
      SheetNames: [sheetName],
      Sheets: {}
    };
    workbook.Sheets[sheetName] = sheet; // 生成excel的配置项
    
    let wopts = {
      bookType: 'xlsx', // 要生成的文件类型
      bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
      type: 'binary'
    };
    let wbout = XLSX.write(workbook, wopts);
    let blob = new Blob([s2ab(wbout)], {
      type: "application/octet-stream"
    }); // 字符串转ArrayBuffer
    
    function s2ab(s) {
      let buf = new ArrayBuffer(s.length);
      let view = new Uint8Array(buf);
      for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
      return buf;
    }
    return blob;
  }
  
  /**
   *
   * @param url 生成的文件
   * @param saveName 保存文件名称
   */
  openDownloadDialog(url, saveName) {
    if (typeof url == 'object' && url instanceof Blob) {
      url = URL.createObjectURL(url); // 创建blob地址
    }
    let aLink = document.createElement('a');
    aLink.href = url;
    aLink.download = saveName || ''; // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
    let event;
    if (window.MouseEvent) event = new MouseEvent('click');
    else {
      event = document.createEvent('MouseEvents');
      event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
    }
    aLink.dispatchEvent(event);
  }
}

export default ToXlsx

单元格样式

设置单元格的样式,就是设置工作表对象中的单元格对象的 s 属性。这个属性的值也是一个对象,它有五个属性:fill、font、numFmt、alignment和border。

Cell styles are specified by a style object that roughly parallels the OpenXML structure. The style object has five top-level attributes: fill, font, numFmt, alignment, and border.

使用

在js页面直接import,然后使用

import ToXlsx from "../../utils/to_xlsx";

// 参数1 表格id
// 参数2 保存的excel文件名
let xlsx = new ToXlsx('#table-data', '下载.xlsx');
xlsx.createCustomizeTable()

 

posted @ 2022-05-17 10:41  yuwenjing  阅读(2035)  评论(0编辑  收藏  举报