SpringBoot中java操作excel【EasyExcel】

这篇具有很好参考价值的文章主要介绍了SpringBoot中java操作excel【EasyExcel】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

EasyExcel 处理Excel;简单记录,方便日后查询!

  • 官方文档: Easy Excel (alibaba.com)

一、EasyExcel概述

Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。
easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析依然需要100M左右内存,改用easyexcel可以降低到几M,并且再大的excel也不会出现内存溢出;03版依赖POI的sax模式,在上层做了模型转换的封装,让使用者更加简单方便

二、导入依赖

以 SpringBoot项目为例

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.6.7</version>
</dependency>
<!-- easyexcel -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.3.2</version>
</dependency>
<dependency>
    <groupId>com.alibaba.fastjson2</groupId>
    <artifactId>fastjson2</artifactId>
    <version>2.0.3</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.24</version>
</dependency>

三、读Excel

1、测试数据

test.xlsx 读取该表中数据;文件放入 resources 目录下

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

2、创建实体类

所有字段都用 String 类型来接收,接收后可以自行转换

@Data
public class DemoData {
    @ExcelProperty("日期")
    private String date;
    @ExcelProperty("名称")
    private String name;
    @ExcelProperty("数量")
    private String num;
}

3、读取监听器

@Slf4j
public class MyReadListener implements ReadListener<DemoData> {
    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(DemoData data, AnalysisContext context) {
        //log.info("解析到一条数据:{}", JSON.toJSONString(data));
        System.out.println(data.getDate() + " - " + data.getName() + " - " + data.getNum());
    }
    
    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        log.info("所有数据解析完成!");
    }
}    

4、读取类

@Slf4j
@Component
public class ExcelUtil {
    /**
     * <p>
     * 1. 创建excel对应的实体对象
     * <p>
     * 2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器
     * <p>
     * 3. 直接读即可
     */
    @SneakyThrows
    public static void simpleRead() {
        // 有个很重要的点 MyReadListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
        // 写法3:
        File file = ResourceUtils.getFile("classpath:test.xlsx");
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
        EasyExcel.read(file, DemoData.class, new MyReadListener())
                .sheet()
            	// 默认头部是1行;该测试数据中是2行
                .headRowNumber(2)
                .doRead();
    }
}    

5、测试运行

public class MyTest {
    public static void main(String[] args) {
        ExcelUtil.simpleRead();
    }
}

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

6、日期转换

在监听器中添加 DateTimeFormatter

@Slf4j
public class MyReadListener implements ReadListener<DemoData> {
    static DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd");

    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(DemoData data, AnalysisContext context) {
        //log.info("解析到一条数据:{}", JSON.toJSONString(data));
        String date = data.getDate();
        LocalDate localDate = LocalDate.parse(date, dtf);
        System.out.println(localDate + " - " + data.getName() + " - " + data.getNum());
    }
}    
  • 运行测试!转换出错 java.time.format.DateTimeParseException

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

原因:测试数据中日期不规范;月份或天数如果是一位时,前面要补0;

期望的格式是:yyyy/MM/dd

建议要读取的excel文件中所有单元格格式都是文本形式;

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

修改测试数据,重新测试。更新测试数据后,要 clean 项目后再测试;

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

7、过滤脏数据

在监听器中加入异常处理

	/**
     * 在转换异常 获取其他异常下会调用本接口。抛出异常则停止读取。如果这里不抛出异常则 继续读取下一行。
     *
     * @param exception
     * @param context
     * @throws Exception
     */
    @Override
    public void onException(Exception exception, AnalysisContext context) {
        log.error("解析失败,但是继续解析下一行:{}", exception.getMessage());
        // 如果是某一个单元格的转换异常 能获取到具体行号
        // 如果要获取头的信息 配合invokeHeadMap使用
        if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;
            log.error("第{}行,第{}列解析异常,数据为:{}", excelDataConvertException.getRowIndex(),
                      excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData());
        }
    }
  • 重新读取测试

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

8、解析成功后统一输出

把解析成功数据先存入集合中,最后统一处理;

修改监听器类

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

9、官方格式转换(推荐)

1> 原理剖析

(个人理解)EasyExcel 会把每个单元格中的数据都当成 String 来读取,再通过各种转换器,转换成需要的类型(实体类中定义的类型),如果转换失败,就抛出异常。在 easyexcel-core-xxx.jar 中有大量的转换器

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

格式转换中容易出问题的是日期格式;

以日期转换为例;

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

2> 测试

  • 修改实体类;把日期类型由 String 改为 LocalDate

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

  • 监听器中直接获取LocalDate字段值;让系统自动进行格式转换

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

  • 运行测试

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

全部解析失败;原因很简单:系统默认期望的日期格式为 yyyy-MM-dd,而测试数据中的日期格式为 yyyy/MM/dd,二者不一致

3> @DateTimeFormat(“…”)

在实体类的日期字段上添加 @DateTimeFormat("yyyy/MM/dd") 注解;与测试数据中的日期格式一致。

