【vue导入导出Excel】vue简单实现导出和导入复杂表头excel表格功能【纯前端版本和配合后端版本】

news2024/12/27 14:03:28

前言
这是一个常用的功能,就是导入和导出excel表格
但是时常会遇到一些复杂表头的表格导出和导入
比如我这个案例里面的三层表头的表格。
网上看了下发现了一个非常简单导出和导入方法
当然这个是纯前端的版本,会出现分页不好下载的情况。所以实际工作中,导出还是后端负责的。

效果图
这里是表格的样式,三层表头
在这里插入图片描述

 这里是点击导出后的效果和表格格式

在这里插入图片描述

在这里插入图片描述 

这里是点击导入后的效果和获取的数据格式

在这里插入图片描述

在这里插入图片描述

 使用方法简介

1,要下载一个插件,输入这个指令:npm install -S file-saver xlsx

2,在页面中引入这个,直接在你需要写导入导出的表格页面写就行

在这里插入图片描述

3,给你的表格绑上这个id。用来导出的时候拿数据的

在这里插入图片描述 

这里如果想要导入后获取数据传给后端,就在这个位置把他循环push到一个新数组内,然后在循环外面把这个数组传给后端

在这里插入图片描述 代码部分(纯前端导入导出)

<template>
  <div>
    <div class="titleBtn">
      <!-- 导出Excel -->
      <el-button
        @click="exportClick"
        type="primary"
        size="small"
        style="margin: 0 20px"
        icon="el-icon-folder-opened"
        >导出</el-button
      >
      <!-- 导入Excel -->
      <el-upload
        action="/上传文件的接口"
        :on-change="onChange"
        :auto-upload="false"
        :show-file-list="false"
        accept=".xls, .xlsx"
        ref="upload"
        :multiple="true"
      >
        <el-button type="warning" icon="el-icon-folder-add" size="small"
          >导入</el-button
        >
      </el-upload>
    </div>
    <el-table :data="tableData" style="width: 100%" id="mainTable">
      <el-table-column prop="date" label="日期" width="150"> </el-table-column>
      <el-table-column label="配送信息">
        <el-table-column prop="name" label="姓名" width="120">
        </el-table-column>
        <el-table-column label="地址">
          <el-table-column prop="province" label="省份" width="120">
          </el-table-column>
          <el-table-column prop="city" label="市区" width="120">
          </el-table-column>
          <el-table-column prop="address" label="地址" width="300">
          </el-table-column>
          <el-table-column prop="zip" label="邮编" width="120">
          </el-table-column>
        </el-table-column>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
import FileSaver from "file-saver";
import * as XLSX from "xlsx";
export default {
  data() {
    return {
      tableData: [
        {
          date: "2016-05-02",
          name: "王小虎",
          province: "上海",
          city: "普陀区",
          address: "上海市普陀区金沙江路 1518 弄",
          zip: 200333,
        },
      ],
    };
  },
  methods: {
    //导出
    exportClick() {
      //第一个参数是到处后文件名,第二个是id绑定表格dom
      this.exportExcel("test", "mainTable");
    },
    //转换数据
    exportExcel(filename, tableId) {
      var xlsxParam = { raw: true }; // 导出的内容只做解析,不进行格式转换
      var table = document.querySelector("#" + tableId).cloneNode(true);
      var wb = XLSX.utils.table_to_book(table, xlsxParam);
      /* 获取二进制字符进行输出 */
      var wbout = XLSX.write(wb, {
        bookType: "xlsx",
        bookSST: true,
        type: "array",
      });
      try {
        FileSaver.saveAs(
          new Blob([wbout], { type: "application/octet-stream" }),
          filename + ".xlsx"
        );
      } catch (e) {
        if (typeof console !== "undefined") {
          console.log(e, wbout);
        }
      }
      return wbout;
    },
    //导入
    onChange(file, fileList) {
      this.readExcel(file); // 调用读取数据的方法
    },
    // 读取数据
    readExcel(file) {
      let that = this;
      if (!file) {
        //如果没有文件
        return false;
      } else if (!/.(xls|xlsx)$/.test(file.name.toLowerCase())) {
        this.$message.error("上传格式不正确,请上传xls或者xlsx格式");
        return false;
      }
      const fileReader = new FileReader();
      fileReader.onload = (ev) => {
        try {
          const data = ev.target.result;
          const workbook = XLSX.read(data, {
            type: "binary",
          });
          if (workbook.SheetNames.length >= 1) {
            this.$message({
              message: "导入数据表格成功",
              showClose: true,
              type: "success",
            });
          }
          const wsname = workbook.SheetNames[0]; //取第一张表
          const ws = XLSX.utils.sheet_to_json(workbook.Sheets[wsname]); //生成json表格内容
          console.log("生成json:", ws);
          // that.tableData = [];
          for (var i = 2; i < ws.length; i++) {
            let sheetData = {
              // 键名为绑定 el 表格的关键字,值则是 ws[i][对应表头名]
              date: ws[i]["日期"],
              name: ws[i]["配送信息"],
              province: ws[i]["__EMPTY"],
              city: ws[i]["__EMPTY_1"],
              address: ws[i]["__EMPTY_2"],
              zip: ws[i]["__EMPTY_3"],
            };
            console.log("上传的数据:", sheetData);
            //添加到表格中
            that.tableData.push(sheetData);
            //正常导入需要拿到上传的数据就在这从新弄个数组push进去,然后传给后台,后台保存后查询表格返给前端。
          }
          this.$refs.upload.value = "";
        } catch (e) {
          console.log(e);
          return false;
        }
      };
      // 如果为原生 input 则应是 files[0]
      fileReader.readAsBinaryString(file.raw);
    },
  },
};
</script>
<style scoped>
.titleBtn {
  display: flex;
  margin: 20px 0;
}
</style>

 配合后端的两个方法

 因为上面的纯前端写法有一个问题,就是有分页的时候我们没法拿到数据。
