需求:前端需要增加一个导入按钮,导入既定的Excel模板数据,
后端接口请求方法:post
参数格式:Form Data

const param = {
	name: 'zhangsan',
	code: '001',
	id: 'A001',
	file: excelData // 后端需要的二进制流
}

分析:既然是Excel的导入或者导出首先我们就要安装 excel 的插件 xlsx

  1. 首先全局安装xlsx插件
npm install xlsx --save
  1. 前端代码:我们还是使用 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 数据就填充到表格中了

}