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上传组件

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

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数据。

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

相关推荐
gihigo199810 分钟前
基于MATLAB的Excel文件批量读取与循环处理
matlab·excel
码事漫谈19 分钟前
解决 Anki 启动器下载错误的完整指南
前端
im_AMBER39 分钟前
Web 开发 27
前端·javascript·笔记·后端·学习·web
蓝胖子的多啦A梦1 小时前
低版本Chrome导致弹框无法滚动的解决方案
前端·css·html·chrome浏览器·版本不同造成问题·弹框页面无法滚动
玩代码1 小时前
vue项目安装chromedriver超时解决办法
前端·javascript·vue.js
訾博ZiBo1 小时前
React 状态管理中的循环更新陷阱与解决方案
前端
StarPrayers.2 小时前
旅行商问题(TSP)(2)(heuristics.py)(TSP 的两种贪心启发式算法实现)
前端·人工智能·python·算法·pycharm·启发式算法
一壶浊酒..2 小时前
ajax局部更新
前端·ajax·okhttp
DoraBigHead3 小时前
React 架构重生记:从递归地狱到时间切片
前端·javascript·react.js
彩旗工作室4 小时前
WordPress 本地开发环境完全指南:从零开始理解 Local by Flywhee
前端·wordpress·网站