Appearance
以前读取Excel都是通过服务器端进行读取的,那是因为大多数用户的电脑配置普遍低,读取大批量数据的Excel可能会造成页面数据卡顿。在前后端分离的时代,我们不方便准确的估算读取数据后业务的进度状态,可以通过将Excel数据进行本地读取进行分批上传,从而估算业务处理时间以进度条的形式展现给用户。
shell
npm install xlsx --save
本地读取Excel通用组件封装
我这里结合ElementPlus框架实现,并做成了通用组件的形式,您可以直接复制到项目中,当作通用组件来使用。
vue
<template>
<el-upload class="upload" accept=".xlsx,.xls" :before-upload="upload" drag action="" :limit="1">
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">将文件拖拽到此处 <em>点击上传</em></div>
<template #tip>
<div class="el-upload__tip">
.xlsx/.xls <slot></slot>
</div>
</template>
</el-upload>
</template>
<script setup>
import { UploadFilled } from "@element-plus/icons-vue"
import { read, utils } from "xlsx"
import { ElMessage } from "element-plus"
const emits = defineEmits(["success"])
const props = defineProps({
// 标题与字段对应关系
relations: {
type: Object,
default: undefined,
required: false
}
})
const upload = (file) => {
const fileReader = new FileReader()
fileReader.onload = (ev) => {
try {
const data = ev.target.result
const workbook = read(data, {
type: "binary"
})
// 取第一张表
const wsname = workbook.SheetNames[0]
// 生成json表格内容
const ws = utils.sheet_to_json(workbook.Sheets[wsname])
if (props.relations) {
// 将标题替换为字段
emits("success", generateData(ws))
} else {
emits("success", ws)
}
} catch (e) {
ElMessage.error("Excel读取失败")
return false
}
}
fileReader.readAsBinaryString(file)
// 阻止ElUpload默认上传
return false
}
/**
* 筛选数据
*/
const generateData = results => {
const arr = []
results.forEach(item => {
const info = {}
Object.keys(item).forEach(key => {
info[props.relations[key]] = item[key]
})
arr.push(info)
})
return arr
}
</script>
<style lang="scss" scoped>
.upload {
max-width: 800px;
margin: 0 auto;
}
</style>
使用本地读取Excel通用组件
- relations是标题与字段对应关系,用户上传一般是使用中文标题进行区分的,但是我们向后端传递数据的字段一般是英文格式,因此需要满足其对应关系
- @success是回调方法,读取成功后会将数据返回
vue
<template>
<div>
<upload-excel v-loading="loading" :relations="relations" @success="parseExcelSuccess">
<el-button type="primary" link><a href="#">下载模板</a></el-button>
</upload-excel>
</div>
</template>
<script setup>
import UploadExcel from "@/components/UploadExcel/index.vue" // 存放上文通用组件的路径
const relations = {
用户名: "username",
密码: "password",
昵称: "nickName",
邮箱: "mailbox"
}
const parseExcelSuccess = async (mDataList) => {
console.log(mDataList) // mDataList是一个数组,就是读取的excel内容
}
</script>