XLSX初探 纯前端导出多个sheet的excel

422 阅读2分钟

1.XLSX

官方Github:github.com/SheetJS/she…

2.安装XLSX

注:这里使用纯原生H5编写一个简单的demo不引入任何框架。

2.1 搭建一个简单的目录结构

- xlsx 根目录
-- xlsxExport 封装导出方法和安装xlsx的目录
--- index.js 封装导出方法
-- index.html 使用演示

2.2 安装XLSX

安装方式参考官方Github,这里在xlsxExport目录下使用npm方式安装:

npm install xlsx

3.封装导出excel方法

下面是xlsxExport/index.js中的代码:

/**
 * 将html表格保存为excel
 * @param {Object} opt
 * @returns
 */
/*
  opt参数示例:
  {
    sheets:[
      {
        table: document.getElmentById('table1'),
        noExportClass: 'table1_noexport',
        name: '表一',
      },
      {
        table: document.getElmentById('table2'),
        noExportClass: ['table2_noexport', 'left', 'right'],
        name: '采购表',
      },
      {
        table: document.getElmentById('table3'),
      }
    ],
    noExportClass:'noExportClass',
    fileName:'table2Excel测试表格',
  }
*/
function table2Excel(
  opt = {
    sheets: [], // 要导出的sheet数组 必填 数组每一项生成一个sheet
    /*
      sheet的结构:
      {
        table:Node, // 要导出的table结构 必传
        name:string, // sheet的名字 可选
        noExportClass:string | string[], // 不被导出的class 可选 只对当前table生效
      }
    */
    noExportClass: "", // 不被导出的class对全部table生效 可选 string | string[]
    fileName: "", // 文件名 可选 不传默认为当前时间戳
  }
) {
  if (!opt.sheets || !opt.sheets.length || !Array.isArray(opt.sheets)) {
    reject("opt.sheets参数类型错误!");
  }

  const sheets = opt.sheets;
  const book = __createBook();
  for (let i = 0; i < sheets.length; i++) {
    if (!sheets[i].table) {
      console.error("opt.sheets参数错误!");
      return;
    }
    if (!sheets[i].name) {
      sheets[i]["name"] = `表格${i + 1}`;
    }
    if (!sheets[i].noExportClass) {
      sheets[i].noExportClass = [];
    }
    if (
      sheets[i].noExportClass &&
      typeof sheets[i].noExportClass === "string"
    ) {
      sheets[i].noExportClass = [sheets[i].noExportClass];
    }
    if (!opt.noExportClass) {
      opt.noExportClass = [];
    }
    if (opt.noExportClass && typeof opt.noExportClass == "string") {
      opt.noExportClass = [opt.noExportClass];
    }
    opt.noExportClass.forEach((className) => {
      sheets[i].noExportClass.push(className);
    });

    // 移除不需要导出的dom
    sheets[i].table = __removeFromNodeByClass(
      sheets[i].table,
      sheets[i].noExportClass
    );

    // 添加sheet对象
    __addSheets(book, __createSheetByTable(sheets[i].table), sheets[i].name);
  }

  __download(book, opt.fileName);
}

// private >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/**
 * 从指定节点上移除指定类名的dom
 * @param {*} node
 * @param {*} classNames
 */
function __removeFromNodeByClass(node, classNames) {
  const target = node.cloneNode(true); // 拷贝dom 防止引用界面上的dom时导致显示混乱
  classNames.forEach((name) => {
    const removeDoms = Array.from(target.getElementsByClassName(name));
    if (removeDoms.length) {
      removeDoms.forEach((item) => {
        item.remove();
      });
    }
  });
  return target;
}

/**
 * 通过table创建XLSX sheet对象
 * @param {*} table
 */
function __createSheetByTable(table) {
  return XLSX.utils.table_to_sheet(table);
}

/**
 * 创建XLSX Book对象
 */
function __createBook() {
  return XLSX.utils.book_new();
}

/**
 * 向Book添加sheet
 * @param {*} book
 * @param {*} sheet
 */
function __addSheets(book, sheet, name) {
  XLSX.utils.book_append_sheet(book, sheet, name);
}

/**
 * 导出文件
 * @param {*} book
 * @param {*} filename
 */
function __download(book, filename = "") {
  if (!filename) {
    filename = new Date().getTime() + "";
  }
  filename += ".xlsx";
  XLSX.writeFile(book, filename);
}

4.导出excel演示

下面是index.html中的代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <table id="table1" border="1">
      <thead>
        <tr>
          <td colspan="3">
            表格1<span class="test1">表格1删除测试1</span
            ><span class="test2">表格1删除测试2</span>
          </td>
        </tr>
        <tr>
          <td>表头1</td>
          <td>表头2</td>
          <td>表头3</td>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>数据1</td>
          <td>数据2</td>
          <td>数据3</td>
        </tr>
      </tbody>
    </table>
    <table id="table2" border="1">
      <thead>
        <tr>
          <td colspan="3">
            表格2<span class="test1">表格1删除测试1</span
            ><span class="test2">表格1删除测试2</span>
          </td>
        </tr>
        <tr>
          <td>表头a</td>
          <td>表头b</td>
          <td>表头c</td>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>数据a</td>
          <td>数据b</td>
          <td>数据c</td>
        </tr>
      </tbody>
    </table>
    <button id="exportBtn">导出</button>
    <!-- 先引入xlsx.full.min.js再引入/xlsxExport/index.js -->
    <script src="./xlsxExport/node_modules/xlsx/dist/xlsx.full.min.js"></script>
    <!-- 引入table2Excel -->
    <script src="./xlsxExport/index.js"></script>
    <script>
      document.getElementById("exportBtn").onclick = () => {
        table2Excel({
          sheets: [
            {
              table: document.getElementById("table1"),
              name: "测试数据1",
              noExportClass: "test1",
            },
            {
              table: document.getElementById("table2"),
            },
          ],
          fileName: "你好",
          noExportClass: "test2",
        });
      };
    </script>
    <script>
      
    </script>
  </body>
</html>