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

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>

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

高考志愿填报,选专业应该考虑哪些因素?

这是一个复杂的社会&#xff0c;各种影响就业的因素层出不穷&#xff0c;也从未断绝。对于高考生而言&#xff0c;高考刚结束&#xff0c;短暂的放松后&#xff0c;就必须考虑自身以后应该就读什么专业&#xff0c;如果不对就读专业进行评估&#xff0c;仔细挑选&#xff0c;毕…

【设计模式深度剖析】【8】【行为型】【备忘录模式】| 以后悔药为例加深理解

&#x1f448;️上一篇:观察者模式 设计模式-专栏&#x1f448;️ 文章目录 备忘录模式定义英文原话直译如何理解呢&#xff1f; 3个角色1. Memento&#xff08;备忘录&#xff09;2. Originator&#xff08;原发器&#xff09;3. Caretaker&#xff08;负责人&#xff09;类…

每日一题——Python实现PAT乙级1028 人口普查 Keyboard(举一反三+思想解读+逐步优化)六千字好文

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 题目链接​编辑我的写法 专业点评 时间复杂度分析 空间复杂度分析 总结 我要更强…

Star-CCM+自动网格执行方法与设置技巧

在Star中进行一个仿真项目时,有时会创建多个自动网格。网格创建结束后需要执行。在Star中,网格执行可以分为三种。分别是:单独执行操作;多个执行操作;全部执行操作。接下来将三种执行操作的方法与步骤进行介绍。 其次,如果不习惯用自定义控制网格,有时在一个项目中就会…

认识一些分布函数-Gumbel分布

1. Gumbel分布 Gumbel分布(也称为古贝尔型)是一种常用的非对称极值分布( Extreme Value Distribution,EVD),用于建模极大值和极小值,也就是所谓的EVD Type I分布。例如,EVD Type I 被用来预测地震、洪水和其他自然灾害,以及在风险管理中建模操作风险和那些在一定年龄…

关于阿里云效流水线自动部署项目教程

1、登录阿里云效:阿里云登录 - 欢迎登录阿里云&#xff0c;安全稳定的云计算服务平台 2、点击左侧流水线&#xff1a; 3、在流水线界面&#xff0c;新建流水线 4、我的是php代码&#xff0c;因此选择php模版 5、创建之后添加流程线源&#xff0c;如下图 6、选择相应的源头。比…

eclipse中报出Invaild project path

一、问题&#xff1a; 二、提示分析&#xff1a; 资源路径位置类型无效的项目路径&#xff1a;找到重复的路径条目 项目路径中有一个名为"/eclipse_rtt_demo"的条目被多次定义&#xff0c;这在Eclipse的构建路径设置中是不允许的。这个重复的条目既被标记为系统包含…

Studio One软件最新版下载及详细安装教程

Studio One 6是一款功能丰富、专业级的音乐制作软件&#xff0c;它具备灵活的工作流程和高效的团队协作能力&#xff0c;能帮助用户实现高质量的音乐创作和制作。 智能模板更快的启动&#xff0c;全新的智能模板为你手头的任务提供了必要的工具集&#xff0c;包括基本录制、混音…

【个人云盘连接助手】解决多个用户账号无法同时映射到本地磁盘问题

问题 家里买了个联想个人云盘&#xff0c;但是使用SAMBA映射到windows本地磁盘时&#xff0c;每次只能连接到一个账户上&#xff0c;于是想着写个小工具&#xff0c;方便切换多个用户账户&#xff0c;自动映射到本地磁盘 开发简介 开发语言&#xff1a;python 主要实现功能&…

训练营第三十六天| 337.打家劫舍 III121. 买卖股票的最佳时机

337.打家劫舍 III 力扣题目链接(opens new window) 在上次打劫完一条街道之后和一圈房屋后&#xff0c;小偷又发现了一个新的可行窃的地区。这个地区只有一个入口&#xff0c;我们称之为“根”。 除了“根”之外&#xff0c;每栋房子有且只有一个“父“房子与之相连。一番侦察…

工业屏:千万不要以为电脑显示啥样,工业屏就啥样,注意色差。

