插件
npm i xlsx --save
项目中 src/components/UploadExcel
<script>
import XLSX from 'xlsx'
export default {
props: {
beforeUpload: Function, // eslint-disable-line
onSuccess: Function// eslint-disable-line
}
}
</script>
导入:
导入excel代码
<template>
<upload-excel :on-success="handleSuccess" />
</template>
<script>
export default {
name: 'Import',
methods: {
handleSuccess({ header, results }) {
console.log(header, results)
}
}
}
</script>
- 导入组件支持俩个关键的prop传入 before-upload:导入之前做校验 可以校验excel文件体积 也可以校验excel表格是否满足文件规范 on-success:插件已经把excel表格转换成了有用的数据 表头数据和表格数据 (
{results, header} )- excel导入插件本质:把excel经过分析转换成js能够识别的常规数据,拿到数据我们可以进行任何操作
- 表格数据格式为对象数组 表头数据格式为由excel表头组成的新数组
const table = { '入职日期': 43535, '姓名': "张飞12", '工号': 88088, '手机号': 15751786457, '转正日期': 43719 } const header = ["手机号", "姓名", "入职日期", "转正日期", "工号"]
常见问题:
调用接口进行excel的重点其实是数据的处理,我们需要按照接口的要求,把excel表格中经过插件处理好的数据处理成后端接口要求的格式,主要包括俩方面
- 接口字段的key需要从中文转成英文
- 涉及到时间的字段需要进行严格的时间格式化处理
- 手机号要求不能出现重复
transData(results) {
const userRelations = {
'入职日期': 'timeOfEntry',
'手机号': 'mobile',
'姓名': 'username',
'转正日期': 'correctionTime',
'工号': 'workNumber'
}
const newArr = []
// 将所有的中文key转换成英文key 然后添加到新数组中
results.forEach(item => {
const map = {}
Object.keys(item).forEach(key => {
map[userRelations[key]] = item[key]
})
// 所有key处理完毕之后才能完成提交
newArr.push(map)
})
// 在这个位置拿到的newArr已经是处理成英文的状态了
// 时间处理
newArr.forEach(item => {
Object.keys(item).forEach(key => {
if (['correctionTime', 'timeOfEntry'].includes(key)) {
// 需要对key对应的value做时间处理
// 严格来讲需要使用与excel插件配套的时间处理函数 处理成标准的时间Date格式
// 后端接口才能识别
item[key] = new Date(formatDate(item[key], '/'))
}
})
})
return newArr
}
导出:
- 插件包位于src/vendor/export2Excel中,采用的是按需引入的方式
什么时候正式要使用导出功能了,插件才会被正式引入到应用里- Export2Excel依赖的包有js-xlsx、file-saver和script-loader
npm install file-saver script-loader --save
- 将vender文件夹复制到我们自己的项目里
exportEmployee() {
// 按需引入
// 表现:只有当点击行为发生 也就是import语法实际执行的时候 才会引入里面配置的包
// 基础原理:动态创建一个script标签 然后通过src动态引入我们的js资源
// 依赖的包:script-loader
// 好处:减小生产包的体积 经常在引入比较大的包并且使用频率不太高的场景
import('@/vendor/Export2Excel').then(async excel => {
// 1.准备表头数据
const header = {
'手机号': 'mobile',
'姓名': 'username',
'入职日期': 'timeOfEntry',
'聘用形式': 'formOfEmployment',
'转正日期': 'correctionTime',
'工号': 'workNumber',
'部门': 'departmentName'
}
const tHeader = Object.keys(header)
// 2.准备表格数据 (从数组库拉取当前页的最新的数据完成导出)
const res = await getEmployeeList(this.params)
const { rows } = res // 解构出来需要的表格数据
function transData(sourceData) {
const newArr = [] // 要求newArr是一个有数组组成二维数组
// 具体的转换逻辑
sourceData.forEach(item => {
const arr = []
Object.keys(item).forEach(key => {
// 增加一些判断处理 通过表头中拥有的字段名称去筛选添加
if (Object.values(header).includes(key)) {
arr.push(item[key])
}
})
newArr.push(arr)
})
return newArr
}
excel.export_json_to_excel({
header: tHeader, // 表头数据
data: transData(rows), // 表格数据 (二维数组)
filename: '员工列表',
autoWidth: true,
bookType: 'xlsx' // 生成的文件类型
})
})
},
总结:
- 实现的技术方案选择
- 前端主导方案 (后端只提供基础数据 前端完成数据转化)
- 后端主导 (前端只需要调用接口 excel解析逻辑都由后端来完成)
导入:类比为一个简单的文件上传 后端发现是excel格式文件会做文件数据转换,入库
导出:调用接口告诉后端要哪一页的数据 后端拿到参数去数据库匹配数据,然后把数据转化成excel格式,作为response返给前端,前端需要定义好数据通信的格式(blob),浏览器发现接口返回的是可以被下载的数据格式会自动触发下载机制进行文件下载
- 前端主导方案里插件做的事儿
xslx : 核心插件
导入:将本地的excel文件转化成js能认识的数据格式,并且产出俩个核心数据,一个叫做表头,是一个数组,一个叫做表格数据,也是一个数组
导出:插件将后端返回的数据转换成可以触发浏览器下载行为的流数据 - 前端和后端算力的问题
如果需要导出的数据量很大,直接采用后端方案