Vue+Element-ui实现表格导出和导入

news/2024/11/8 23:03:11/

表格导出,填写数据,导入表格

  • 需求:表格导出,填写数据,导入数据
    • 表格文件存储在前端
    • 表格文件不存储

需求:表格导出,填写数据,导入数据

分析需求:
(1)关于表格导出
      在前端页面导出表格,有三种情况:①表格文件存储在后端,后端返给前端文件流,前端调用后端接口,下载文件;②表格文件存储在前端,前端下载文件;③表格文件不存储,前端根据tableData的某些字段导出相应表格。
(2)填写数据
      Excel里填写数据,便不再多说;
(3)导入数据
      读取Excel表格,得到所需的数据,可能需要进行数据处理,总之,导入数据是给后端交一个对象数组

表格文件存储在前端

如图,表格文件template.xlsx存储在public下的static文件夹下
在这里插入图片描述
页面布局和用户需填写的excel如下
在这里插入图片描述
注意: 涉及到金额的保留2位不是四舍五入,而是直接保留两位,其他去掉。如:200.098保留2位,得到的结果为200.09。因此,在导入数据时,需要对数值进行处理,处理办法如下:

num=Math.floor(num*100)/100

代码实现
1.template

<div class="buttons"><el-button type="primary" size="small"@click="DownloadTemplate">下载模板</el-button><el-uploadaction=""class="upload"accept=".xlsx,.xls":auto-upload="false":show-file-list="false":on-change="importData"><el-button type="primary" size="small">导入数据</el-button></el-upload></div><el-table:data="newData"style="width: 100%"><el-table-columnprop="name"label="姓名"width="180"/><el-table-columnprop="date"label="出生日期"/><el-table-columnprop="last"label="上月"/><el-table-columnprop="next"label="下月"/><el-table-columnprop="sum"label="合计"/></el-table></div>

2.js

import * as XLSX from 'xlsx'
//相当于一个字典对应关系
const tempObj = {姓名: 'name',出生日期: 'date',上月: 'last',下月: 'next'
}data () {return {newData: []}
},
methods: {// 点击按钮触发a下载文件DownloadTemplate () {let a = document.createElement('a')a.href = './static/template.xlsx'a.download = '近期消费统计表.xlsx'a.style.display = 'none'document.body.appendChild(a)a.click()a.remove()},ImportData (file) { // 参数为file,表示要上传的文件const types = file.name.slice(file.name.lastIndexOf('.')) // 获取文件后缀名const fileType = ['.xlsx', '.xls'].some(item => item === types) // 判断文件类型是否为xlsx或xlsif (!fileType) { // 如果文件类型不正确,提示用户重新上传this.$message.warning('文件格式错误!请重新上传')return // 如果文件类型不正确 结束函数}this.newData = [] // 初始化newData,用于存储读取到的数据const reader = new FileReader() // 创建文件读取器reader.readAsBinaryString(file.raw) // 将文件内容读取成二进制字符串reader.onload = () => { // 当文件读取成功时const binary = reader.result // 获取文件内容的二进制字符串const wb = XLSX.read(binary, { // 将二进制字符串转换成workbook对象type: 'binary'})// 将workbook对象中的第一个sheet转换成JSON格式(跳过前两行)const outdata = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], { range: 2 })console.log(outdata)outdata.map((item, index) => {// 对读取的字段进行必要的判断this.JudgeEmpty(item['出生日期'], '出生日期', index)this.JudgeEmpty(item['姓名'], '姓名', index)this.JudgeEmptyAndNumber(item['上月'], '上月', index)this.JudgeEmptyAndNumber(item['下月'], '下月', index)let obj = {}for (let key in tempObj) {if (!item.hasOwnProperty(key)) { continue }if (key === '上月' || key === '下月') {obj[tempObj[key]] = Math.floor(item[key] * 100) / 100} else if (key === '出生日期') {obj[tempObj[key]] = this.$util.formatExcelDate(item[key])} else { obj[tempObj[key]] = item[key] }}this.newData.push(obj)})this.DataProcess()}},DataProcess () {// 涉及需要系统自动计算处理的this.newData.forEach(ele => {this.$set(ele, 'sum', Math.floor((ele.last + ele.next) * 100) / 100)})console.log(this.newData)// 处理完后,接下来调用接口,将newData提交给后端},// Excel里字段判空JudgeEmpty (a, str, i) {i++if (typeof a === 'undefined') {this.$message.error('Excel中第' + i + '行<' + str + '>列数据未填写完整,请补充!')this.newData = []throw Error}},// Excel里字段判空且填写类型必须是数字JudgeEmptyAndNumber (a, str, i) {i++if (typeof a === 'undefined') {this.$message.error('Excel中第' + i + '行<' + str + '>列数据未填写完整,请补充!')this.newData = []throw Error}if (isNaN(a)) {this.$message.error('Excel中第' + i + '行<' + str + '>列数据类型不正确,请修正!')this.newData = []throw Error}}
}  