重要的事情说三遍&#xff1a;一定要放到实际场景下调色&#xff0c;定要放到实际场景下调色&#xff0c;定要放到实际场景下调色。 工业控制屏的色域通常比普通电脑显示器要小。工业控制屏主要用于工业环境中&#xff0c;需要满足特定行业的需求和标准。由于工业控制屏的设计…

深度剖析淘宝扭蛋机源码:打造趣味性电商活动的秘诀

在当今电商市场中&#xff0c;如何吸引用户的注意力、提升用户的参与度成为了各大电商平台竞相追求的目标。淘宝扭蛋机作为一种新型的电商活动形式&#xff0c;以其趣味性和互动性深受用户喜爱。本文将深度剖析淘宝扭蛋机源码&#xff0c;探讨其如何打造趣味性与互动性并存的电…

可视化图表走起来(1):桑基图,一目了然数据流向。

从事可视化设计&#xff0c;什么时候选用什么样的图表非常重要&#xff0c;今天来介绍一下桑基图的定义、场景、数据项等等&#xff0c;贝格前端工场愿意与各位老铁一道成长。 一、桑基图的定义 桑基图&#xff08;Sankey diagram&#xff09;是一种特殊类型的可视化图表&…

深入解析 Spring Cloud Sentinel:分布式系统流量控制与熔断降级的全面指南

&#x1f4e2;&#x1f4e2;&#x1f4e2; 深入解析 Spring Cloud Sentinel&#xff1a;分布式系统流量控制与熔断降级的全面指南 Spring Cloud Sentinel 是阿里巴巴开源的一款强大的分布式系统流量防卫组件&#xff0c;专为微服务架构设计&#xff0c;提供流量控制、熔断降级…

【Spring6】13-19章 JdbcTemplate+代理模式+AOP+Spring事务+Spring集成MyBatis

十三、JdbcTemplate JdbcTemplate是Spring提供的一个JDBC模板类&#xff0c;是对JDBC的封装&#xff0c;简化JDBC代码。 当然&#xff0c;你也可以不用&#xff0c;可以让Spring集成其它的ORM框架&#xff0c;例如&#xff1a;MyBatis、Hibernate等。 接下来我们简单来学习一下…

【LVGL】Guider 界面分析

文章目录 前言架构创建 UI切换界面空间释放分析创建页面空间变化 前言 分析Gui Guider-1.7.2-GA 生成的 LVGL 界面切换&#xff0c;资源管理等处理 架构 所有控件存放于同一个结构体 lv_ui 内&#xff0c;每个页面都至少包含 screen_xxx 和 screen_xxx_del 两个成员 typede…

Cask ‘oraclexxx‘ is unavailable: No Cask with this name exists.

brew search oracle-jdk或brew search --cask oracle-jdk 原因&#xff1a;Homebrew官方仓库不再维护多个旧版本的OracleJDK 不推荐使用Homebrew环境安装JDK //指定版本安装 brew install --cask temurin17 //设置 JAVA_HOME 环境变量 //找到安装的JDK 版本的路径 /usr/lib…

大数据可视化电子沙盘:前端技术的全新演绎

随着大数据时代的到来&#xff0c;数据可视化成为了一个重要的技术趋势。数据可视化不仅可以让复杂的数据变得更加直观易懂&#xff0c;还能帮助我们更好地分析和理解数据。在本文中&#xff0c;我们将深入探讨一种基于HTML/CSS/Echarts等技术的大数据可视化电子沙盘&#xff0…

MAC系统下安装VUE

下载node.js 点击链接 选择图片中的稳定版本 安装node.js 打开终端&#xff0c;输入 node -v 和 npm -v 显示如上信息表示安装成功 安装vue脚手架&#x1f527; sudo npm install -g vue/cli查看vue版本 vue -V6. 启动项目 1 采用 图形页面方式 控制台输入&#xff…

前端菜鸡流水账日记 -- Pagination分页

哈喽哇大家&#xff0c;老规矩&#xff0c;见面先问好&#xff0c;今天是端午节假期后的第一天上班&#xff0c;大家假期开心吗&#xff0c;哈哈哈哈&#xff0c;我还是蛮开心的... 今天这篇笔记要分享得主要是一个分页器&#xff0c;但是不一样得地方是因为&#xff0c;首先是…