首頁 > 軟體

vue匯入處理Excel表格功能步驟詳解

2022-07-10 14:01:47

1. 前言

最近遇到前端匯入並處理excel表格的情況,趁此機會剛好研究一下vue匯入並處理excel資料;當然自己手擼一個工具沒有那麼多時間,本文只是藉助現有的工具來做一下工具使用總結。

2.vue匯入Excel表格

vue匯入Excel表格主要有兩種常用的方法,一個是藉助ElementUI檔案上傳進行表格匯入,另一個是自帶的input做檔案上傳;以下對兩個方法做詳細介紹;

2.1 使用ElementUI中的upload元件

安裝ElementUI

npm i element-ui -S

安裝Excel表格解析外掛

npm i xlsx -S

匯入需要用的工具包

import Vue from "vue";
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css";
import { read, utils } from "xlsx"; // 注意處理方法引入方式
Vue.use(ElementUI);

引入元件

<el-upload
        action="https://jsonplaceholder.typicode.com/posts/"
        :on-success="handleChange"
        :file-list="fileList"
        class="el-upload"
      >

新增處理邏輯

// 匯入成功時執行
handleChange(res, file, fileList) {
      // 將檔案放入
      for (let i = 0; i < fileList.length; i++) {
        if (file.name != fileList[i].name) {
          this.fileList.push({
            name: file.name,
            url: "",
            uid: file.uid
          });
        }
      }
      const files = { 0: file };
      this.readExcel(files);
    },
    readExcel(file) {
      const fileReader = new FileReader();

      fileReader.onload = ev => {
        try {
          const data = ev.target.result;
          const workbook = read(data, { type: "binary" });
          const params = [];
          // 取對應表生成json表格內容
          workbook.SheetNames.forEach(item => {
            this.tableData.push(utils.sheet_to_json(workbook.Sheets[item]));
          });
          // 該演演算法僅針對表頭無合併的情況
          if (this.tableData.length > 0) {
            // 獲取excel中第一個表格資料tableData[0][0],並且將表頭提取出來
            for (const key in this.tableData[0][0]) {
              this.tableHead.push(key);
            }
          }
          // 重寫資料
        } catch (e) {
          console.log("error:" + e);
          return false;
        }
      };
      fileReader.readAsBinaryString(file[0].raw);
    }

以上處理的資料我這邊用元件展示在了頁面上,效果如下圖:

2.2 使用input檔案上傳

1.安裝Excel表格解析外掛

npm i xlsx -S

2.匯入需要用的工具包

import { read, utils } from "xlsx"; // 注意處理方法引入方式

3.使用input

<div class="flex-display">
      <div class="left-box">檔案上傳(input):</div>
      <input type="file" v-on:change="onChange" class="file-ipt" />
    </div>

4.新增處理邏輯

基本與上面處理邏輯相同

onChange(e) {
      const file = e.target.files[0];
      const fileReader = new FileReader();

      fileReader.onload = ev => {
        try {
          const data = ev.target.result;
          const workbook = read(data, { type: "binary" });
          const params = [];
          // 取對應表生成json表格內容
          workbook.SheetNames.forEach(item => {
            params.push({
              name: item,
              dataList: utils.sheet_to_json(workbook.Sheets[item])
            });
            this.tableData.push(utils.sheet_to_json(workbook.Sheets[item]));
          });
          // 該演演算法僅針對表頭無合併的情況
          if (this.tableData.length > 0) {
            // 獲取excel中第一個表格資料tableData[0][0],並且將表頭提取出來
            for (const key in this.tableData[0][0]) {
              this.tableHead.push(key);
            }
          }
          return params;
          // 重寫資料
        } catch (e) {
          console.log("error:" + e);
          return false;
        }
      };
      fileReader.readAsBinaryString(file);
    }

3. 總體程式碼與效果

效果如下:

總的樣式以及程式碼如下:

<template>
  <div>
    <div class="flex-display">
      <div class="left-box">表格上傳(ElementUI):</div>
      <el-upload
        action="https://jsonplaceholder.typicode.com/posts/"
        :on-success="handleChange"
        :file-list="fileList"
        class="el-upload"
      >
        <el-button size="small" type="primary" class="el-btn"
          >點選上傳</el-button
        >
        <div slot="tip" class="el-upload-tip">
          只能上傳xlsx檔案,且不超過5MB
        </div>
      </el-upload>
    </div>
    <el-table v-if="tableHead.length" :data="tableData[0]" style="width: 100%">
      <el-table-column
        v-for="(data, key) in tableHead"
        :prop="data"
        :label="data"
        :key="key"
        width="180"
      >
      </el-table-column>
    </el-table>
    <div class="flex-display">
      <div class="left-box">檔案上傳(input):</div>
      <input type="file" v-on:change="onChange" class="file-ipt" />
    </div>
  </div>