或者数据太大了我们下载实在是有点慢和卡。所以基本上工作中都是后端生成下载链接导出的。
这里再分享两个方法。

1,a标签下载

这种方法核心就是后端直接生成下载链接,前端只需要生成A标签然后下载就行了。较为常用的一个

daochu(){
      // A标签导出方法:通过生成一个A标签然后触发后台传过来的下载链接完成导出
      //核心注意需要给请求的格式改为:responseType: "blob",
      this.axios
          .post(
            url, {}, {
              token: true,
              responseType: "blob",
            }
          )
          .then((res) => {
            if (res.status == 200) {
              //拿到后台发过来的下载链接
              let url = window.URL.createObjectURL(new Blob([res.data]));
              //生成一个A标签
              let link = document.createElement("a");
              //样式设为none,没有大小,不占位置
              link.style.display = "none";
              //把链接地址给href
              link.href = url;
              //下载后的名字,用时间来标注避免重复
              let filename = new Date().getTime() + ".xlsx";
              //给A标签添加属性download,值为上面的名字
              link.setAttribute("download", filename);
              //在页面的尾部插入元素A标签
              document.body.appendChild(link);
              //点击A标签,这样就触发下载了。
              link.click();
            } else if (res.data.code != 200) {
              this.$message("暂无数据");
            }
            this.exporloading = false;
          })
          .catch((err) => {
            this.exporloading = false;
          });
    }

2,用上面的那种前端方法,我们直接让后端传给我们一个完整的表格数据,不分页的那种。

然后用这个数据赋值到表格的数组内,然后把表格dom拿去导出方法中也可以下载。
这里我是因为后端没有给全部的数据,然后数据不是很多,我就干脆自己前台直接循环请求把每一页的数据合并到数组内实现了拿到所有数据的目的,不过这样不推荐啊。

这里this.$excels是我封装了一下这个方法,然后main.js赋值原型了。方法还是和上面的一样哈。

在这里插入图片描述

封装的样子,和上面基本是一样的。
在这里插入图片描述

这是循环拿到的分页数据,看到了吧85条都拿到了,然后复制给tableData2数组,然后拿表格的dom,就可以导出全部数据的表格了

在这里插入图片描述

表格中多个sheet一次读取出来写法


有时候我们需要的不仅仅是第一个sheet的。可能一个表格中有很多个sheet然后每个sheet字段不一样。所以我们可以这样写,在上面的方法中稍加改动。
只需要把readExcel这个方法修改一下就行了。修改的地方主要就是加了个循环,读取每一个sheet的数据出来。

