SpringBoot+Vue实现Excel文档导入和导出

news2024/11/30 0:47:01

1.准备工作

1.1.前端程序

在前端首先加上批量导出的按钮,如下

<el-button size="small" type="warning" plain @click="exportData">
批量导出
</el-button>

 在添加了点击事件之后,在methods中要与之对应的添加上exportData的方法,其中multipleSelection是复选框中勾选后用户的id,下面的代码逻辑为,当我没有勾选复选框的时候(也就是multipleSelection的长度为0时)就执行导出功能

//批量导出
    exportData(){
      //没有选择行的时候全部导出,或者根据搜索条件导出
      if(!this.multipleSelection.length){
       
      }
    },

 1.2.后端程序

前端基本架构写好了,接下来我们开始写后端的接口,如下 

  • 接口的参数有两个,一个是用户的名字,一个是response对象(为了获取输出流,将Excel写回浏览器)
  • 借助hutool工具包提供的ExcelUtil类获取一个ExcelWrite对象(别忘了导入hutool的jar包)
<!--hutool工具包-->
<dependency>
  <groupId>cn.hutool</groupId>
  <artifactId>hutool-all</artifactId>
  <version>5.7.16</version>
</dependency>
  • 执行查询所有用户,将结果添加到write对象中
  • 在获取了输出流之后,将write对象写到流里
     /**
     * 批量导出
     * @param name
     */
    @GetMapping("/export")
    public void exportData(@RequestParam(required = false) String name, HttpServletResponse response) throws IOException {
        ExcelWriter writer = ExcelUtil.getWriter(true);
        List<User> list = new ArrayList<>();
        //第一种:全部导出(当name为空的时候执行,也就是说前端没有勾选复选框时,全部导出)
        if(StringUtils.isBlank(name)){
            //查询所有用户
            list = userService.list();
        }
        writer.write(list,true);
        //获取输出流
        ServletOutputStream outputStream = response.getOutputStream();
        //将excel写入到输出流里,并设置用完流之后就关闭
        writer.flush(outputStream,true);
    }

2.完善工作

这个时候,后端的程序也基本写好了,现在返回前端来写请求,我的请求之中添加了token,因为之前添加过jwt验证,如果没有token的话,就不能访问,但是之前在axios的请求头中都添加了token,而这个请求是js中的,所以要自己手动在请求路径中添加一个token(而之前后端程序中写了,如果请求头里没有token,那么后台会自己在请求路径中寻找token)

  //批量导出
    exportData(){
      //没有选择行的时候全部导出,或者根据搜索条件导出
      if(!this.multipleSelection.length){
        window.open('http://localhost:8082/user/export?token='+this.user.token)
      }
    },

3.测试

前后端框架基本写好了,接下来进行测试,启动前后端工程后,点击批量导出

可以看到,报了500的错误,那就表明是后台代码写的有问题,返回后端查看,发现控制台报了以下错误

这个错误比较经典,在对Excel进行处理的时候我们必须引入一个叫POI-OOXML的依赖,如下:

 <dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.2.3</version>
 </dependency>

接下来,进行测试,发现下载的文件是zip类型的,这与Excel表格格式后缀xlsx不符,所以我们还要在后台添加导出的文件格式

response.setContentType("application/vnd.openxmlformatsofficedocument.spreadsheetml.sheet;charset=utf-8");
response.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode("用户信息表","UTF-8")+".xlsx");
  • setContentType设置了HTTP响应的Content-Typeapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet,这表示响应的内容是一个Excel文件,即OpenXML格式的电子表格。charset=utf-8指定了字符编码为UTF-8。
  • setHeader设置了HTTP响应的Content-Disposition头,其值为attachment,表示响应的内容是附件,浏览器会提示用户下载该文件。filename=后面跟的是附件的默认文件名,这里通过URLEncoder.encode方法对"用户信息表"进行了URL编码,以确保文件名中的非ASCII字符在HTTP头中正确传输。编码后的字符串加上.xlsx后缀,构成了完整的文件名。

4.第二次测试

加上了响应格式之后,我们再来一次测试,如下:

