时间:2021-12-27 11:16:27 | 栏目:vue | 点击:次
最近在整理日常开发中长涉及到的业务需求,正好想到了excel的解析与上传方面的事情,在开发中还是比较常见的,趁着周末做一下整理学习吧
主要基于Vue+element实现文件的解析与导出,用的的插件是 xlsx,里面的具体方法,感兴趣的去研究一下,基本的样式,配置就不赘述了,也比较简单,我们直接上主食
用户点击文件上传,将excel的表格已json的格式显示在页面中,用户进行操作,检查数据后对服务进行提交,上传操作用的的element中的upload组件
<!-- 上传文件按钮 --> <div class="buttonBox"> <el-upload action accept=".xlsx, .xls" :auto-upload="false" :show-file-list="false" :on-change="handle" > <el-button type="primary" slot="trigger">选取EXCEL文件</el-button> </el-upload> <el-button type="success" @click="submit" :disabled="disable">采集数据提交</el-button> </div> <!-- 解析出来的数据 --> <div class="tableBox" v-show="show"> <h3> <i class="el-icon-info"></i> 小主,以下是采集完成的数据,请您检查无误后,点击“采集数据提交”按钮上传至服务器哦! </h3> <el-table :data="tempData" style="width: 100%" :height="height" border> <el-table-column prop="name" label="姓名" min-width="50%"></el-table-column> <el-table-column prop="phone" label="电话" min-width="50%"></el-table-column> </el-table> </div>
通过upload组件可以获取上传的文件流(下图)
将文件流转为二进制,这里我们可以在utils文件中增加对应的方法(如下)
// 把文件按照二进制进行读取 export function readFile(file) { return new Promise(resolve => { let reader = new FileReader(); reader.readAsBinaryString(file); reader.onload = ev => { resolve(ev.target.result); }; }); }
通过xlsx将二进制六转为json,这样才能显示
//读取FILE中的数据(变为JSON格式) let data = await readFile(file); let workbook = xlsx.read(data, { type: "binary" }), worksheet = workbook.Sheets[workbook.SheetNames[0]]; data = xlsx.utils.sheet_to_json(worksheet); // 打印结果加下图 console.log(workbook);
把读取出来的数据变为最后可以传递给服务器的数据,我们需要先封装一个映射表来对应传给后端的格式(如下)
// 字段对应表 export let character = { name: { text: "姓名", type: 'string' }, phone: { text: "电话", type: 'string' } };
转换数据格式
let arr = []; data.forEach(item => { let obj = {}; for (let key in character) { if (!character.hasOwnProperty(key)) break; let v = character[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); });
发送给服务器
这里要看服务器支持多条文件一起发送,如果不支持我们前端就可以采用递归逐条发送的方式进行发送,具体情况可以与后端进行沟通,我们这采用递归的方式进行传输
// 提交数据给服务器 async submit() { if (this.tempData.length <= 0) { this.$message({ message: "小主,请您先选择EXCEL文件!", type: "warning", showClose: true }); return; } this.disable = true; let loadingInstance = Loading.service({ text: "小主,请您稍等片刻,奴家正在玩命处理中!", background: "rgba(0,0,0,.5)" }); // 完成后处理的事情 let complate = () => { this.$message({ message: "小主,奴家已经帮您把数据上传了!", type: "success", showClose: true }); this.show = false; this.disable = false; loadingInstance.close(); }; // 需要把数据一条条传递给服务器 let n = 0; let send = async () => { if (n > this.tempData.length - 1) { // 都传递完了 complate(); return; } let body = this.tempData[n]; // 走接口 let result = await createAPI(body); if (parseInt(result.code) === 0) { // 成功 n++; } send(); }; send(); }
以上就是对Excel文件的解析与上传的总结,其实并不是很难,都是日常开发常常涉及的业务,接下来一起看下Excel的导出吧
一进来页面获取刚刚上传的文件,然后显示在表格中,然后做个分页.......这些就不说了,我们直接从点击导出excel按钮开始,先看下页面结构
<div class="container"> <!-- 上传按钮 --> <div class="buttonBox"> <router-link to="/upload"> <el-tooltip content="EXCEL数据采集" placement="top"> <el-button type="primary" icon="el-icon-edit" circle></el-button> </el-tooltip> </router-link> </div> <!-- 搜索区域 --> <div class="searchBox"> <el-input v-model="search" placeholder="基于姓名、手机模糊搜索" @change="searchHandle"></el-input> <el-button type="success" @click="submit" :disabled="disabled">导出选中的数据</el-button> </div> <!-- 列表区域 --> <div class="tableBox"> <el-table :data="tableData" :height="height" style="width: 100%" v-loading="loading" element-loading-text="小主,奴家正在努力加载中..." @selection-change="selectionChange" > <el-table-column type="selection" width="50" align="center"></el-table-column> <el-table-column prop="id" label="编号" min-width="10%"></el-table-column> <el-table-column prop="name" label="姓名" min-width="20%"></el-table-column> <el-table-column prop="phone" label="电话" min-width="20%"></el-table-column> <el-table-column prop="time" label="创建时间" min-width="25%" :formatter="formatter"></el-table-column> </el-table> </div> <!-- 分页区域 --> <div class="pageBox"> <el-pagination background hide-on-single-page layout="total, sizes, prev, pager, next" :page-size="pageSize" :current-page="page" :total="total" @size-change="sizeChange" @current-change="prevNext" @prev-click="prevNext" @next-click="prevNext" ></el-pagination> </div> </div>
将json数据变为sheet数据,新建表格,在表格中插入一个sheet,通过xlsx的writeFile方法将文件写入
// 导出数据 submit() { if (this.selectionList.length <= 0) { this.$message({ message: "小主,请您先选择要导出的数据哦!", type: "warning", showClose: true }); return; } this.disabled = true; let loadingInstance = Loading.service({ text: "小主,请您稍等片刻,奴家正在玩命处理中...", background: "rgba(0,0,0,.5)" }); let arr = this.selectionList.map(item => { return { 编号: item.id, 姓名: item.name, 电话: item.phone }; }); // 将json数据变为sheet数据 let sheet = xslx.utils.json_to_sheet(arr), // 新建表格 book = xslx.utils.book_new(); // 在表格中插入一个sheet xslx.utils.book_append_sheet(book, sheet, "sheet1"); // 通过xlsx的writeFile方法将文件写入 xslx.writeFile(book, `user${new Date().getTime()}.xls`); loadingInstance.close(); this.disabled = false; }
**以上是对Excele的相关操作,文件上传解析是常见的需求,如果前端小伙伴们对大文件上传以及断电续传感兴趣的可以参考一下我的这篇文章大文件上传与断点续传