// 读取数据
    readExcel(file) {
      let that = this;
      if (!file) {
        //如果没有文件
        return false;
      } else if (!/.(xls|xlsx)$/.test(file.name.toLowerCase())) {
        this.$message.error("上传格式不正确,请上传xls或者xlsx格式");
        return false;
      }
      const fileReader = new FileReader();
      fileReader.onload = (ev) => {
        try {
          const data = ev.target.result;
          const workbook = XLSX.read(data, {
            type: "binary",
          });
          if (workbook.SheetNames.length >= 1) {
            //读取到表中sheet
            this.$message({
              message: "导入数据表格成功",
              showClose: true,
              type: "success",
            });
          }
          for (var i = 0; i < workbook.SheetNames.length; i++) {
            const wsname = workbook.SheetNames[i]; //取第一张表
            const ws = XLSX.utils.sheet_to_json(workbook.Sheets[wsname]); //生成json表格内容
            console.log("生成json:", ws);

            // that.tableData = [];
            // for (var i = 2; i < ws.length; i++) {
            //   let sheetData = {
            //     // 键名为绑定 el 表格的关键字,值则是 ws[i][对应表头名]
            //     date: ws[i]["日期"],
            //     name: ws[i]["配送信息"],
            //     province: ws[i]["__EMPTY"],
            //     city: ws[i]["__EMPTY_1"],
            //     address: ws[i]["__EMPTY_2"],
            //     zip: ws[i]["__EMPTY_3"],
            //   };
            //   console.log("上传的数据:", sheetData);
            //   //添加到表格中
            //   that.tableData.push(sheetData);
            //   //正常导入需要拿到上传的数据就在这从新弄个数组push进去,然后传给后台,后台保存后查询表格返给前端。
            // }
          }
          this.$refs.upload.value = "";//清空上传列表,不能放在循环内清空,否则第一次循环sheet1时直接清空了上传列表,第二次循环sheet2就没数据了
        } catch (e) {
          console.log(e);
          return false;
        }
      };
      // 如果为原生 input 则应是 files[0]
      fileReader.readAsBinaryString(file.raw);
    },

多sheet读取效果图

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/661994.html

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

相关文章

深入分析Go语言与C#的异同

摘要&#xff1a;本文由葡萄城技术团队于CSDN原创并首发。转载请注明出处&#xff1a;葡萄城官网&#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务&#xff0c;赋能开发者。 前言 为了更加深入地介绍Go语言以及与C#语言的比较&#xff0c;本文将会从多个维度出发…

ppt怎么录制视频和声音 ppt怎么录制人像

ppt在课堂上是非常重要的工具&#xff0c;许多微课都是通过ppt讲授。ppt的功能日新月异&#xff0c;之前的ppt仅具有演示功能&#xff0c;如今pp录制视频t还是可以的。ppt怎么录制视频和声音&#xff1f;首先&#xff0c;我们得创建一个ppt&#xff0c;然后再进行录制。ppt怎么…

【Python 随练】分解质因数

题目&#xff1a; 将一个正整数分解质因数。例如&#xff1a;输入 90,打印出90233*5。 简介&#xff1a; 在本篇博客中&#xff0c;我们将解决一个数学问题&#xff1a;如何将一个正整数分解成质因数的乘积。我们将给出问题的解析&#xff0c;并提供一个完整的代码示例来实现…

【Python】解决pandas读取excel,以0向前填充的数字会变成纯数字

1 问题 test.xlsx的内容如下 序号code000012310001242000125 df pd.read_excel(test.xlsx)读取后的codel列&#xff0c;样例如下 序号code012311242125 显然这不是我想要的结果。 2 解决办法 &#xff08;1&#xff09;第一种 指定列以字符串读取 df pd.read_excel(t…

在 ZBrush、Blender 和 Substance 3D Painter 中重新创建 Bowser

今天瑞云渲染小编给大家带来一篇mral Ismayilov作者Bowser 项目背后的工作流程&#xff0c;展示了头发是如何修饰的&#xff0c;并解释了纹理化过程。 简介 大家好&#xff0c;我是尤姆拉尔-伊斯马伊洛夫&#xff0c;是一名3D角色艺术家和动作设计师&#xff0c;在阿塞拜疆的巴…

【CMake 入门与进阶(10)】 CMake如何定义函数,内部参数及作用域(附代码)

前几篇已经学习了cmake 中常用的命令 command、变量 variable &#xff0c;相信大家已经掌握了 cmake 工具的基本使用方法&#xff1b;本文我们进一步学习 cmake&#xff0c;看看 cmake 还有哪些东西。 定义函数 在 cmake 中我们也可以定义函数&#xff0c;cmake 提供了 funct…

基于图神经网络的切片级漏洞检测及解释方法

源自&#xff1a;软件学报 作者&#xff1a;胡雨涛 王溯远 吴月明 邹德清 李文科 金海 摘 要 随着软件的复杂程度越来越高, 对漏洞检测的研究需求也日益增大. 软件漏洞的迅速发现和修补, 可以将漏洞带来的损失降到最低. 基于深度学习的漏洞检测方法作为目前新兴的检测手…

云原生之深入解析Kubernetes中Kubectl Top是如何进行资源监控

一、Kubectl top 的使用 kubectl top 是基础命令,但是需要部署配套的组件才能获取到监控值:1.8 以下:部署 heapter;1.8 以上:部署 metric-server;kubectl top node:查看 node 的使用情况:kubectl top pod:查看 pod 的使用情况:不指定 pod 名称,则显示命名空间下所有…

TSception:从EEG中捕获时间动态和空间不对称性用于情绪识别