如果测试数据中的日期格式与官方默认格式一致,可以省略。

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

  • 运行测试

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

四、写Excel

1、目标数据表

期望生成如下数据表

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

  • 复杂表头:多行、字体、颜色、行高、列宽
  • 指定数据格式:日期 yyyy年MM月dd日 ,百分比#.##% 最多二位

2、实体类

WriteDemoData 关键类;

数据表中的样式都在这里面定义

  • fillForegroundColor 为颜色枚举类中的颜色索引值 IndexedColors.RED.getIndex()
  • @DateTimeFormat(“yyyy年MM月dd日”) 为生成后的日期格式
  • @NumberFormat(“#.##%”) 数字格式
@Getter
@Setter
@EqualsAndHashCode
// 头背景设置成红色 IndexedColors.RED.getIndex()
@HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 10)
// 头字体设置成16
@HeadFontStyle(fontHeightInPoints = 16)
// 内容的背景设置成绿色 IndexedColors.GREEN.getIndex()
//@ContentStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 17)
// 内容字体设置成11
//@ContentFontStyle(fontHeightInPoints = 11)
// 内容行高
@ContentRowHeight(20)
// 头部行高
@HeadRowHeight(25)
// 列宽
@ColumnWidth(10)
@AllArgsConstructor
public class WriteDemoData {
    @ExcelProperty({"主标题", "二级主标题", "日期"})
    @DateTimeFormat("yyyy年MM月dd日")
    @ColumnWidth(20)
    private LocalDate date;
    // 字符串的头背景设置成粉红 IndexedColors.PINK.getIndex()
    //@HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 14)
    // 字符串的头字体设置成20
    //@HeadFontStyle(fontHeightInPoints = 30)
    // 字符串的内容的背景设置成天蓝 IndexedColors.SKY_BLUE.getIndex()
    //@ContentStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 40)
    // 字符串的内容字体设置成20
    //@ContentFontStyle(fontHeightInPoints = 30)
    @ExcelProperty({"主标题", "二级主标题", "名称"})
    private String name;

    @ExcelProperty({"主标题", "二级主标题", "份额"})
    @NumberFormat("#.##%")
    private Double num;
}

3、目标数据

@Slf4j
public class ExcelUtil {
    /**
     * 测试数据
     *
     * @return
     */
    private static List<WriteDemoData> data() {
        List<WriteDemoData> list = new ArrayList<>();
        list.add(new WriteDemoData(LocalDate.parse("2023-07-09"), "张三", 0.1525));
        list.add(new WriteDemoData(LocalDate.parse("2023-07-10"), "李四", 0.2650));
        list.add(new WriteDemoData(LocalDate.parse("2023-07-11"), "王五", 0.1385));
        list.add(new WriteDemoData(LocalDate.parse("2023-07-12"), "小刘", 0.1723));
        list.add(new WriteDemoData(LocalDate.parse("2023-07-13"), "小李", 0.3652));
        list.add(new WriteDemoData(LocalDate.parse("2023-07-14"), "小陈", 0.1234));
        list.add(new WriteDemoData(LocalDate.parse("2023-07-15"), "小赵", 0.863));
        list.add(new WriteDemoData(LocalDate.parse("2023-07-16"), "小可", 0.1329));
        list.add(new WriteDemoData(LocalDate.parse("2023-07-17"), "小钱", -0.1560));
        return list;
    }
}

LocalDate.parse(“2023-07-09”) 中的日期格式与系统默认的格式一致,parse时可以省略DateTimeFormatter

4、写入文件

@Slf4j
public class ExcelUtil {
    @SneakyThrows
    public static void write() {
        // 类路径目录
        Resource resource = new ClassPathResource("");
        String resourceDir = resource.getFile().getAbsolutePath();

        File file = new File(resourceDir, "test_" + System.currentTimeMillis() + ".xlsx");

        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        EasyExcel.write(file, WriteDemoData.class).sheet("模板").doWrite(data());
    }
}

5、运行测试

public class MyTest {
    public static void main(String[] args) {
        ExcelUtil.write();
    }
}

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

6、自定义表头

如果表头随内容而变化,需要在生成表的时候才能确定,如下图

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

1> 修改实体类

去掉原来实体类中注解定义的表头

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

2> 准备表头数据

	/**
     * 动态表头
     * @return
     */
    private static List<List<String>> head() {
        String mainTitle = "自定义主标题";
        String secondTitle = "自定义二级标题";
        
        List<List<String>> list = new ArrayList<>();
        
        List<String> head0 = new ArrayList<>();
        head0.add(mainTitle);
        head0.add(secondTitle);
        head0.add("日期");

        List<String> head1 = new ArrayList<>();
        head1.add(mainTitle);
        head1.add(secondTitle);
        head1.add("名称");

        List<String> head2 = new ArrayList<>();
        head2.add(mainTitle);
        head2.add(secondTitle);
        head2.add("份额");

        list.add(head0);
        list.add(head1);
        list.add(head2);
        return list;
    }

