当前位置: 首页 > news >正文

Springboot 导入导出Excel ,一对多关系,复合表格、合并单元格数据

前言

学习是自己的事。

但是跟着我学习,也未尝不可。

这种一对多的导出需求,好像确实也是比较常见的: 

表面拒绝,反手上演一手实战示例。

内容:



① 一对多关系数据 (合并单元格)数据的 导出

②一对多关系数据 (合并单元格)数据的 导入

导入导出一块给整了,直接杀死比赛。

(看官们,收藏起来,以后备用。顺手给我点个赞。)

之前写过一篇极其简单的excel导入导出,是单个文件的:


Springboot 最简单的结合MYSQL数据实现EXCEL表格导出及数据导入_小目标青年的博客-CSDN博客

还写过一篇单个,多个 excel文件导出,转成ZIP包的:

SpringBoot 导出多个Excel文件,压缩成.zip格式下载_小目标青年的博客-CSDN博客
 

还有指定模板导出的:
Springboot 指定自定义模板导出Excel文件_小目标青年的博客-CSDN博客_自定义导出excel


正文

模拟一个这种数据的业务场景:

效果,数据导出:
 

实战:
 

先看看工程目录结构:

pom.xml 引入核心依赖:
 

    <dependencies>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-spring-boot-starter</artifactId>
            <version>4.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

这篇文章核心就是使用easypoi 的 注解

@Excel()

合并单元格、复合表格的关键注解 

@ExcelCollection()

项目小组类

ProjectGroupExcelVO.java

import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelCollection;
import lombok.Data;
import java.util.List;

/**
 * @Author: JCccc
 * @Description:
 * @Date: 1/1/1 1:11
 */
@Data
public class ProjectGroupExcelVO {

    @Excel(name = "小组名称", needMerge = true, width = 20,height = 8)
    private String groupName;

    @Excel(name = "小组口号", needMerge = true, width = 20,height = 8)
    private String groupSlogan;

    @Excel(name = "小组类型", needMerge = true, width = 20,height = 8)
    private String groupType;

    @ExcelCollection(name = "组员信息")
    private List<GroupUserExcelVO> groupUsers;
    
}

简析:

组员的类

GroupUserExcelVO.java

import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;

/**
 * @Author: JCccc
 * @Description:
 * @Date: 1/1/1 1:11
 */
@Data
public class GroupUserExcelVO {

    @Excel(name = "组员名字", width = 20,height = 8)
    private String name;

    @Excel(name = "组员电话", width = 20,height = 8)
    private String phone;

    @Excel(name = "年龄",  width = 20,height = 8)
    private Integer age;

}

导入导出工具类一个

MyExcelUtils.java

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.NoSuchElementException;

/**
 * @Author: JCccc
 * @Description:
 * @Date: 1/1/1 1:11
 */
public class MyExcelUtils {


    /**
     * 功能描述:复杂导出Excel,包括文件名以及表名,不创建表头
     *
     * @param list 导出的实体类
     * @param title 表头名称
     * @param sheetName sheet表名
     * @param pojoClass 映射的实体类
     * @param fileName
     * @param response
     * @return
     */
    public static void exportExcel(	List<?> list, String title, String sheetName, Class<?> pojoClass,
                                       String fileName, HttpServletResponse response) {
        defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName));
    }

    /**
     * 功能描述:默认导出方法
     *
     * @param list 导出的实体集合
     * @param fileName 导出的文件名
     * @param pojoClass pojo实体
     * @param exportParams ExportParams封装实体
     * @param response
     * @return
     */
    private static void defaultExport(	List<?> list, Class<?> pojoClass, String fileName,
                                          HttpServletResponse response, ExportParams exportParams) {
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
        if (workbook != null) {
            downLoadExcel(fileName, response, workbook);
        }
    }

    /**
     * 功能描述:Excel导出
     *
     * @param fileName 文件名称
     * @param response
     * @param workbook Excel对象
     * @return
     */
    private static void downLoadExcel(	String fileName, HttpServletResponse response,
                                          Workbook workbook) {
        try {
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "multipart/form-data");
            response.setHeader("Content-Disposition",
                    "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            workbook.write(response.getOutputStream());

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 功能描述:根据接收的Excel文件来导入Excel,并封装成实体类
     *
     * @param file 上传的文件
     * @param titleRows 表标题的行数
     * @param headerRows 表头行数
     * @param pojoClass Excel实体类
     * @return
     */
    public static <T> List<T> importExcel(	MultipartFile file, Integer titleRows, Integer headerRows,
                                              Class<T> pojoClass) {
        if (file == null) {
            return null;
        }
        ImportParams params = new ImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);
        List<T> list = null;
        try {
            list = ExcelImportUtil.importExcel(file.getInputStream(), pojoClass, params);
        } catch (NoSuchElementException e) {
            throw new RuntimeException("excel文件不能为空");
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());

        }
        return list;
    }
}