</template>
<script>
import Vue from "vue";
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css";
import { read, utils } from "xlsx";

Vue.use(ElementUI);
export default {
  data() {
    return {
      fileList: [], //上傳檔案列表
      tableHead: [], //表頭
      tableData: [] // 表資料
    };
  },
  methods: {
    onChange(e) {
      const file = e.target.files[0];
      const fileReader = new FileReader();

      fileReader.onload = ev => {
        try {
          const data = ev.target.result;
          const workbook = read(data, { type: "binary" });
          const params = [];
          // 取對應表生成json表格內容
          workbook.SheetNames.forEach(item => {
            params.push({
              name: item,
              dataList: utils.sheet_to_json(workbook.Sheets[item])
            });
            this.tableData.push(utils.sheet_to_json(workbook.Sheets[item]));
          });
          // 該演演算法僅針對表頭無合併的情況
          if (this.tableData.length > 0) {
            // 獲取excel中第一個表格資料tableData[0][0],並且將表頭提取出來
            for (const key in this.tableData[0][0]) {
              this.tableHead.push(key);
            }
          }
          return params;
          // 重寫資料
        } catch (e) {
          console.log("error:" + e);
          return false;
        }
      };
      fileReader.readAsBinaryString(file);
    },
    handleChange(res, file, fileList) {
      // 將檔案放入
      for (let i = 0; i < fileList.length; i++) {
        if (file.name != fileList[i].name) {
          this.fileList.push({
            name: file.name,
            url: "",
            uid: file.uid
          });
        }
      }

      // this.fileList = fileList.slice(-3);
      const files = { 0: file };
      this.readExcel(files);
    },
    readExcel(file) {
      const fileReader = new FileReader();

      fileReader.onload = ev => {
        try {
          const data = ev.target.result;
          const workbook = read(data, { type: "binary" });
          const params = [];
          // 取對應表生成json表格內容
          workbook.SheetNames.forEach(item => {
            params.push({
              name: item,
              dataList: utils.sheet_to_json(workbook.Sheets[item])
            });
            this.tableData.push(utils.sheet_to_json(workbook.Sheets[item]));
          });
          // 該演演算法僅針對表頭無合併的情況
          if (this.tableData.length > 0) {
            // 獲取excel中第一個表格資料tableData[0][0],並且將表頭提取出來
            for (const key in this.tableData[0][0]) {
              this.tableHead.push(key);
            }
          }
          return params;
          // 重寫資料
        } catch (e) {
          console.log("error:" + e);
          return false;
        }
      };
      fileReader.readAsBinaryString(file[0].raw);
    }
  }
};
</script>
<style lang="scss" scoped>
.upload-demo {
  width: 100%;
}
.flex-display {
  margin: 50px 30px;
  width: 100%;
  display: flex;
  justify-content: flex-start;
  .left-box {
    margin: 20 30;
    height: 36px;
    line-height: 36px;
  }
}
.el-upload {
  margin-left: 40px;
  .el-btn {
    font-size: 16px;
  }
  .el-upload-tip {
    display: inline;
    font-size: 12px;
  }
}
.file-ipt {
  width: 200px;
  height: 36px;
  line-height: 36px;
  button {
    background-color: #409eff;
  }
}
input #file-upload-button {
  background-color: #409eff;
}
</style>

4. 總結

較為容易踩坑的點就是xlsx這個包的匯入方式,這個包處理excel表格功能時相當強大的,除了匯入與資料解析,還有匯出為excel等功能,在我們日常網站開發中非常常用。其次容易踩坑的就是vue中事件的監聽與處理方式,我們可以看到使用元件賀不使用元件區別還是比較大的,當然使用現有元件往往能獲得更好的效果,所以這裡還是推薦大家使用方法一去實現這個功能。

最後本文僅對資料做簡單處理,若要處理更為複雜的表格資料,就需要研究更強大的演演算法,不喜勿碰,謝謝。

到此這篇關於vue匯入處理Excel表格功能步驟的文章就介紹到這了,更多相關vue匯入處理Excel內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com