表头整体上是一个list,list中元素又是list,内部的每个list表示表头中的一列,表头有几行,内部list中就有几个元素

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

3> 写数据

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel

4> 运行测试

SpringBoot中java操作excel【EasyExcel】,# SpringBoot,Java,# Spring及MVC,java,spring boot,excel文章来源地址https://www.toymoban.com/news/detail-608791.html

到了这里,关于SpringBoot中java操作excel【EasyExcel】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java配置方式使用Spring MVC

    上一节,我们学习了如何基于XML配置与注解的方式使用Spring MVC,涉及到三个XML配置文件:Spring配置文件(spring-config.xml)、Spring MVC配置文件(spring-mvc-config.xml)、Web部署描述文件(web.xml),这一节,我们通过案例学习如何基于Java配置类与注解的方式使用Spring MVC,只有Java配

    2024年02月05日
    浏览(22)
  • 【Java EE】关于Spring MVC 响应

    在博主前面写的博客 【Java EE】Spring请求如何传递参数详解 中我们已经设置了响应数据,Http响应结果可以是数据,也可以是静态⻚⾯,也可以针对响应设置状态码, Header信息等 首先我们像创建一个静态界面,创建位置如下: 前端代码如下: 不过这里的后端的代码和以前的代码

    2024年04月14日
    浏览(24)
  • spring boot导入导出excel,集成EasyExcel

    一、安装依赖 二、新建导出工具类 三、新建实体类 @ExcelProperty: 核心注解,value属性可用来设置表头名称,converter属性可以用来设置类型转换器; @ColumnWidth: 用于设置表格列的宽度; @DateTimeFormat: 用于设置日期转换格式; @NumberFormat: 用于设置数字转换格式。 四、如果需

    2024年02月06日
    浏览(32)
  • 【Java 中级】一文精通 Spring MVC - 上传(十)

    👉 博主介绍 : 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO 专家博主 ⛪️ 个人社区:个人社区 💞 个人主页:个人主页 🙉 专栏地址: ✅ Java 高阶 🙉八股文专题:剑指大厂,手撕

    2024年02月11日
    浏览(24)
  • 【Java EE】初识Spring Web MVC

    Spring Web MVC 是 基于 Servlet API 构建的原始 Web 框架 ,从⼀开始就包含在Spring框架中。它的正式名称“Spring Web MVC”来⾃其源模块的名称(Spring-webmvc),但它通常被称为)Spring MVC). Servlet是⼀种实现动态⻚⾯的技术.准确来讲Servlet是⼀套Java Web 开发的规范,或者说是⼀套Java Web 开发的

    2024年04月10日
    浏览(33)
  • Java配置方式使用Spring MVC:实战练习

    承接上文《Java配置方式使用Spring MVC》 登录页面 - login.jsp 注:这个页面没有JSP代码,其实可以做成静态页面 - login.html 登录成功页面 - success.jsp(必须是动态页面,因为要获取会话对象中的数据) 如果不用JSP的标签库,要获取会话中的数据,要复杂一点 登录失败页面 - failu

    2024年02月05日
    浏览(36)
  • java spring MVC之RESTful快速开发

    我这里有个一springboot项目 我在启动类同目录下创建了一个目录 目录名叫 controller 里面有一个UserController diam结构是这样的 这是一个基础的REST风格风格开发 但其实 我们可以很大程度的简化 这里 我先启动项目 然后用Postman测试 这些都是可以正常访问 和 调用返回的 确认无误之

    2024年02月05日
    浏览(24)
  • 网页版Java(Spring/Spring Boot/Spring MVC)五子棋项目(四)对战模块

    匹配成功返回数据 1. message消息类别 2. ok 3. reson 4. 房间id 5. 双方id 6.白色玩家 一个类记录房间中的信息(房间id,两个用户id,是否为白棋) 信息提示框 处理匹配API 初始化游戏(棋盘,下一个棋子,接受棋子处理响应,判断是否结束) 1. 客户端连接到游戏房间后, 服务器返回

    2024年02月13日
    浏览(28)
  • 【Java 高阶】一文精通 Spring MVC - 基础概念(一)

    👉 博主介绍 : 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO 专家博主 ⛪️ 个人社区:个人社区 💞 个人主页:个人主页 🙉 专栏地址: ✅ Java 高阶 🙉八股文专题:剑指大厂,手撕

    2024年02月11日
    浏览(26)
  • 探索Java中最常用的框架:Spring、Spring MVC、Spring Boot、MyBatis和Netty

    🎉欢迎来到Java面试技巧专栏~探索Java中最常用的框架:Spring、Spring MVC、Spring Boot、MyBatis和Netty ☆* o(≧▽≦)o *☆嗨~我是IT·陈寒🍹 ✨博客主页:IT·陈寒的博客 🎈该系列文章专栏:Java面试技巧 📜其他专栏:Java学习路线 Java面试技巧 Java实战项目 AIGC人工智能 数据结构学习

    2024年02月08日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包