背景
因我司需求,需要将导入的excel文件进行读取并填充到表格中。本应后端处理,但考虑数据量过大,因为导入的excel包含10个sheet,每个sheet又差不多包含4-30个字段,因此将这一操作放入前端来处理
效果
通过选择文件点击导入,将Excel中的内容填充到表格中
所用技术
vue,element-ul,xlsx插件,当然还有个会敲代码的你
开始
安装xlsx插件,官网地址
npm install xlsx
在main.js文件中引入xlsx
import XLSX from xlsx
新建一个组件名叫ExportImport.vue,如下
ExportImport.vue组件中代码
props中的headerTitle是表格头,后面有图, 主要逻辑在handle方法中,大概的思路是先将excel文件中的内容进行读取,再去拿到每个sheet的内容,通过与headerTitle中的数据进行匹配,最终实现表格的展示,小编语言表达不好,还请看代码,哈哈哈.
<template>
<div class="ExportImport">
<el-upload
action
accept=".xlsx, .xls"
:auto-upload="false"
:show-file-list="true"
:on-change="handleChange"
:on-remove="handleRemove"
:before-remove="beforeRemove"
:on-exceed="handleExceed"
:file-list="fileList"
>
<el-button>上传文件</el-button>
</el-upload>
<el-button type="primary" @click="handle">导入</el-button>
</div>
</template>
<script>
import * as XLSX from "xlsx/xlsx.mjs";
export default {
name: "ExportImport",
props: {
headerTitle: { type: Array, default: [] }
},
data() {
return {
fileList: [],
file: null
};
},
methods: {
readFile(file) {
//文件读取
return new Promise(resolve => {
let reader = new FileReader();
reader.readAsBinaryString(file); //以二进制的方式读取
reader.onload = ev => {
resolve(ev.target.result);
};
});
},
handleRemove(file, fileList) {
this.file = null;
},
handleExceed(files, fileList) {
if (fileList.length > 1) {
fileList.splice(0, 1);
this.$message.error("只能上传一个文件");
}
},
beforeRemove(file, fileList) {
return this.$confirm(`确定移除 ${file.name}?`);
},
handleChange(file, fileList) {
this.file = file;
if (fileList.length > 0) {
this.fileList = [fileList[fileList.length - 1]]; //这一步,是 展示最后一次选择文件
}
},
async handle() {
let file = this.file?.raw;
if (!this.file) {
console.log("文件打开失败");
return;
} else {
let data = await this.readFile(file);
let workbook = XLSX.read(data, { type: "binary" }); //解析二进制格式数据
let resultArr = [];
for (let i = 0; i < workbook.SheetNames.length; i++) {
let worksheet = workbook.Sheets[workbook.SheetNames[i]]; //获取第i个Sheet
let headerRow = this.headerTitle[i]; // 获取第i个Sheet的表格头参数
const sheet2JSONOpts = {
defval: "" // 给defval赋值为空的字符串
};
let sheetData = XLSX.utils.sheet_to_json(worksheet, sheet2JSONOpts); // 获取当期Sheet中数据
for (let tIdx = 0; tIdx < sheetData.length; tIdx++) {
for (let RowIdx = 0; RowIdx < headerRow.length; RowIdx++) {
let label = headerRow[RowIdx].dataIndex; // 传给服务端字段
let hTitleName = headerRow[RowIdx].title; // 表格中表头展示的名字
Object.keys(sheetData[tIdx]).forEach((key, item) => {
if (key.includes(hTitleName)) {
sheetData[tIdx][label] = sheetData[tIdx][key];
delete sheetData[tIdx][key];
}
});
}
}
resultArr.push(sheetData);
}
this.$emit("handelImportChange", resultArr);
}
}
}
};
</script>
<style lang="less" scoped>
.ExportImport {
display: flex;
align-items: center;
div {
display: flex;
align-items: center;
}
button:nth-child(2) {
margin-left: 24px;
}
}
</style>
columns.js中参数格式如下,columns中得数据用来设置表格中的表头,结构类似与el-table中el-table-column格式,如果不了解的话可以先去看看el-table,Element-ui官l
props中的headerTitle是表格头,后面有图, 主要逻辑在handle方法中,大概的思路是先将excel文件中的内容进行读取,再去拿到每个sheet的内容,通过与headerTitle中的数据进行匹配,最终实现表格的展示,小编语言表达不好,还请看代码,哈哈哈.
页面中引入
// 拿到导入的数据并赋值给表格
handelImportChange(params) {
console.log(params, "paramsparams");
this.data = params;
}