前端依靠sheetjs完成excel文件的导入解析,和excel下载

3,846 阅读2分钟

安装依赖

<script lang="javascript" src="dist/xlsx.full.min.js"></script>

npm i xlsx

一、excel文件的导入与解析

  1. 这次导入的是一个后台管理机构的模板文件

image.png

  1. 我们依靠vue和element搭建一个demo
<!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>纯前端excel解析与下载</title>
    <link
      rel="stylesheet"
      href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"
    />
    <!-- import Vue before Element -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <!-- import JavaScript -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    <script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>
  </head>
  <body>
    <div id="app">
      <el-upload
        class="upload-demo"
        ref="upload"
        action="xlsx.html"
        :auto-upload="false"
        :on-change="getMyExcel"
      >
        <el-button size="small" type="primary">选取文件</el-button>
      </el-upload>
      <el-button size="small" type="primary" style="margin-top: 10px"
        >模板文件导出</el-button
      >
    </div>
  </body>
  <script>
    new Vue({
      el: "#app",
      data: function () {
        return { visible: false };
      },
      methods: {
        getMyExcel(file, fileList) {
          console.log(file);
        },
      },
    });
  </script>
</html>

通过element的uopload组件的onchang事件可以获取到file文件 如图:

image.png

  1. 已经获取到文件后,我们用sheetjs来进行解析
        getMyExcel(file, fileList) {
          // 用FileReader来完成数据流的转换
          let reader = new FileReader();
          reader.onload = function (e) {
            let data = e.target.result;
            //通过XLSX来解析出workbook(工作簿)也就导入的excel文件
            let wb = XLSX.read(data, { type: "binary" });
            console.log(wb);
          };
          //readAsBinaryString需要File 或 Blob 对象的参数
          reader.readAsBinaryString(file.raw);
          // console.log(XLSX.read(file, { type: "array" }));
        },

可以得到下面的结果:

image.png

SheetNames保存着工作簿下的所有工作表 我们这个demo中只要关注SheetNames中的第一个表,也就是sheet1。

image.png

工作表中我们只要注意这三种属性即可:

  1. !merges工作表中合并单元格相对应的范围对象的数组,c和r分别是列和行的缩写 image.png
  2. !ref工作表的范围,也就是左上到右下的坐标

image.png 参考这个坐标图就很好理解了 image.png

  1. 所有有内容的单元格 每个单元格的V属性就是对应的内容 image.png

有了每个单元格的坐标和内容,就完成了我们解析的要求。 官方还提供了一些便捷的api,需要的可以去官网看下:

image.png

二、excel文件的导出

  1. 首先我们需要创建一个wb工作簿 let wb = XLSX.utils.book_new();

  2. 创建工作表的内容数组,一定要是二维的,不然插入的时候会报错~!

 let ws_data = [
            ["S", "h", "e", "e", "t", "J", "S"],
            [1, 2, 3, 4, 5],
          ];`
  1. 创建一个工作表,写入内容,并插入到工作簿中。
let ws_name = "模板文件";
let ws = XLSX.utils.aoa_to_sheet(ws_data);
XLSX.utils.book_append_sheet(wb, ws, ws_name);

这时我们可以打印wb看下:

image.png 没有问题,准备导出

  1. 导出文件

XLSX.writeFile(wb, filename, write_opts) 把 wb 写入到特定的文件 filename 中。如果是基于浏览器的环境,此函数会强制浏览器端下载。 XLSX.writeFileAsync(filename, wb, o, cb) 把 wb 写入到特定的文件 filename 中。如果 o 被省略,写入函数会使用第三个参数作为回调函数。

XLSX.writeFile(wb, "后台配置模板.xlsx", { bookType: "xlsx" });

导出内容如下:

image.png

  1. 补充 如果导出的文件需要合并单元格 需要在工作表中添加!merges属性,给出合并的范围即可 如果需要配置样式,需要专业版以上,付费的。

完整代码

<!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>纯前端excel解析与下载</title>
    <link
      rel="stylesheet"
      href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"
    />
    <!-- import Vue before Element -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <!-- import JavaScript -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>

    <script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>
  </head>
  <body>
    <div id="app">
      <el-upload
        class="upload-demo"
        ref="upload"
        action="xlsx.html"
        :auto-upload="false"
        :on-change="getMyExcel"
      >
        <el-button size="small" type="primary">选取文件</el-button>
      </el-upload>
      <el-button
        size="small"
        type="primary"
        style="margin-top: 10px"
        @click="downLoad"
        >模板文件导出</el-button
      >
    </div>
  </body>
  <script>
    new Vue({
      el: "#app",
      data: function () {
        return {};
      },
      methods: {
        getMyExcel(file, fileList) {
          // 用FileReader来完成数据流的转换
          let reader = new FileReader();
          reader.onload = function (e) {
            let data = e.target.result;
            //通过XLSX来解析出workbook(工作簿)也就导入的excel文件
            let wb = XLSX.read(data, { type: "binary" });
            console.log(wb);
          };
          //readAsBinaryString需要File 或 Blob 对象的参数
          reader.readAsBinaryString(file.raw);
          // console.log(XLSX.read(file, { type: "array" }));
        },
        downLoad() {
          let wb = XLSX.utils.book_new();
          //创建工作表的内容数组
          let ws_data = [
            ["S", "h", "e", "e", "t", "J", "S"],
            [1, 2, 3, 4, 5],
          ];
          let ws_name = "模板文件";
          //写入工作表
          let ws = XLSX.utils.aoa_to_sheet(ws_data);
          //插入工作簿
          XLSX.utils.book_append_sheet(wb, ws, ws_name);
          XLSX.writeFile(wb, "后台配置模板.xlsx", { bookType: "xlsx" });
        },
      },
    });
  </script>
</html>

参考链接

sheetjs官网:github.com/sheetjs/she…

sheetjs中文镜像:github.com/liyutg/shee…