可以看到,该文件名字已经被修改成“用户信息表”,并且格式也不是之前的.zip,而是Excel的格式,打开文件,如下:

可以看到表头对应的是实体类的字段名,那么如何将表头换成中文呢?

只需要在实体类的字段上加上@Alias注解并设置别名即可(注意:这个@Alias注解是hutool包下的,不是mybatis包下的),如下: 

 加上注解之后,再进行测试,Excel表头就会被修改成指定的名称

到目前为止,Excel导出的功能就完成了,但是还要修改一下业务逻辑

  • 当我不进行模糊查询的时候,点击批量导出,则要导出全部的数据
  • 当我进行模糊查询的时候,点击批量导出,则要导出查询出来的全部数据

所以我要给代码修改一下逻辑,如下:

LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.like(StringUtils.isNotBlank(name),User::getName,name);

list = userService.list(wrapper);

添加一个模糊查询,并设置一个条件,只有当name的值不为空,才会进行模糊查询,否则就不会添加模糊查询的条件,这样就完成了上面提出的业务要求

 5.完善后的前后端代码

@GetMapping("/export")
    public void exportData(@RequestParam(required = false) String name, HttpServletResponse response) throws IOException {
        ExcelWriter writer = ExcelUtil.getWriter(true);
        List<User> list = new ArrayList<>();
        //第一种:全部导出(当name为空的时候执行,也就是说前端没有勾选复选框时,全部导出)
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(name),User::getName,name);

        //if(StringUtils.isBlank(name)){
            //查询所有用户
            list = userService.list(wrapper);
        //}
        writer.write(list,true);

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode("用户信息表","UTF-8")+".xlsx");
        //获取输出流
        ServletOutputStream outputStream = response.getOutputStream();
        //将excel写入到输出流里,并设置用完流之后就关闭
        writer.flush(outputStream,true);
        //关闭write
        writer.close();
    }

前端添加的代码是要给请求添加一个name属性,这样后台才能接收到name,如下:

 //批量导出
    exportData(){
      //没有选择行的时候全部导出,或者根据搜索条件导出
      if(!this.multipleSelection.length){
        window.open('http://localhost:8082/user/export?token='+this.user.token+'&name='+this.name)
      }
    },

 测试如下:

首先查询姓王的用户,查询结果如下:

 然后再导出,结果如下:

自此,初步功能已经完善

6.勾选复选框之后进行导出

之前完成的是,不勾选复选框,然后进行全部数据的导出,和进行模糊搜索之后,将搜索出的数据进行全部导出 

整体思路

  • 要想勾选复选框之后对指定的数据进行导出,那么在勾选复选框之后就要把该用户的id传给后端,由于可以选择多个用户,那么前端传的数据应该是一个数组类型,但是GET方法传不了数组,所以我们可以将其转换成字符串类型,然后后端用String类型接收,然后再将字符串转换成List集合进行查询(为什么要转换成集合,因为mybatis-plus中的条件构造器in需要一个list类型的参数) 

在前端添加id的请求参数,如下,第一行程序意思是,将前端复选框勾选的用户的id数组转换成字符串,并且以逗号分隔,类似于"1","2","3"

let idStr = this.multipleSelection.join(',');
window.open('http://localhost:8082/user/export?token='+this.user.token+'&ids=' + idStr)

 后端用String类型的参数即可接收,如下:

  @RequestParam(required = false) String ids

 接下来的工作就是将字符串类型的参数转换成list集合,并将其添加到条件查询器里,如下:

//将字符串按逗号分割成数组
String[] id = ids.split(",");
//使用Stream API 将字符串数组转换为整数集合
List<Integer> userId = Arrays.stream(id).map(Integer::valueOf).collect(Collectors.toList());
wrapper.in(StringUtils.isNotBlank(ids),User::getId,userId);

全部代码

