Vue封裝Excel導(dǎo)入組件并使用ElementUI顯示內(nèi)容,將json結(jié)果集傳遞給后端

前言

使用Vue讀取Excel內(nèi)的數(shù)據(jù)需要使用npm安裝xlsx,將結(jié)果提取出來(lái)然后動(dòng)態(tài)渲染到ElementUI的Table中進(jìn)行結(jié)果展示,再一步點(diǎn)擊確定來(lái)把數(shù)據(jù)傳遞給SpringBoot后端加入到數(shù)據(jù)庫(kù)中

一、演示

1.選擇文件

點(diǎn)擊導(dǎo)入按鈕后,選擇要導(dǎo)入的excel文件




2.查看內(nèi)容

這里為了演示就把讀取到的Excel數(shù)據(jù)直接展示出來(lái)了,后面會(huì)介紹如何轉(zhuǎn)換某些特定字段,例如:男女改為0,1



點(diǎn)擊確定導(dǎo)入后輸出一下要傳到后端的數(shù)據(jù)



二、界面

1.主頁(yè)面

一個(gè)按鈕,一個(gè)組件,UploadEx 為自定義上傳彈框組件,選擇文件界面和內(nèi)容列表界面都在此組件內(nèi),想要完成其他Excel文件讀取,只需要修改以下兩個(gè)組件屬性和一個(gè)方法

excelTitle:要映射的列名

urlStr:后端url

<el-button type="primary" @click="importShow = true">導(dǎo)入</el-button>
<UploadEx :isShow.sync="importShow" :excelTitle="excelTitle" urlStr="/api/excel/import/userinfo"></UploadEx>
data中的內(nèi)容

data(){
 return{
    importShow: false,
    excelTitle: [],
  }
},
在頁(yè)面created函數(shù)中設(shè)置excelTitle內(nèi)容

// 設(shè)置導(dǎo)出模板的列

setTitle(){
  this.excelTitle = []
  let et1 = {'label':'姓名', 'prop':'userName'}
  let et2 = {'label':'性別', 'prop':'userSex'}
  let et3 = {'label':'愛(ài)好', 'prop':'userHobby'}
  this.excelTitle.push(et1)
  this.excelTitle.push(et2)
  this.excelTitle.push(et3)
},
2.組件注冊(cè)

文件注冊(cè)大家可以使用import或下面這個(gè)方法來(lái)全局注冊(cè)

可以在此組件所在位置聲明一個(gè)index.js文件

// 公用組件
import uploadEx from './uploadEx.vue' // 文件上傳框

const components = {
  install: function (Vue) {
    // 公用組件
    Vue.component('UploadEx', uploadEx)
  }
}
export default components
然后main.js中修改,記得找對(duì)index.js文件

import components from './xxx/index'
Vue.use(components)

3.組件內(nèi)容

uploadEx組件HTML內(nèi)容如下,一個(gè)上傳框用于選擇文件,一個(gè)Table列表用于顯示Excel內(nèi)容

<template>
  <div>
    <el-dialog title="導(dǎo)入" :visible="isShow" :show-close='false' width="40%" @before-close="importClose">
      <el-upload style="margin: 10px auto;"
        drag
        action=""
        :on-change="handleChange"
        :show-file-list="false"
        :on-remove="handleRemove"
        :file-list="fileListUpload"
        :limit="1"
        accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
        :auto-upload="false">
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">點(diǎn)擊上傳</div>
        <div class="el-upload__tip" slot="tip">只能上傳xlsx和xls格式的且大小必須小于2M</div>
      </el-upload>
      <span slot="footer" class="dialog-footer">
        <el-button @click="importClose()">取消</el-button>
      </span>
    </el-dialog>
    <el-dialog
      title="Excel內(nèi)容" :visible.sync="excelShow" width="60%" center>
      <el-table
        :data="excelData"
        ref="excelDataRef"
        border
        style="width: 100%;height:300px;overflow-y:scroll;">
        <template v-for='(col,index) in excelTitle'>
          <el-table-column
            :prop="col.prop"
            :label="col.label"
            :key="index">
          </el-table-column>
        </template>
      </el-table>
      <span slot="footer" class="dialog-footer">
        <el-button @click="excelShow = false;fileTemp = null;fileListUpload = []">重新選擇</el-button>
        <el-button type="primary" @click="importExcel()">確定導(dǎo)入</el-button>
      </span>
    </el-dialog>
  </div>
</template>
樣式就是隨便加個(gè)吧






<style lang="scss">
.el-upload{
  .el-upload-dragger{
    background-color: rgb(13, 57, 128);
    .el-upload__text{
      color: white;
    }
  }
  .el-upload-dragger:hover{
    box-shadow: 5px 5px 15px #0f64c5ad;
    border: 1px solid #0f64c5ad;
  }
}
</style>
接下來(lái)是js內(nèi)容,其中我們要引入一個(gè)ImportExcel工具文件,文件在本部分的下面