导出接口:

TestController.java

import com.jc.excel.excelVO.GroupUserExcelVO;
import com.jc.excel.excelVO.ProjectGroupExcelVO;
import com.jc.excel.util.MyExcelUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: JCccc
 * @Description:
 * @Date: 1/1/1 1:11
 */
@RestController
public class TestController {


    /**
     * excel导出 
     *
     * @return
     */
    @GetMapping(value = "/exportTest")
    public void export(HttpServletResponse response) {


        List<ProjectGroupExcelVO> projectGroupList=new ArrayList<>();

        //小组A数据模拟
        ProjectGroupExcelVO groupA=new ProjectGroupExcelVO();
        groupA.setGroupName("小组A");
        groupA.setGroupSlogan("天天向上,爱学习!");
        groupA.setGroupType("奋斗类型");
        List<GroupUserExcelVO> groupUserAList=new ArrayList<>();
        GroupUserExcelVO groupUser1=new GroupUserExcelVO();
        groupUser1.setName("小收");
        groupUser1.setPhone("123456");
        groupUser1.setAge(18);

        GroupUserExcelVO groupUser2=new GroupUserExcelVO();
        groupUser2.setName("小藏");
        groupUser2.setPhone("654321");
        groupUser2.setAge(20);
        groupUserAList.add(groupUser1);
        groupUserAList.add(groupUser2);
        groupA.setGroupUsers(groupUserAList);


        //小组B数据模拟
        ProjectGroupExcelVO groupB=new ProjectGroupExcelVO();
        groupB.setGroupName("小组B");
        groupB.setGroupSlogan("跟着JC学java,稳!");
        groupB.setGroupType("努力类型");
        List<GroupUserExcelVO> groupBUserBList=new ArrayList<>();
        GroupUserExcelVO groupUserB1=new GroupUserExcelVO();
        groupUserB1.setName("小点");
        groupUserB1.setPhone("123456");
        groupUserB1.setAge(12);

        GroupUserExcelVO groupUserB2=new GroupUserExcelVO();
        groupUserB2.setName("小赞");
        groupUserB2.setPhone("654321");
        groupUserB2.setAge(15);

        GroupUserExcelVO groupUserB3=new GroupUserExcelVO();
        groupUserB3.setName("JCccc");
        groupUserB3.setPhone("136919xxxxx");
        groupUserB3.setAge(10000);

        groupBUserBList.add(groupUserB1);
        groupBUserBList.add(groupUserB2);
        groupBUserBList.add(groupUserB3);
        groupB.setGroupUsers(groupBUserBList);
        
        projectGroupList.add(groupA);
        projectGroupList.add(groupB);
        
        
        String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss"));
       
        MyExcelUtils.exportExcel(projectGroupList,
                "小组信息",
                "小组信息",
                ProjectGroupExcelVO.class,
                "小组信息文件"+time+".xls",response);



    }

}