表格文件不存储

看图:
在这里插入图片描述
excel的一些填写注意点与前端存储excel模板时一样

依赖下载:
npm install moment
npm install vue-json-excel?
npm install xlsx?

代码实现
1.template

<download-excelclass="export-excel-wrapper":data="tableData":fields="json_fields"header="近期消费统计模板表"type="xls"worksheet="My Worksheet"name="近期消费统计模板表"
><el-button type="primary" size="small">导出模板</el-button>
</download-excel>
<!-- 导入数据按钮同前端存储excel -->
<el-table:data="tableData"style="width: 100%"
><el-table-columnprop="name"label="姓名"width="180"/><el-table-columnprop="gender"label="性別"width="180"/><el-table-columnprop="date"label="出生日期"/><el-table-columnprop="last"label="上月"/><el-table-columnprop="next"label="下月"/><el-table-columnprop="sum"label="合计"/><el-table-columnprop="remarks"label="备注"/>
</el-table>

2.js

import * as XLSX from 'xlsx'
let tempObj = {出生日期: 'date',上月: 'last',下月: 'next',备注: 'remarks'
}data () {return {// 导出的字段(前两个字段有值,后4个无值)json_fields: {姓名: 'name',性别: 'gender',出生日期: 'xxx',上月: 'xxx',下月: 'xxx',备注: 'xxx'},// 后端返给前端的初始假数据tableData: [{name: 'yxx',gender: '女'},{name: 'wx',gender: '男'}],// 新导入的数据newData: []}},
methods: {ImportData (file) {const types = file.name.slice(file.name.lastIndexOf('.')) // 获取文件后缀名const fileType = ['.xlsx', '.xls'].some(item => item === types) // 判断文件类型是否为xlsx或xlsif (!fileType) { // 如果文件类型不正确,提示用户重新上传this.$message.warning('文件格式错误!请重新上传')return // 如果文件类型不正确 结束函数}this.newData = [] // 初始化newData,用于存储读取到的数据const reader = new FileReader() // 创建文件读取器reader.readAsBinaryString(file.raw) // 将文件内容读取成二进制字符串reader.onload = () => { // 当文件读取成功时执行以下操作const binary = reader.result // 获取文件内容的二进制字符串const wb = XLSX.read(binary, { // 将二进制字符串转换成workbook对象type: 'binary'})// 将workbook对象中的第一个sheet转换成JSON格式,跳过1行(标题行)const outdata = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], { range: 1 })console.log(outdata)outdata.map((item, index) => {this.JudgeEmpty(item['出生日期'], '出生日期', index)this.JudgeEmptyAndNumber(item['上月'], '上月', index)this.JudgeEmptyAndNumber(item['下月'], '下月', index)this.JudgeEmpty(item['备注'], '备注', index)let obj = {}// eslint-disable-next-line guard-for-infor (let key in tempObj) {// eslint-disable-next-line no-prototype-builtinsif (!item.hasOwnProperty(key)) { return }if (key === '上月' || key === '下月') {obj[tempObj[key]] = Math.floor(item[key] * 100) / 100} else if (key === '出生日期') {obj[tempObj[key]] = this.$util.formatExcelDate(item[key])} else { obj[tempObj[key]] = item[key] }}this.newData.push(obj)})this.DataProcess()}},DataProcess () {this.tableData.forEach((ele, i) => {// eslint-disable-next-line guard-for-infor (let key in this.newData[i]) { // 将新旧数据对象拼接起来this.$set(ele, key, this.newData[i][key])}// 涉及需要系统自动计算处理的this.$set(ele, 'sum', Math.floor((ele.last + ele.next) * 100) / 100)})// 处理完后,接下来调用接口,将newData提交给后端}
}

处理excel输入为日期时的方法,放在了公共代码util.js里,如下:

import * as moment from 'moment'
const START_TIME = '1900/01/01'
const FORMAT = 'YYYY/MM/DD'
export default {// 日期转换:将1999年8月27日或1999/8/27 统一转为1996/08/27formatExcelDate (num) {let duration = num - 1// 1900/2/29的num为60if (num > 60) {// 对于num大于60的需解析日期,要减去多的1900/2/29日的那一天duration = num - 2}return moment(START_TIME).add(moment.duration({ days: duration })).format(FORMAT)},install (innerVue) {innerVue.prototype.$util = this}
}

http://www.ppmy.cn/news/93311.html

相关文章

Windows Subsystem for Linux (WSL)安装Ubuntu 0x80070005的问题

文章目录 小结问题解决参考 小结 在Windows 11中安装Windows Subsystem for Linux (WSL)&#xff0c; 并安装Ubuntu 22.04.2 LTS&#xff0c;碰到了棘手的问题报错&#xff1a;0x80070005&#xff0c; 进行了解决。 问题 在Windows 11的微软应用商店Microsoft Store中安装Ub…

C++中读写文件方法(fstream用法)

文章目录 前言一、 打开文件方法二、读写方法三、读写文本示例1、文本文件操作示例&#xff1a;2、二进制文件读写示例&#xff1a; 总结 前言 日常工作中肯定会用到文件读写操作&#xff0c;C STL中 fstream 是一种用于文件读写的流类&#xff0c;它可以方便地对文件进行输入…

服务器模型 setsockopt 网络超时检测 广播组播和unix域套接字 5.23

四.服务器模型 1.循环服务器 TCP服务器 TCP服务器端运行后等待客户端的连接请求。 TCP服务器接受一个客户端的连接后开始处理&#xff0c;完成了客户的所有请求后断开连接。 TCP循环服务器一次只能处理一个客户端的请求。 只有在当前客户的所有请求都完成后&#xff0c;服务…

Java-API简析_java.lang.Class类(基于JDK1.8)(浅析源码)

【版权声明】未经博主同意&#xff0c;谢绝转载&#xff01;&#xff08;请尊重原创&#xff0c;博主保留追究权&#xff09; https://blog.csdn.net/m0_69908381/article/details/130838927 出自【进步*于辰的博客】 其实我的【Java-API】专栏内的博文对大家来说意义是不大的。…

GATK最佳实践之数据预处理SnakeMake流程

<~生~信~交~流~与~合~作~请~关~注~公~众~号生信探索> 写的数据预处理snakemake流程其实包括在每个单独的分析中比如种系遗传变异和肿瘤变异流程中&#xff0c;这里单独拿出来做演示用&#xff0c;因为数据预处理是通用的&#xff0c;在call变异之前需要处理好数据。 数据…

GPC_UICC Configuration

GPC_UICC Configuration_v2.0.pdf 1 简介 本文档规定了在 ETSI 规范 TS 102 221 [TS 102 221]、TS 102 223 [TS 102 223] 中指定的 UICC 平台上实施 GlobalPlatform 规范的配置要求&#xff0c; TS 102 225 [TS 102 225] 和 TS 102 226 [TS 102 226]。 GlobalPlatform Common …

叮咚音乐门铃芯片方案推荐 WTN6006-8S 低功耗 高性价比

​ 随着物联网技术的不断发展&#xff0c;智能家居已经成为了生活中不可或缺的一部分。作为智能家居中的重要组成部分&#xff0c;门铃同样需要进行智能化升级&#xff0c;在改善用户体验、保障家庭安全方面起到了重要作用。本文将介绍一种基于音乐芯片的叮咚门铃应用方案…

金融、医疗、教育等各场景下小程序SDK的应用

近年来&#xff0c;随着数字经济的飞速发展和移动终端的迅速普及&#xff0c;移动互联网全面覆盖&#xff0c;各类应用服务层出不穷&#xff0c;涵盖了方方面面的生活、工作和学习。 而小程序作为一种轻量级的应用形态&#xff0c;越来越受到开发者和用户的欢迎。为了满足不同行…