vue導(dǎo)入excel文件,vue導(dǎo)入多個sheets的方式
用input 導(dǎo)入 excel ,然后生成表格,然后調(diào)用接口上傳到后臺
html 導(dǎo)入按鈕和選擇文件的彈框
<el-button v-waves :loading='downloadLoading' class='filter-item' type='primary' icon='el-icon-download' @click='daoru'> 導(dǎo)入 </el-button> <el-dialog title="導(dǎo)入文件" :visible.sync="excelImportShow"> <a href="javascript:;" rel="external nofollow" class="file"> <input id="upload" type="file" @change="importfxx(this)" accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" /> </a> <div id="demo"></div> <div slot="footer" class="dialog-footer"> <el-button @click.native="excelImportShow = false">取消</el-button> <el-button type="primary" @click.native="submit">提交</el-button> </div> </el-dialog>
js 重中之重 導(dǎo)入 excel 開始啦
1.data里面的數(shù)據(jù)
excelImportShow: false, //導(dǎo)入文件的彈框 uploadArr: [], // 上傳給后臺的數(shù)據(jù) realname: '', // 以下都是我要轉(zhuǎn)換的數(shù)據(jù),因人而異 gender: '', age: '', minzu: '', wenhua: '', shengfenzheng: '', job: '', mobile: '', mark: ''
2. 導(dǎo)入彈框
daoru() { this.excelImportShow = true },
3. 導(dǎo)入方法
// 導(dǎo)入 importfxx(obj) { let _this = this; let inputDOM = this.$refs.inputer; // 通過DOM取文件數(shù)據(jù) this.file = event.currentTarget.files[0]; var rABS = false; //是否將文件讀取為二進(jìn)制字符串 var f = this.file; var reader = new FileReader(); FileReader.prototype.readAsBinaryString = function(f) { var binary = ""; var rABS = false; //是否將文件讀取為二進(jìn)制字符串 var pt = this; 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)), { //手動轉(zhuǎn)化 type: 'base64' }); } else { wb = XLSX.read(binary, { type: 'binary' }); } outdata = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]); //outdata就是你想要的東西 this.da = [...outdata] let arr = [] let nameArr = outdata[1] for (let v in nameArr) { // 拿到 excel 里面的列名,根據(jù)列名得到里面的鍵名 let title = nameArr[v] switch (title){ case '姓名': console.log('這是姓名',nameArr[v]); _this.realname = v console.log('這是realname',v); break; case '性別': console.log('這是性別',nameArr[v]); _this.gender = v console.log('這是gender',v); break; case '年齡': console.log('這是年齡',nameArr[v]); _this.age = v console.log('這是age',v); break; case '民族': console.log('這是民族',nameArr[v]); _this.minzu = v console.log('這是minzu',v); break; case '學(xué)歷': console.log('這是性別',nameArr[v]); _this.wenhua = v console.log('這是job',v); break; case '身份證號': console.log('這是身份證號',nameArr[v]); _this.shengfenzheng = v console.log('這是shenfengzheng',v); break; case '工作單位/學(xué)校/社區(qū)': console.log('"工作單位/學(xué)校/社區(qū)"',nameArr[v]); _this.job = v console.log('這是job',v); break; case '手機(jī)/電話': console.log('這是手機(jī)/電話',nameArr[v]); _this.mobile = v console.log('這是mobile',v); break; case '備注': console.log('這是備注',nameArr[v]); _this.mark = v console.log('這是mark',v); break; default: break; } } let obj let uploadArr = [] // 這里是一個excel里面會有多個sheets,把里面的惡數(shù)據(jù)整個到這個數(shù)組里面一起上傳 let leng = Object.keys(wb.Sheets).length // 用for循環(huán),leng 是sheets的個數(shù),用來循環(huán)次數(shù) for (var i = 0; i < leng+1; i++) { XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[i]]) let arrr = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[i]]) arrr = arrr.slice(2) //如果從第三行開始是數(shù)據(jù),那這里就是1,如果從第四行開始是數(shù)據(jù),那這里就是2 uploadArr.push.apply(uploadArr,arrr) _this.uploadArr = uploadArr } this.da.map(v => { let obj = {} obj.id = v.id obj.status = v.status arr.push(obj) }) let para = { withList: arr } _this.$message({ message: '請耐心等待導(dǎo)入成功', type: 'success' }); } reader.readAsArrayBuffer(f); } if (rABS) { reader.readAsArrayBuffer(f); } else { reader.readAsBinaryString(f); } },
4.確認(rèn)導(dǎo)入
(其實這里就是上傳到后臺接口的,存到數(shù)據(jù)庫里面才能保存)
// 確認(rèn)導(dǎo)入 submit() { let uploadArr = this.uploadArr this.excelImportShow = false let obj for (let v in uploadArr) { obj = {realname:uploadArr[v][""+this.realname+""], age:uploadArr[v][""+this.age+""], gender: uploadArr[v][""+this.gender+""]=='男'?'MALE':'FEMALE', minzu: uploadArr[v][""+this.minzu+""], wenhua: uploadArr[v][""+this.wenhua+""], shengfenzheng: uploadArr[v][""+this.shengfenzheng+""], job: uploadArr[v][""+this.job+""], wenhua: uploadArr[v][""+this.wenhua+""], mobile:uploadArr[v][""+this.mobile+""], mark:uploadArr[v][""+this.mark+""], place: "00"} // 這里的obj 就是后臺需要的參數(shù),用變量表示鍵名 [""+此處是你的變量+""] createUser(obj).then((res) => { 這是后臺添加的方法 if (res.data.return_code === '200') { this.dialogFormVisible = false } else { this.$notify.error(res.data.return_msg) } }) if (parseInt(v) === parseInt(uploadArr.length)-1) { console.log(v+'和'+uploadArr.length); setTimeout(()=>{ this.$notify({ title: '成功', message: '創(chuàng)建成功', type: 'success', duration: 2000 }) this.getList({ page: 1,limit: 20 }) // 添加成功之后調(diào)用list 接口,展示所添加的數(shù)據(jù) },1500) } } },
vue導(dǎo)入處理excel表格
最近遇到前端導(dǎo)入并處理excel表格的情況,趁此機(jī)會剛好研究一下vue導(dǎo)入并處理excel數(shù)據(jù);當(dāng)然自己手?jǐn)]一個工具沒有那么多時間,本文只是借助現(xiàn)有的工具來做一下工具使用總結(jié)。
1.vue導(dǎo)入Excel表格
vue導(dǎo)入Excel表格主要有兩種常用的方法,一個是借助ElementUI文件上傳進(jìn)行表格導(dǎo)入,另一個是自帶的input做文件上傳;以下對兩個方法做詳細(xì)介紹;
1.1 使用ElementUI中的upload組件 安裝ElementUI
npm i element-ui -S
安裝Excel表格解析插件
npm i xlsx -S
導(dǎo)入需要用的工具包
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" >
添加處理邏輯
// 導(dǎo)入成功時執(zhí)行 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 = []; // 取對應(yīng)表生成json表格內(nèi)容 workbook.SheetNames.forEach(item => { this.tableData.push(utils.sheet_to_json(workbook.Sheets[item])); }); // 該算法僅針對表頭無合并的情況 if (this.tableData.length > 0) { // 獲取excel中第一個表格數(shù)據(jù)tableData[0][0],并且將表頭提取出來 for (const key in this.tableData[0][0]) { this.tableHead.push(key); } } // 重寫數(shù)據(jù) } catch (e) { console.log("error:" + e); return false; } }; fileReader.readAsBinaryString(file[0].raw); }
以上處理的數(shù)據(jù)我這邊用組件展示在了頁面上,效果如下圖:
1.2 使用input文件上傳 安裝Excel表格解析插件
npm i xlsx -S
導(dǎo)入需要用的工具包
import { read, utils } from "xlsx"; // 注意處理方法引入方式
使用input
<div class="flex-display"> <div class="left-box">文件上傳(input):</div> <input type="file" v-on:change="onChange" class="file-ipt" /> </div>
添加處理邏輯
基本與上面處理邏輯相同
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 = []; // 取對應(yīng)表生成json表格內(nèi)容 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中第一個表格數(shù)據(jù)tableData[0][0],并且將表頭提取出來 for (const key in this.tableData[0][0]) { this.tableHead.push(key); } } return params; // 重寫數(shù)據(jù) } catch (e) { console.log("error:" + e); return false; } }; fileReader.readAsBinaryString(file); }
2. 總體代碼與效果
效果如下:
總的樣式以及代碼如下:
<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: [] // 表數(shù)據(jù) ? ? }; ? }, ? 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 = []; ? ? ? ? ? // 取對應(yīng)表生成json表格內(nèi)容 ? ? ? ? ? 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中第一個表格數(shù)據(jù)tableData[0][0],并且將表頭提取出來 ? ? ? ? ? ? for (const key in this.tableData[0][0]) { ? ? ? ? ? ? ? this.tableHead.push(key); ? ? ? ? ? ? } ? ? ? ? ? } ? ? ? ? ? return params; ? ? ? ? ? // 重寫數(shù)據(jù) ? ? ? ? } 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 = []; ? ? ? ? ? // 取對應(yīng)表生成json表格內(nèi)容 ? ? ? ? ? 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中第一個表格數(shù)據(jù)tableData[0][0],并且將表頭提取出來 ? ? ? ? ? ? for (const key in this.tableData[0][0]) { ? ? ? ? ? ? ? this.tableHead.push(key); ? ? ? ? ? ? } ? ? ? ? ? } ? ? ? ? ? return params; ? ? ? ? ? // 重寫數(shù)據(jù) ? ? ? ? } 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>
總結(jié):較為容易踩坑的點就是xlsx這個包的導(dǎo)入方式,這個包處理excel表格功能時相當(dāng)強(qiáng)大的,除了導(dǎo)入與數(shù)據(jù)解析,還有導(dǎo)出為excel等功能,在我們?nèi)粘>W(wǎng)站開發(fā)中非常常用。其次容易踩坑的就是vue中事件的監(jiān)聽與處理方式,我們可以看到使用組件賀不使用組件區(qū)別還是比較大的,當(dāng)然使用現(xiàn)有組件往往能獲得更好的效果,所以這里還是推薦大家使用方法一去實現(xiàn)這個功能。
最后本文僅對數(shù)據(jù)做簡單處理,若要處理更為復(fù)雜的表格數(shù)據(jù),就需要研究更強(qiáng)大的算法,不喜勿碰。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
element-ui動態(tài)添加表單項并實現(xiàn)事件觸發(fā)驗證代碼示例
這篇文章主要給大家介紹了關(guān)于element-ui動態(tài)添加表單項并實現(xiàn)事件觸發(fā)驗證的相關(guān)資料,其實就是利用了vue的v-for循環(huán)渲染,通過添加數(shù)組實現(xiàn)動態(tài)添加表單項,需要的朋友可以參考下2023-12-12