vue導(dǎo)入excel文件,vue導(dǎo)入多個(gè)sheets的方式
用input 導(dǎo)入 excel ,然后生成表格,然后調(diào)用接口上傳到后臺(tái)
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: [], // 上傳給后臺(tái)的數(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)), { //手動(dòng)轉(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 '身份證號(hào)':
console.log('這是身份證號(hào)',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 = []
// 這里是一個(gè)excel里面會(huì)有多個(gè)sheets,把里面的惡數(shù)據(jù)整個(gè)到這個(gè)數(shù)組里面一起上傳
let leng = Object.keys(wb.Sheets).length
// 用for循環(huán),leng 是sheets的個(gè)數(shù),用來(lái)循環(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: '請(qǐng)耐心等待導(dǎo)入成功',
type: 'success'
});
}
reader.readAsArrayBuffer(f);
}
if (rABS) {
reader.readAsArrayBuffer(f);
} else {
reader.readAsBinaryString(f);
}
},4.確認(rèn)導(dǎo)入
(其實(shí)這里就是上傳到后臺(tái)接口的,存到數(shù)據(jù)庫(kù)里面才能保存)
// 確認(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 就是后臺(tái)需要的參數(shù),用變量表示鍵名 [""+此處是你的變量+""]
createUser(obj).then((res) => {
這是后臺(tái)添加的方法
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ī)會(huì)剛好研究一下vue導(dǎo)入并處理excel數(shù)據(jù);當(dāng)然自己手?jǐn)]一個(gè)工具沒有那么多時(shí)間,本文只是借助現(xiàn)有的工具來(lái)做一下工具使用總結(jié)。
1.vue導(dǎo)入Excel表格
vue導(dǎo)入Excel表格主要有兩種常用的方法,一個(gè)是借助ElementUI文件上傳進(jìn)行表格導(dǎo)入,另一個(gè)是自帶的input做文件上傳;以下對(duì)兩個(gè)方法做詳細(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)入成功時(shí)執(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 = [];
// 取對(duì)應(yīng)表生成json表格內(nèi)容
workbook.SheetNames.forEach(item => {
this.tableData.push(utils.sheet_to_json(workbook.Sheets[item]));
});
// 該算法僅針對(duì)表頭無(wú)合并的情況
if (this.tableData.length > 0) {
// 獲取excel中第一個(gè)表格數(shù)據(jù)tableData[0][0],并且將表頭提取出來(lái)
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ù)我這邊用組件展示在了頁(yè)面上,效果如下圖:

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 = [];
// 取對(duì)應(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]));
});
// 該算法僅針對(duì)表頭無(wú)合并的情況
if (this.tableData.length > 0) {
// 獲取excel中第一個(gè)表格數(shù)據(jù)tableData[0][0],并且將表頭提取出來(lái)
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" ? ? ? ? ? >點(diǎn)擊上傳</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 = [];
? ? ? ? ? // 取對(duì)應(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]));
? ? ? ? ? });
? ? ? ? ? // 該算法僅針對(duì)表頭無(wú)合并的情況
? ? ? ? ? if (this.tableData.length > 0) {
? ? ? ? ? ? // 獲取excel中第一個(gè)表格數(shù)據(jù)tableData[0][0],并且將表頭提取出來(lái)
? ? ? ? ? ? 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 = [];
? ? ? ? ? // 取對(duì)應(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]));
? ? ? ? ? });
? ? ? ? ? // 該算法僅針對(duì)表頭無(wú)合并的情況
? ? ? ? ? if (this.tableData.length > 0) {
? ? ? ? ? ? // 獲取excel中第一個(gè)表格數(shù)據(jù)tableData[0][0],并且將表頭提取出來(lái)
? ? ? ? ? ? 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é):較為容易踩坑的點(diǎn)就是xlsx這個(gè)包的導(dǎo)入方式,這個(gè)包處理excel表格功能時(shí)相當(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)有組件往往能獲得更好的效果,所以這里還是推薦大家使用方法一去實(shí)現(xiàn)這個(gè)功能。
最后本文僅對(duì)數(shù)據(jù)做簡(jiǎn)單處理,若要處理更為復(fù)雜的表格數(shù)據(jù),就需要研究更強(qiáng)大的算法,不喜勿碰。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue父組件向子組件傳遞多個(gè)數(shù)據(jù)的實(shí)例
下面小編就為大家分享一篇vue父組件向子組件傳遞多個(gè)數(shù)據(jù)的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2018-03-03
element-ui動(dòng)態(tài)添加表單項(xiàng)并實(shí)現(xiàn)事件觸發(fā)驗(yàn)證代碼示例
這篇文章主要給大家介紹了關(guān)于element-ui動(dòng)態(tài)添加表單項(xiàng)并實(shí)現(xiàn)事件觸發(fā)驗(yàn)證的相關(guān)資料,其實(shí)就是利用了vue的v-for循環(huán)渲染,通過添加數(shù)組實(shí)現(xiàn)動(dòng)態(tài)添加表單項(xiàng),需要的朋友可以參考下2023-12-12
vue單個(gè)元素綁定多個(gè)事件問題(例如點(diǎn)擊綁定多個(gè)事件方法)
這篇文章主要介紹了vue單個(gè)元素綁定多個(gè)事件問題(例如點(diǎn)擊綁定多個(gè)事件方法),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04

