目录

vue3导入excel并解析excel数据渲染到表格中,纯前端实现

vue3导入excel并解析excel数据渲染到表格中,纯前端实现。

需求

用户将已有的excel上传到系统,并将excel数据同步到页面的表格中进行二次编辑,由于excel数据不是最终数据,只是批量的一个初始模板,后端不需要存储,所以该功能由前端独立完成。

吐槽

系统中文件上传下载预览三部曲走了一遍,万万没想到还要自己实现同步数据。

实际

反手各种资料开始查阅,终于找到了可以完美实现该需求的方法,来记录下我的实现方案。希望对有需要的小伙伴有帮助。

注意以下为正文(重要内容),好好阅读,不要漏掉重要知识点奥~


涉及到的主要知识点

  • 插件xlsx
  • elementUI  plus中的Upload 上传组件
  • 动态设置 ref

展开说说:

1、插件xlsx

// 在项目根路径 安装xlsx
npm install -S xlsx

// 在需要使用的页面引入 xlsx
import * as xlsx from 'xlsx'

2、upload 上传组件

上传组件的自动上传方法,传参方法,详细可翻阅

3、动态设置 ref

涉及到动态设置 ref 的原因:

一是由于 upload 组件在设置了 :limit=“1”,在上传第一个文件之后,浏览器会保存着我们已经上传的文件,导致我们继续上传文件的时候,页面没有反应;解决该问题需要在 on-success 钩子函数中通过 ref 来清除已经上传的文件。

<template>
<div>
<el-upload
ref="importExcelRef"
:action="VITE*APP_API_URL"
:limit="1"
:show-file-list="false"
class="uploadExcelContent"
:on-success="importSuccess"  
 >
<div title="导入 excel">
<div class="importExcel"></div>
</div>
</el-upload>
</div>
</template>
<script setup>
import { ref } from 'vue'
const importExcelRef = ref(null)
const importSuccess = ()=>{
importExcelRef.value.clearFiles();
}
</script>

二是因为表单中存在多个表格需要导入 excel 作为基础数据进行编辑,且表格数量不固定,是根据后端数据渲染的,所以在清空上传文件的时候,需要处理未知的多个,所以需要动态设置 ref。

<template>
<div>
<el-upload :ref="(el) => handleSetUploadRefMap(el, rowIndex,compIndex)">
<div title="导入 excel" >
<div class="importExcel"></div>
</div>
</el-upload>
</div>
</template>
<script>
import { ref } from 'vue'
const uploadRefMap = ref({});
// 动态设置 upload Ref
const handleSetUploadRefMap = (el,rowIndex,compIndex) => {
if (el) {
uploadRefMap.value[`Upload_Ref*${rowIndex}_${compIndex}`] = el
}
}
</script>

需求实现代码

<template>
<div>
<!-- 上传 excel -->
<el-upload
:ref="(el) => handleSetUploadRefMap(el)"
action=""
:http-request="httpExcelRequest"
:limit="1"
:show-file-list="false"
class="uploadExcelContent"
:data={}
>
<div title="导入 excel" style="cursor: pointer;" >
<div>导入 excel</div>
</div>
</el-upload>

      <!-- 列表 -->
      <div class="excel-content"  v-for="(rowItem,rowIndex) in excelList" :key="rowIndex">
        <div class="comp" v-for="(comp,compIndex) in rowItem" :key="compIndex">{{comp}}</div>
      </div>
    </div>

</template>

<script setup name="mainContent">
import * as xlsx from 'xlsx'
import {ElMessage} from 'element-plus'
import { ref } from 'vue'
const uploadRefMap = ref({});
const excelList = ref([])

// 动态设置 upload Ref
const handleSetUploadRefMap = (el) => {
if (el) {
uploadRefMap.value[`Upload_Ref`] = el
}
}

// 文件上传自定义
const httpExcelRequest = async (op) => {
// 获取除文件之外的参数,具体根据实际业务需求来
console.log(op.data)
// 获取上传的 excel 并解析数据
let file = op.file
let dataBinary = await readFile(file);
let workBook = xlsx.read(dataBinary, { type: "binary", cellDates: true })
let workSheet = workBook.Sheets[workBook.SheetNames[0]]
const excelData = xlsx.utils.sheet_to_json(workSheet,{ header: 1 })
excelList.value = excelData
console.log(excelData)
if(uploadRefMap.value[`Upload_Ref`]){
uploadRefMap.value[`Upload_Ref`].clearFiles();
}
}

const readFile = (file) => {
return new Promise((resolve) => {
let reader = new FileReader()
reader.readAsBinaryString(file)
reader.onload = (ev) => {
resolve(ev.target?.result)
}
})
}

</script>

<style lang="scss" scoped>
.uploadExcelContent{
display: flex;
flex-direction: row;
}
.excel-content{
display: flex;
flex-direction: row;
align-items: center;
.comp{
width: 200px;
font-size: 12px;
}
}
</style>

由于业务需求不同,对表格数据的详细处理逻辑,就不在这里显示了,可根据自己的数据结构进行赋值操作,运行 demo 后可以直接在控制台查看拿到的 excel 数据。

今天就到这里了,会继续加油的,是亮晶晶的芋头哟~