需求:前端需要增加一个导入按钮,导入既定的Excel模板数据,
后端接口请求方法:post
参数格式:Form Data
const param = {
name: 'zhangsan',
code: '001',
id: 'A001',
file: excelData // 后端需要的二进制流
}
分析:既然是Excel的导入或者导出首先我们就要安装 excel 的插件 xlsx
- 首先全局安装xlsx插件
npm install xlsx --save
- 前端代码:我们还是使用 element-ui 的 el-upload 组件,不过这个组件过于复杂和详细,它考虑的场景比较多,但是我们要删繁就简,只获取我们需要的东西即可。
<!--
1.action 必选参数,上传的地址,这里我们调用后端接口,所以不提供地址,但是得给不然会报错
2.show-file-list 这里不显示上传的文件列表,所以::show-file-list='false' 指定为false
3.accept 接受上传的文件类型 这里我指定为:.xlsx, .xls
4.on-change 文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用
5.auto-upload 是否在选取文件后立即进行上传,我们需要调接口,所以,指定为false
6.on-exceed 文件超出个数限制时的钩子 可限制文件的大小
-->
<el-upload
ref="upload"
action
accept=".xlsx, .xls"
:show-file-list='false'
:on-change="handleUpLoad"
:auto-upload="false">
<el-button slot="trigger" type="primary">导入Excel文件</el-button>
</el-upload>
import readFile from '@/utils/index' // 从工具函数中导入文件处理函数,注意此时readFile相当于一个对象
// 导入Excel
async handleUpLoad (ev) {
let file = ev.raw
if (!file) return
const extension = file.name.substring(file.name.lastIndexOf('.') + 1)
const fileType = ['xlsx', 'xls'].some(item => item === extension)
if (!fileType) {
this.$message('格式错误!请选择后缀是.xlsx, .xls 的文件')
return
}
let data = await readFile.readFile(file) // 这个数据就是后端需要的二进制数据流,传给后端即可
this.importExcelData(data) // 这里调用后端接口并传参
}
// 解析Excel数据为二进制数据流, 写入工具函数utils.js 中方便其他模块使用
const readFile = file => {
return new Promise(resolve => {
let reader = new FileReader()
reader.readAsBinaryString(file)
reader.onload = ev => {
resolve(ev.target.result)
}
})
}
// 导入
async importExcelData (importData) {
const param = {
name: '张三',
code: '123',
id: '111',
file: importData
}
let res = await api.importData(param)
if (res.data && res.data.code === 'T') {
this.$message('导入成功')
}
}
后续补充:以上为完整的调用后端接口导入Excel数据,二进制数据流是后端处理的,那么,如果,我们要将导入的excel 数据填充到表格内来展示,如何做到呢?
问题:Excel中有列头有值,我们怎么解析excel中的数据为 json 格式,然后塞到 tableData 中?
<template>
<el-table
:data="tableData"
style="width: 100%">
<el-table-column
prop="name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="studyCode"
label="学号"
width="180">
</el-table-column>
<el-table-column
prop="age"
label="年龄">
</el-table-column>
</el-table>
</template>
比如导入的excel 列头有姓名 学号 年龄 等字段,怎么解析这些列头字段呢?
同样的,我们在 utils.js 中定义一个列头对照对象:
import readFile from '@/utils/index'
import xlsx from 'XlSX'
// 定义key值对照对象
export let columns = {
name: {
text: '姓名',
type: 'string'
},
studyCode: {
text: '学号',
type: 'string'
},
age: {
text: '年龄',
type: 'string'
}
}
处理获取到的excel工作目录中的数据:
// 读取FILE 中的数据(处理为Json对象)
async handleUpLoad (ev) {
let data = await readFile(file)
let workbook = xlsx.read(data, {type: 'binary'}),
worksheet = workbook.Sheets[workbook.Sheets[0]] // 获取第一张工作表
// 此时的json 对象的key是汉字形式:{姓名:'张三', 年龄:'20'},后续要处理为{name: 'zhangsan', age: '20'}
data = xlsx.utils.sheet_to_json(worksheet)
// 把导入进来的数据转换为服务器可以处理的Json 格式(姓名:name 电话:phone)
let arr = []
data.forEach(item => {
let obj = {}
for (let key in columns) {
if (!columns.hasOwnProperty(key)) break; // 此语句排除对象的继承属性
let v = columns[key],
text = v.text,
type = v.type
v = item[text] || ''
type === 'string' ? (v = String(v)) : null
type === 'number' ? (v = Number(v)) : null
obj[key] = v
}
arr.push(obj)
})
// 然后赋值给tableData
this.tableData = arr // 至此,导入的Excel 数据就填充到表格中了
}