<script>
import { importEx } from '@/libs/ImportExcel'
export default {
  name: "uploadEx",
  props: ["isShow","excelTitle","urlStr"],
  data() {
    return {
      fileTemp: undefined,
      excelShow: false,
      excelData: [],
      fileListUpload: [],
    };
  },
  mounted() {
  },
  methods: {
    // 判斷文件格式
    handleChange(file, fileList) {
      this.fileTemp = file.raw
      let fileName = file.raw.name
      let fileType = fileName.substring(fileName.lastIndexOf('.') + 1);
      if (this.fileTemp) {
        if ((fileType == 'xlsx') || (fileType == 'xls')) {
          this.importf(this.fileTemp)
        } else {
          this.handleRemove()
          this.$message({
            type: 'warning',
            message: '文件格式錯(cuò)誤'
          })
        }
      }
    },
    // 移除Excel表
    handleRemove() {
      this.fileTemp = null
      this.fileListUpload = []
    },
    // 關(guān)閉導(dǎo)入框
    importClose(){
      this.handleRemove()
      this.$emit('update:isShow', false)  
    },
    // 導(dǎo)入數(shù)據(jù)并傳遞給表格顯示
    importf(obj){
      var self = this
      let arr = []
      importEx(this.excelTitle, obj).then(arr => {
        if (arr.length==0){
          self.$message({message: '沒(méi)有數(shù)據(jù)哦',type: 'error',duration: 1500})
          self.handleRemove()
          return
        }
        // 可以對(duì)空字符數(shù)據(jù)進(jìn)行處理,例如某個(gè)接口要導(dǎo)入的信息有男女字段,將男女改為0,1
        // 這個(gè)只是針對(duì)/api/excel/import/userinf這個(gè)邏輯中的文件進(jìn)行字段轉(zhuǎn)換,可以加else if來(lái)替換其他文件的特殊字段,當(dāng)然也可以注釋掉,那么久需要在后端進(jìn)行轉(zhuǎn)換了
        if (this.urlStr==='/api/excel/import/userinfo'){
          for (var ar in arr){
            if (arr[ar]['userSex']=='男'){
              arr[ar]['userSex'] = 0
            } else if (arr[ar]['userSex']=='女'){
              arr[ar]['userSex'] = 1
            }
          }
        }
        self.excelData = [...arr]
        self.excelShow = true
      })
    },
    // 將數(shù)據(jù)傳給后臺(tái)添加
    importExcel(){
      console.log(this.excelData)
      let self = this
      this.$http
        .request({
        url: this.urlStr,
        method: 'POST',
        data: this.excelData
      }).then(resp => {
        // 數(shù)據(jù)添加成功或失敗后清空內(nèi)容
        if (resp && resp.status === 100) {
          self.$message({message: '成功',type: 'success',duration: 1500})
          self.importClose()
          self.$parent.queryMainData()
        }else{
          self.handleRemove()
          self.$message({message: resp.message, type: 'error',duration: 1500})
        }
      })
      this.excelShow = false
    },
  },
  };
  </script>

4.Excel讀取

這個(gè)文件中利用了xlsx來(lái)讀取內(nèi)容并轉(zhuǎn)為json,當(dāng)然這個(gè)js文件網(wǎng)上有很多種寫(xiě)法,總之結(jié)果可正常轉(zhuǎn)換為json就可以了,最重要的是獲取鍵與值那部分代碼

export function importEx(excelTitle, fileobj) {
  return new Promise((resolve, reject) => {
    var rABS = false; //是否將文件讀取為二進(jìn)制字符串
    var f = fileobj
    var reader = new FileReader();
    FileReader.prototype.readAsBinaryString = function (f) {
      var binary = "";
      var rABS = false; //是否將文件讀取為二進(jìn)制字符串
      var wb; //讀取完成的數(shù)據(jù)
      var outdata;
      var reader = new FileReader();
      reader.onload = function (e) {
        var bytes = new Uint8Array(reader.result);
        var length = bytes.byteLength;
        for (var i = 0; i < length; i++) {
          binary += String.fromCharCode(bytes[i]);
        }
        var XLSX = require('xlsx');
        if (rABS) {
          wb = XLSX.read(btoa(fixdata(binary)), { //手動(dòng)轉(zhuǎn)化
            type: 'base64'
          });
        } else {
          wb = XLSX.read(binary, {
            type: 'binary'
          });
        }
        // outdata => excel導(dǎo)入的數(shù)據(jù)
        outdata = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
        let arr = []
        outdata.map(v => {
          // let jsonString = JSON.stringify(v).replace(/\*/g, '').replace(/\s/ig,'');
          let jsonString = JSON.stringify(v).replace(/\//g, '');
          v = JSON.parse(jsonString);
          let obj = {}
          // 自動(dòng)獲取鍵與值
          for (var k1 in v){
            for (var et in excelTitle){
              if (excelTitle[et].label==k1){
                var col_key = excelTitle[et].prop
                var col_val = v[k1]
                obj[col_key] = col_val
              }
            }
          }
          arr.push(obj)
        })
        resolve(arr);
      }
      reader.readAsArrayBuffer(f);
    }
    if (rABS) {
      reader.readAsArrayBuffer(f);
    } else {
      reader.readAsBinaryString(f);
    }
    reader.onerror = reject;
  })
}
然后,后端代碼就不用展示了,你就懟個(gè)對(duì)應(yīng)的實(shí)體類(lèi)隨便接受吧

總結(jié)

然后在需要進(jìn)行導(dǎo)入操作的頁(yè)面使用UploadEx組件,并且設(shè)置兩個(gè)屬性和一個(gè)方法,基本就可以完成操作了。

當(dāng)然有好處也有壞處,不同的xlsx文件處理需要進(jìn)行不同的設(shè)置,但是對(duì)于用戶(hù)來(lái)說(shuō)展示很友好,而且方便定義數(shù)據(jù)列名,但是對(duì)于一個(gè)文件幾十個(gè)列,那就當(dāng)我沒(méi)說(shuō)吧唉。大家可以對(duì)其自行擴(kuò)展哦!

作者:小碼哥


歡迎關(guān)注微信公眾號(hào) :碼出宇宙

掃描添加好友邀你進(jìn)技術(shù)交流群,加我時(shí)注明【姓名+公司(學(xué)校)+職位】