TSception&#xff1a;从EEG中捕获时间动态和空间不对称性用于情绪识别&#xff08;论文复现&#xff09; 摘要模型结构代码实现写在最后 **这是一篇代码复现&#xff0c;原文通过Pytorch实现&#xff0c;本文中使用Keras对该结构进行复现。**该论文发表在IEEE Transactions on…

【Python 随练】古典问题:兔子繁殖问题

题目&#xff1a; 古典问题&#xff1a;有一对兔子&#xff0c;从出生后第 3 个月起每个月都生一对兔子&#xff0c;小兔子长到第三个月&#xff0c;后每个月又生一对兔子&#xff0c;假如兔子都不死&#xff0c;问每个月的兔子总数为多少&#xff1f; 简介&#xff1a; 在本…

三、DSMP/OLS等夜间灯光数据贫困地区识别——MPI和灯光指数拟合、误差分析

一、前言 当我们准备好MPI和灯光指数(包括总灯光指数和平均灯光指数)之后,接下来主要的过程就是通过将MPI和灯光指数拟合,构建多维度指数估算模型,这里我解释一下前文中的MPI计算过程,其实利用熵值法确定指标权重,并通过各 指 标 归 一 化 数 值 乘 以 对 应 的 权 重 …

UG NX二次开发(C#)-用UFun函数导出图像(Image)

文章目录 1、前言2、在UG NX中交互导出图像的操作2.1 打开一个三维模型2.2 打开导出图像的界面3、采用UFun函数来实现3.1 搜索image的方法3.2 帮助说明3.3 应用环境3.4 方法应用4、后记1、前言 在UG NX二次开发过程中,三维CAD模型有时需要导出为图像,如.png、.jpg、.bmp、.t…

类与封装的概念

类通常分为以下两个部分 类的实现细节 类的使用方式 当使用类时&#xff0c;不需要关心其实现细节 当创建类时&#xff0c;才需要考虑其内部实现细节 封装的基本概念 根据经验&#xff1a;并不是类的每个属性都是对外公开的 如&#xff1a;女孩子不希望外人知道自己的体重…

【系统开发】尚硅谷 - 谷粒商城项目笔记(二):搭建分布式系统基本环境

文章目录 搭建分布式系统基本环境引入spring-cloud-alibaba依赖Nacos作为注册中心Feign 远程调用Nacos作为配置中心Nacos配置中心进阶Nacos加载多配置集GateWay网关网关路由分发解释 搭建分布式系统基本环境 引入spring-cloud-alibaba依赖 在common的pom.xml中加入 &#xff…

Socket网络通信过程 与 IO多路复用原理

0、引言 本文主要讲述Socket网络编程的基本知识、IO多路复用的select、poll、epoll实现原理以及比较&#xff0c;并解答了一些socket建立连接、阻塞的常见问题。 1、什么是Socket、网络通信的过程 Socket 的中文名叫作插口&#xff0c;事实上&#xff0c;双方要进行网络通信前…

HTML(一)

一.HTML的标准结构 <!doctype html> 声明文档类型<html> HTML根标签<head> 头标签<title></title> 标题标签</head><body> 主题标签...</body></html> 二.标签介绍 2.1 段落标签 1.注释标签 <!--我是一个注释--…

送外卖适合什么蓝牙耳机,推荐几款适合户外佩戴的骨传导耳机

骨传导耳机&#xff0c;是通过震动的方式将声音转化为不同频率的机械振动&#xff0c;由于不需要通过耳膜就可以听到声音&#xff0c;骨传导耳机在保留传统耳机的优点的基础上&#xff0c;解决了传统耳机不能在开放环境中使用的问题。那么在骨传导耳机中&#xff0c;究竟有哪些…

MobaXterm 常用设置

MobaXterm 是用于远程计算的工具箱&#xff0c;作为一个 Windows 应用程序&#xff0c;它为程序员、网站管理员、IT管理员和几乎所有需要以更简单的方式处理远程工作的用户量身定制了大量功能。MobaXterm 提供了所有重要的远程网络工具(SSH, X11, RDP, VNC, FTP, MOSH&#xff…

消息队列常见问题整理

前言 消息队列&#xff08;Message Queue&#xff09;&#xff0c;从广义上讲是一种消息队列服务中间件&#xff0c;提供一套完整的信息生产、传递、消费的软件系统。 消息队列所涵盖的功能远不止于队列&#xff08;Queue&#xff09;&#xff0c;其本质是两个进程传递信息的…

Java Web程序设计的学习

属于B/S结构、服务器软件&#xff1a;Apache Tomcat、 Web 项目 目录结构&#xff1a; 1.src目录&#xff1a;存放Java源文件 2.WebRoot目录&#xff1a; 存在两个子目录&#xff1a; META-INF目录 WEB-INF目录&#xff1a;&#xff08;lib目录&#xff1a;存放驱动…