后端:

    /**
     * 批量导出
     * @param name
     */
    @GetMapping("/export")
    public void exportData(@RequestParam(required = false) String name,
                           @RequestParam(required = false) String ids,
                           HttpServletResponse response) throws IOException {
        ExcelWriter writer = ExcelUtil.getWriter(true);
        List<User> list = new ArrayList<>();
        //第一种:全部导出(当name为空的时候执行,也就是说前端没有勾选复选框时,全部导出)
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();

        //如果ids不为空(也就是我勾选了复选框),就执行将传进来的ids字符串转换成数组类型的操作然后导出勾选的用户数据,否则就执行全部导出
        if(StringUtils.isNotBlank(ids)){
            //将字符串按逗号分割成数组
            String[] id = ids.split(",");
            // 使用 Stream API 将字符串数组转换为整数集合
            List<Integer> userId = Arrays.stream(id).map(Integer::valueOf).collect(Collectors.toList());
            wrapper.in(StringUtils.isNotBlank(ids),User::getId,userId);

        }else {
            wrapper.like(StringUtils.isNotBlank(name),User::getName,name);
        }
        list = userService.list(wrapper);
        writer.write(list,true);

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode("用户信息表","UTF-8")+".xlsx");
        //获取输出流
        ServletOutputStream outputStream = response.getOutputStream();
        //将excel写入到输出流里,并设置用完流之后就关闭
        writer.flush(outputStream,true);
        //关闭write
        writer.close();
    }

前端: 


    //批量导出
    exportData(){
      //没有选择行的时候全部导出,或者根据搜索条件导出
      if(!this.multipleSelection.length){
        window.open('http://localhost:8082/user/export?token='+this.user.token+'&name=' + this.name)
      }else {
        //不加","也可以,join默认会加上
        let idStr = this.multipleSelection.join(',');
        window.open('http://localhost:8082/user/export?token='+this.user.token+'&ids=' + idStr)
      }
    },

7.批量导入功能实现

  • 由于Excel文件导入和文件上传本质一样,所以后端接口的参数也要一个MultipartFile
  • 同样的,Excel文件导入也要借助ExcelUtil,其中的getReader方法需要一个Input流作为参数,而MultipartFile类型能获取InputStream
  • 获取到reader之后,readAll方法将Excel文件中的数据读取为一个User对象的列表。User.class是Java反射中用来指定类的。
  • 获取到Excel表中的User类型的数据集合,再调用mybatisplus中的方法,将数据写入数据库
  • 其中这个ServiceException是自定义的异常

后端: 

    @PostMapping("/import")
    public Result importData(MultipartFile file) throws IOException {
        try {
            //获取inputStream流
            InputStream inputStream  = file.getInputStream();
            ExcelReader reader = ExcelUtil.getReader(inputStream);
            List<User> userList = reader.readAll(User.class);
            userService.saveBatch(userList);
        } catch (Exception e) {
            throw new ServiceException("文件上传失败");
        }
        return Result.success();
    }

前端: 

 来看看上传文件的前端代码,如下:

  • 文件上传是一个特定的代码,其中Element-UI规定了以下格式,其中有几个属性需要了解
  • action 后面跟请求路径
  • :headers  后面跟要在这个请求的请求头里添加的东西
  • :show-file-list  表示文件上传成功后要不要显示上传成功的文件的列表,false表示关闭,true表示开启
  • :on-success  后面跟文件上传成功之后的事件,handleImport事件如下:
    //批量导入
    handleImport(res,file,fileList){
      console.log(res)
      this.load(1)
      if (res.code === '200'){
        this.$message.success("上传成功")
      }else {
        this.$message.error(res.msg)
      }
    },
<el-upload
    style="display: inline-block;margin-left: 10px"
    action="http://localhost:8082/user/import"
    :headers="{token:user.token}"
    :show-file-list="false"
    :on-success="handleImport">
    <el-button size="small" plain type="primary">文件导入</el-button>
</el-upload>

 到此为止,该模块的功能全部实现>_<

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

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

相关文章

Visual Studio Code 的安装教程和配置C语言环境插件推荐

目录 1.vscode简介2.下载安装vs code3.VSCode基础配置VSCode界面简介VSCode设置中文界面VSCode个性化设置VSCode常用设置基本编辑快捷键VSCode常用快捷键 4.下载安装MinGW5.设置vscode里的环境6.插件推荐7.vscode官方文档 1.vscode简介 VSCode是微软出的一款轻量级编辑器&…