调用一下看看导出的效果:
 

 非常OK:

接下来是导入,写个简单接口玩一下:

数据:

导入 接口代码:
 

    /**
     * excel导入
     *
     * @return
     */
    @PostMapping(value = "/importTest")
    public void importTest( @RequestParam("file") MultipartFile file) {
        List<ProjectGroupExcelVO> projectGroupExcelVOList = MyExcelUtils.importExcel(file, 1, 2, ProjectGroupExcelVO.class);

        System.out.println(projectGroupExcelVOList.toString());

        System.out.println("-----------------------------------");

        System.out.println("写入数据库");
    }

调用看看效果:

 导入成功,就是如此简单。

相关文章:

  • 怎么清晰地理解、表达 IaaS 、 PaaS 、 SaaS ?
  • UML类图的六大关系,最佳学习理解方式
  • Springboot 整合 Socket 实战案例 ,实现 单点发送、广播群发,1对1,1对多
  • Springboot Mybatis 、JPA 调用存储过程,实战教程
  • 写代码的七八九十宗罪,多图、胆小慎入!
  • Springboot byte[] 转 MultipartFile ,InputStream 转 MultipartFile
  • Springboot 最细节全面的接口传参接参介绍,总有你喜欢的一种方式
  • Springboot 整合RabbitMq ,用心看完这一篇就够了
  • 用过Apifox这个API接口工具后,确实感觉postman有点鸡肋......
  • ClickHouse 挺快,esProc SPL 更快
  • 苹果6sp内存可以扩展吗_饮用苹果醋可以减肥吗?
  • tcpdump抓两个网卡的包_Kubernetes 疑难杂症排查分享:神秘的溢出与丢包
  • 使用vim的重不重要_如何优雅地使用 Vim?
  • hbase 使用disruptor_HBase和Kryo混合使用时出现的jar包冲突
  • mediacodec延时_ijkplayer播放rtsp流卡顿、延迟问题解决
  • 【跃迁之路】【477天】刻意练习系列236(2018.05.28)
  • 10个最佳ES6特性 ES7与ES8的特性
  • C++入门教程(10):for 语句
  • EOS是什么
  • exif信息对照
  • iOS 颜色设置看我就够了
  • Iterator 和 for...of 循环
  • java 多线程基础, 我觉得还是有必要看看的
  • JS 面试题总结
  • JS进阶 - JS 、JS-Web-API与DOM、BOM
  • laravel with 查询列表限制条数
  • Linux快速复制或删除大量小文件
  • MQ框架的比较
  • python 学习笔记 - Queue Pipes,进程间通讯
  • 从零开始的无人驾驶 1
  • 个人博客开发系列:评论功能之GitHub账号OAuth授权
  • 快速构建spring-cloud+sleuth+rabbit+ zipkin+es+kibana+grafana日志跟踪平台
  • 嵌入式文件系统
  • 实战:基于Spring Boot快速开发RESTful风格API接口
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • 小程序开发之路(一)
  • 学习HTTP相关知识笔记
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • HanLP分词命名实体提取详解
  • 如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes ...
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (4)Elastix图像配准:3D图像
  • (pojstep1.1.2)2654(直叙式模拟)
  • (八)c52学习之旅-中断实验
  • (二十五)admin-boot项目之集成消息队列Rabbitmq
  • (三)Hyperledger Fabric 1.1安装部署-chaincode测试
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • (转)Mysql的优化设置
  • ./include/caffe/util/cudnn.hpp: In function ‘const char* cudnnGetErrorString(cudnnStatus_t)’: ./incl
  • .net 4.0 A potentially dangerous Request.Form value was detected from the client 的解决方案
  • .net core 6 使用注解自动注入实例,无需构造注入 autowrite4net
  • .net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法
  • .net mvc 获取url中controller和action
  • .net mvc部分视图
  • .NET 中让 Task 支持带超时的异步等待