您当前的位置:易学堂 > 日志记录

vue使用ElementUI中的upload组件导入处理Excel表格详解

时间:2022-05-31 09:52:58

1. 前言

最近遇到前端导入并处理excel表格的情况,趁此机会刚好研究一下vue导入并处理excel数据;当然自己手撸一个工具没有那么多时间,本文只是借助现有的工具来做一下工具使用总结。


2.vue导入Excel表格

vue导入Excel表格主要有两种常用的方法,一个是借助ElementUI文件上传进行表格导入,另一个是自带的input做文件上传;以下对两个方法做详细介绍;


2.1 使用ElementUI中的upload组件

  1. 安装ElementUI
npm i element-ui -S 
  1. 安装Excel表格解析插件
npm i xlsx -S 
  1. 导入需要用的工具包
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); 
  1. 引入组件
<el-upload
action="https://jsonplaceholder.typicode.com/posts/"
:on-success="handleChange"
:file-list="fileList"
class="el-upload"
> 
  1. 添加处理逻辑
// 导入成功时执行
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 
  1. 导入需要用的工具包
import { read, utils } from "xlsx"; // 注意处理方法引入方式 
  1. 使用input
<div class="flex-display">
<div class="left-box">文件上传(input):</div>
<input type="file" v-on:change="onChange" class="file-ipt" />
</div> 
  1. 添加处理逻辑 基本与上面处理逻辑相同
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