第2章 Rust初体验8/8:末尾不带分号的表达式即代码块返回值:更简洁的语法:猜骰子冷热游戏

讲动人的故事,写懂人的代码 2.9 故事7: 玩家输入的数字若越界则继续猜 贾克强:“我们终于要一起写这个游戏的最后一个故事啦!游戏中,你需要猜两个骰子的点数之和,因此你猜的数字应该在2到12之间。我们可以在代码中加入一些判断逻辑,如果你猜的数字超出了这个范围,游戏会…

足底筋膜炎怎么治疗才能彻底除根

现代快节奏的生活中&#xff0c;足底筋膜炎作为一种常见的足部疾病&#xff0c;困扰着越来越多的人。长时间的站立、行走&#xff0c;以及不正确的运动姿势&#xff0c;都可能成为足底筋膜炎的诱因。足底筋膜炎带来的疼痛和不适&#xff0c;严重影响了人们的生活质量和日常工作…

用Rust手把手编写一个Proxy(代理), 开始动工

https://shop.kongfz.com/795263/ 代理端和代理服务端之间可用自有格式来实现多路复用以减少连接的建立断开的开销,目前暂未实现代理服务端。 类结构 proxy.rs 负责代理结构的存储,监听类型,监听地址,是否有父级地址,认证账号密码等。 flag.rs 监听类型的二进制结构,…

网络安全 - DDoS 攻击原理 + 实验

DDoS 攻击 什么是 DDoS 进攻 D D o S \color{cyan}{DDoS} DDoS&#xff08;Distributed Denial of Service&#xff0c;分布式拒绝服务&#xff09;攻击是一种通过多个计算机系统同时向目标系统发送大量请求&#xff0c;消耗其资源&#xff0c;使其无法正常服务的攻击方式。DD…

后端高频面试题分享-用Java判断一个列表是否是另一个列表的顺序子集

问题描述 编写一个函数&#xff0c;该函数接受两个列表作为参数&#xff0c;判断第一个列表是否是第二个列表的顺序子集&#xff0c;返回True或False。 要求 判断一个列表是否是另一个列表的顺序子集&#xff0c;即第一个列表的所有元素在第二个列表需要顺序出现。列表中的元…

Linux常用命令及或g++(或gcc)编辑器运用

一. 实验内容 1&#xff0e;打开VMware Workstation虚拟机进入Ubuntu系统&#xff0c;打开终端。 练习使用常用的Linux命令&#xff0c;主要包括如下命令&#xff1a; mkdir, rmdir, cd, pwd, ls, clear, cat, rm等。&#xff08;其中&#xff0c;cat、rm命令请在下面实验内容3…

Navicat和SQLynx产品功能比较二(SQL查询)

数据库管理工具最常用的功能就是SQL的查询&#xff0c;没有之一。本文针对Navicat和SQLynx做了SQL查询相关的性能测试&#xff0c;从测试结果来看&#xff0c;Navicat主要适合开发类的小型数据量需求&#xff0c;SQLynx可以适应大型数据量或小型数据量的需求&#xff0c;用户可…

python-基础篇-函数-是什么

文章目录 定义一&#xff1a;如果在开发程序时&#xff0c;需要某块代码多次执行。为了提高编写的效率以及更好的维护代码&#xff0c;需要把具有独立功能的代码块组织为一个小模块&#xff0c;这就是函数。定义一&#xff1a;我们把一些数据喂给函数&#xff0c;让他内部消化&…

政安晨【零基础玩转各类开源AI项目】解析开源:Stable Diffusion 3 论文及用户界面工具 StableSwarmUI

目录 关键成果 性能 结构细节 通过重新配重改善整形流量 比例整形变换模型 灵活的文本编码器 使用模型&#xff1a;StableSwarmUI 开源项目的现状&#xff1a; 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 零基础玩转各类开源AI…

重生奇迹mu魔剑士简介

