解析excel


先上效果图:

在这里插入图片描述

功能:

  • 解析excel文件
  • 将解析的数据在表格展示
  • 解决表格中存在单元格合并的问题

官网https://www.npmjs.com/package/xlsx

1、引入插件

  • 安装 xlsx 插件

    npm i xlsx -S

  • 引入

    • 直接在当前页面中引用
    const xlsx = require("xlsx");
    // import xlsx from 'xlsx';
    
    • 全局使用
    // main.js
    import Vue from 'vue';
    import xlsx from 'xlsx';
    
    Vue.prototype.$xlsx = xlsx;
    
  • 可以通过引入 CDN 的方式

    <script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>
    

2、解析文件

  • 基本使用

    可以去node_modules/xlsx目录下查看相关的文档,里面非常详细的说明了该插件的使用(解析本地excel文件、解析远程返回的excel文件等),包含了使用的例子。

    xlsx 的 read 方法:(注意 options 的参数类型)

    function read(blob, options) {
    	switch(options && options.type || "base64") {
    		case "file": return read_file(blob, options);
    		case "base64": return parse(s2a(Base64.decode(blob)), options);
    		case "binary": return parse(s2a(blob), options);
    	}
    	return parse(blob, options);
    }
    

    具体的解析原理我也没看懂太多,就不赘述了。

  • 做简单封装

    • 解析excel文件
    const { read } = require("xlsx");
    // 获取解析后的数据
    exports.showxlsx = function(
    	data , 
        type = "readAsBinaryString" , 
        options = { type: "binary"}
    	) {
      return new Promise( (resolve,reject) => {
        const file = new FileReader();
        file[type](data);
        // 加载事件
        file.onload = function(e){
          let result = e.target.result; // 获取文件内容
          try { resolve(read(result , options));} 
          catch (error) { reject(error); }
        }
      })
    }
    

    在这里插入图片描述

    • 处理解析得到的数据
    exports.parse = function(params) {
      let SheetNames = params.SheetNames[0];
      if(!SheetNames) throw new Error("params error !");
      let obj = {...params.Sheets[SheetNames]};
      if(!obj) throw new Error(`${SheetNames} error !`);
      let res = {} , merge = [] , header = []; // 主要数据 , 合并信息 , 表头
      Object.keys(obj).map( v => {
        // 暂时不明确作用,先去除
        if(v == "!margins" || v == "!ref") return ;
        // 获取合并的信息
        if(v == "!merges") {
          obj[v].map( item => { merge.push(getMergeMessage(item)); })
          return ;
        }
        // 存储每一行的信息
        let [row , number] = [v.split("").slice(0,1) , v.split("").slice(1).join("")];
        !res[row] && (res[row] = []);
        res[row][number] = obj[v]["v"];
      })
      for(let k in res){
        if(!(/[a-zA-Z]/.test(k))) continue;
        header.push({ prop: k, label: k }) // 表头数据(A-Z)
      }
      return {
        header,
        data: res,
        merge: merge[0],
      }
    }
    // 获取合并信息
    function getMergeMessage(obj) {
      let result = []
      Object.keys(obj).map( v => {
        result.push([obj[v].r,obj[v].c]);
      })
      return result;
    }
    

    在这里插入图片描述

3、展示数据

  • 封装表格组件(略)

  • 通过 el-upload 获取 file 信息(监听 on-change )(略)

  • on-change 事件 (前提:先引入上述方法)

    // 获取 excel 文件数据
    onchange(file) {
      this.loading = true;
      showxlsx(file).then((res) => {
        let result = parse(res);
        this.tableHeader = result.header;
        this.tableData = [];
        let max = Math.max.apply(
          "",
          this.tableHeader.map((v) => {
            return result.data[v.label].length;
          })
        );
        // 由于 data 记录的每一列的数据,需要进行处理  
        for (let i = 0; i < max; i++) {
          this.tableData[i] = {};
          this.tableHeader.map((v) => {
            this.tableData[i][v.label] = result.data[v.label][i] || "";
          });
          this.tableData = this.tableData.filter((v) => {
            return Object.values(v).filter((val) => val).length > 0;
          });
        }
        this.$nextTick(() => {
          this.$refs.mtable.$refs.mTable.doLayout(); // 解决表格信息错乱
          this.loading = false;
        });
        this.merge = [...result.merge]; // 传给表格组件的表格合并数据
      });
    },
    

4、解决单元合并

  • 表格组件

    <el-table
      :ref="refName"
      :show-header="showHeader"
      :span-method="arraySpanMethod"
    >...</el-table>
    <script>
    export default {
    	props: {
            // 合并的数据
            mergeTable: {
              type: Array,
              default: function() {
                return [];
              },
            }
        }
    },
    methods: {
    // 增加表格合并
    arraySpanMethod({ rowIndex }) {
      if(!this.merge.length) return ;
      let arr = this.mergeTable.map( v => {
        let [r , c] = v; // 行 列
        if(rowIndex == r)
          return Number(c) + 1;
      }).filter( v => v);
      return arr.length?arr:"";
    },
    }
    </script>
    

5、后续优化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值