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

news2025/2/25 13:27:40

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

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

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

分析需求:
(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-upload
        action=""
        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-column
        prop="name"
        label="姓名"
        width="180"
      />
      <el-table-column
        prop="date"
        label="出生日期"
      />
      <el-table-column
        prop="last"
        label="上月"
      />
      <el-table-column
        prop="next"
        label="下月"
      />
      <el-table-column
        prop="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或xls
    if (!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-excel
  class="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-column
    prop="name"
    label="姓名"
    width="180"
  />
  <el-table-column
    prop="gender"
    label="性別"
    width="180"
  />
  <el-table-column
    prop="date"
    label="出生日期"
  />
  <el-table-column
    prop="last"
    label="上月"
  />
  <el-table-column
    prop="next"
    label="下月"
  />
  <el-table-column
    prop="sum"
    label="合计"
  />
  <el-table-column
    prop="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或xls
      if (!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-in
          for (let key in tempObj) {
            // eslint-disable-next-line no-prototype-builtins
            if (!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-in
        for (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/27
  formatExcelDate (num) {
    let duration = num - 1

    // 1900/2/29的num为60
    if (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.coloradmin.cn/o/561402.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Leetcode60天带刷】day01——704.二分查找、27.移除元素

题目&#xff1a; 704. 二分查找 Leetcode原题链接&#xff1a;力扣704.二分查找 思考历程与知识点&#xff1a; 考查二分查找能力&#xff0c;注意mid的取值。 注意&#xff1a; 右端点的大小&#xff0c;需要在数组长度上-1。也就是nums.size()-1&#xff0c;因为下标是从…

chatgpt赋能Python-python_numpy_转置

Python Numpy 转置 - 高效处理数据的必备技巧 作为一名专注于Python编程的工程师&#xff0c;你可能已经知道了 Python 编程语言的优雅以及Numpy 库的高效操作。在进行数值计算和数据处理方面&#xff0c;Numpy 库已成为 Python 可以与其他编程语言匹敌的主要原因之一。其中一…

Vue 3 第二十二章:组件十(组件高级特性-组件的渲染函数和JSX/TSX语法)

文章目录 1. 渲染函数2. JSX / TSX 语法2.1. 基本使用2.2. 使用 vue 中的语法2.2.1. {} 语法2.2.2. v-model 使用2.2.3. v-show 使用2.2.4. v-if 不支持&#xff0c;实现v-if功能2.2.5. v-for 不支持&#xff0c;实现 v-for 功能2.2.6. v-bind 不支持&#xff0c;模拟 v-bind2.…

AWD竞赛全流程解析

AWD(Attack With Defense&#xff0c;攻防兼备)是一个非常有意思的模式&#xff0c;你需要在一场比赛里要扮演攻击方和防守方&#xff0c;攻者得分&#xff0c;失守者会被扣分。也就是说&#xff0c;攻击别人的靶机可以获取 Flag 分数时&#xff0c;别人会被扣分&#xff0c;同…

汇编十三、串口

1、通信相关概念 (1)单工&#xff1a;只能接收或只能发送数据。 (2)半双工&#xff1a;既能发送数据&#xff0c;也能接收数据&#xff0c;但不能同时进行。 (3)全双工&#xff1a;可以同时进行发送和接收数据。 (4)单片机中常用的通信物理接口&#xff1a;I2C、SPI、USB、…

tushare单个股票过去五年的数据整理与预测

文章目录 前言&#xff1a;1. 导入相关包2. 数据预处理3. 构建模型3. 模型训练4. 检查数据6. 工作中其他常用包记录 前言&#xff1a; %md 在量化投资中&#xff0c;计算收益率是更常见的做法&#xff0c;而不是仅计算股价。计算收益率可以更好地反映投资的回报情况&#xff0c…

Pinctrl子系统_01_Pinctrl子系统介绍

本节介绍在Pinctrl子系统中&#xff0c;将会学习哪些内容。 Pinctrl作用 Pinctrl&#xff1a;Pin Controller&#xff0c;顾名思义&#xff0c;就是用来控制引脚的。 一个芯片有成百上千个引脚&#xff0c;这些引用要怎么配置&#xff0c;配置成什么功能&#xff0c;都是通P…

python+django网上书籍商城小说在线阅读分享下载系统k19is-vue

为了解决用户便捷地在网上购物以及下载文件&#xff0c;本文设计和开发了一个网页小说阅读系统。本系统是基于 B/S架构设计&#xff0c;Dango框架 &#xff0c;Python技术的前台页面设计与实现&#xff0c;使用Mysql数据库管理来完成系统的相关功能。主要实现了管理员与用户的注…

ETSI TS-关于SCP80

描述 GPC_UICC Configuration_v2.0.pdf 中: 规范 ts_102.225v12.1.0 Secured packet structure for UICC based applications.pdf spi kic kid编码 7 TCP/IP 的实现 在发送安全数据包之前&#xff0c;发送实体应使用定义的推送机制打开 TCP/IP 连接 在 ETSI TS 102 226 [9] …

【MATLAB第34期】基于MATLAB的2023年棕熊优化算法BOA优化LSTM时间序列预测模型 优势明显,注释详细,绘图丰富

【MATLAB第34期】基于MATLAB的2023年棕熊优化算法BOA优化LSTM时间序列预测模型 优势明显&#xff0c;注释详细&#xff0c;绘图丰富&#xff0c;适合小白 一、代码优势 1.使用2023年棕熊算法BOA优化LSTM超参数&#xff08;学习率&#xff0c;隐藏层节点&#xff0c;正则化系数…

chatgpt赋能Python-python_numpy倒序

Python Numpy倒序&#xff1a;简介、使用和优势 简介 Python是一门功能强大的编程语言&#xff0c;提供了众多开源库&#xff0c;其中Numpy是其中最流行的之一。Numpy是Python中的一个数值计算库&#xff0c;提供了一个高效的数组对象和相应的数学函数。它是数据科学家和机器…

Thonny-适合初学者小白的开箱即用的轻量级 Python IDE

如果你是一位Python初学者小白,那最适合Thonny它了&#xff0c;如果不是初学者&#xff0c;请选择PyDev和Pycharm。 Thonny是一款面向初学者小白的轻量级 IDE&#xff0c;可以让初学者更好更快的入门上手 Python&#xff0c;而不致于在环境上浪费过多的时间。 取之 Python&…

chatgpt赋能Python-python_purple

Python Purple: 一个高效的Python IDE Python Purple是Python程序员们最需要的工具之一。它是一款高效的Python IDE&#xff0c;允许用户轻松地创建&#xff0c;编辑和协作开发Python代码。本文将涉及Python Purple的一些重要特点以及它如何提高编码质量和提高生产力。 介绍P…

【利用AI让知识体系化】TypeScript目标:扩展JavaScript能力

I. TypeScript 简介 TypeScript 的起源 TypeScript 的起源是由微软公司开发&#xff0c;其首席架构师是 Anders Hejlsberg。Anders 是 Delphi 和 C# 语言的创始人&#xff0c;于2012年从微软发布了 TypeScript。 TypeScript 诞生的原因是为了解决 JavaScript 的一些缺点&…

Nginx(四)

部署LNMP架构动态网站WordPress LNMPLinuxNginxMySQLPhp 环境 192.168.29.141centos8Nginx1.24.0192.168.29.142centos8MySQL8.0.33192.168.29.143centos8Php7.2.24 关闭firewalld systemctl stop firewalld systemctl disable firewalld 关闭selinux setenforce 0 sed -ir…

网络原理(六):http 协议(上)

目录 HTTP 协议是什么 抓包工具 Fiddler 的下载 使用Fiddler HTTP 请求 (Request) HTTP 请求格式 首行 请求头&#xff08;Header&#xff09; Cookie HTTP 协议是什么 还是老样子&#xff0c;在讲解http 之前我们先来了解以下什么叫做 http 。 HTTP&#xff08;Hyp…

使用百度 PaddleOCR对身份证识别的简单处理

一&#xff1a;引言 本文才用百度的PaddleOCR对身份证进行识别的处理&#xff0c;由于直接使用并未进行对跟多数据集进行训练&#xff0c;当前的效果是对非少数民族的身份证识别率可以达到85%以上&#xff0c;同时要求身份证图片是正面且相对清晰。否则效果不理想&#xff0c;本…

基于java的时间管理系统的设计与实现

背景 要设计一个时间管理系统&#xff0c;通过这个系统能够满足时间管理的管理功能。系统的主要功能包括首页&#xff0c;个人中心&#xff0c;系统公告管理&#xff0c;用户管理&#xff0c;时间分类管理&#xff0c;事件数据管理&#xff0c;目标数据管理&#xff0c;用户日…

【系统软件】源码编译安装ZLIB——Could NOT find ZLIB(missing:ZLIB_LIBRARY ZLIB_INCLUDE_DIR

【系统软件】源码编译安装ZLIB——Could NOT find ZLIB(missing:ZLIB_LIBRARY ZLIB_INCLUDE_DIR 前言一、简介二、源码下载三、解压、构建四、编译五、安装六、安装成功后如下图七、如何使用zlib中的include 前言 今天原本打算源码编译安装protobuf&#xff0c;但是在构建项目…

图神经网络GNN GCN AlphaFold2 虚拟药物筛选和新药设计

文章目录 图神经网络1. Geometric Deep LearningRepresentation learning 表征学习机器学习的数据类型&#xff1a;序列、网格、图引出GNN 2. Graph Neural NetworksMachine Learning Lifecyclelearning graph is hardFeature Learning in GraphsWays to Analyze NetworksA Nai…