出生地&#xff1a;勇者大陆 性 别&#xff1a;男 擅 长&#xff1a;近距离作战、武器特技&攻击魔法使用 转 职&#xff1a;剑圣&#xff08;3转&#xff09; 介 绍&#xff1a;当玩家账号中有一个220级以上的角色时&#xff0c;便可以创建职业为魔剑士的新角色&#x…

关于element-plus中el-select自定义标签及样式的问题

关于element-plus中el-select自定义标签及样式的问题 我这天天的都遇到各种坑&#xff0c;关于自定义&#xff0c;我直接复制粘贴代码都实现不了&#xff0c;研究了一下午&#xff0c;骂骂咧咧了一下午&#xff0c;服气了。官网代码实现不了&#xff0c;就只能 “ 曲线救国 ”…

AI大模型爆发,你还不学就晚了!抓住时代机遇,快速入门指南!

AI大模型风起云涌&#xff0c;你准备好乘风破浪了吗&#xff1f; 在一个阳光明媚的午后&#xff0c;小李坐在自己的工位上&#xff0c;眼前的代码如同繁星般繁多。他是一名资深的软件工程师&#xff0c;但在最近的技术浪潮中&#xff0c;他却感到了一丝不安。他的朋友圈里&…

SAP Build 2-PDF数据提取与决策

0. 安装desktop agent 在后续过程中发现要预先安装desktop agent&#xff0c;否则没法运行自动化流程… 0.1 agent下载 参考官方文档说明 https://help.sap.com/docs/build-process-automation/sap-build-process-automation/create-user-in-rbsc-download-repository?loca…

numpy创建维数组

一&#xff0c;numpy创建一维数组 1.1.np.array() # 创建一维数组 anp.array([1,2,3,4,5]) print(a) 1.2.np.arange() # 创建等差数组 bnp.arange(0,6,2) print(b) 1.3.np.linspace() #生成10个数&#xff0c;范围为[1,10]&#xff0c;满足等差数列 y,cnp.linspace(1,2,3,end…

电商领域利器来了!港大阿里联合提出MimicBrush,对参考图模仿进行零样本图像编辑,万物皆可编辑。

阿里和港大提出的MimicBrush可以通过对参考图模仿进行零样本图像编辑。将一张图片的某一部分融合到领一张图片上去。用在电商商品展示上或者单纯的图片编辑和内容迁移很有用。从官方演示来看效果也很好。 MimicBrush&#xff0c;它会随机选择视频剪辑中的两帧&#xff0c;遮盖其…

远程桌面端口,远程桌面改端口有哪些方法

方法一&#xff1a;通过修改注册表 步骤一&#xff1a;打开注册表编辑器 按下 Windows键R 打开“运行”对话框。输入 regedit 并按 Enter 打开注册表编辑器。 步骤二&#xff1a;定位到远程桌面服务的端口设置 导航至第一个注册表路径&#xff1a;HKEY_LOCAL_MACHINE\SYSTE…

RabbitMQ安装配置,封装工具类,发送消息及监听

1. Get-Started docker安装rabbitmq 拉取镜像 [rootheima ~]# docker pull rabbitmq:3.8-management 3.8-management: Pulling from library/rabbitmq 7b1a6ab2e44d: Pull complete 37f453d83d8f: Pull complete e64e769bc4fd: Pull complete c288a913222f: Pull complet…

VD1011 单节锂离子充电电池保护 2.8V过放保护 SOT-23小封装芯片

VD1011&#xff0c;内置高精度电压检测电路和延迟电路以及内置MOSFET&#xff0c;是用于单节锂离子/锂聚合物可再充电 电池的保护IC。 本IC适合干对1节锂离子/锂聚合物可再充电电池的过充电、过放电和过电流进行保护。 VD1011具备如下特点 高精度电压检测电路 过充电检测电压 …

PyTorch计算机视觉入门:使用自己的数据集训练神经网络

前言 计算机视觉&#xff0c;作为人工智能领域的一个重要分支&#xff0c;近年来在图像识别、物体检测、图像生成等应用上取得了显著的进步。PyTorch&#xff0c;作为一款灵活且强大的深度学习框架&#xff0c;为开发者提供了便捷的工具来构建和训练计算机视觉模型。本文将指导…