EasyExcel:让Excel操作变得简单优雅

前言

在Java开发中,处理Excel文件是一个常见的需求。无论是数据导入导出、报表生成,还是批量数据处理,Excel操作都是不可避免的。传统的POI库虽然功能强大,但使用起来相对复杂,而且在处理大量数据时容易出现内存溢出问题。今天要介绍的EasyExcel,正是为了解决这些痛点而生的优秀框架。

什么是EasyExcel?

EasyExcel是阿里巴巴开源的一个基于Java的Excel处理工具,它重写了POI对Excel的解析,能够原本一个3M的Excel用POI sax解析依然需要100M左右内存,改用EasyExcel可以降低到几M,并且再大的Excel也不会出现内存溢出的情况。

主要特性

  • 内存占用低:避免OOM(内存溢出)

  • 使用简单:基于注解的模式,代码简洁

  • 功能丰富:支持读写、样式设置、数据验证等

  • 性能优越:处理速度快,支持大文件操作

快速上手

添加依赖

首先在项目中添加EasyExcel依赖:

复制代码
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.3.2</version>
</dependency>

创建数据模型

使用注解定义Excel表格结构:

复制代码
public class User {
    @ExcelProperty("用户ID")
    private Long id;
    
    @ExcelProperty("用户名")
    private String username;
    
    @ExcelProperty("邮箱")
    private String email;
    
    @ExcelProperty(value = "注册时间", converter = LocalDateTimeConverter.class)
    private LocalDateTime createTime;
    
    // 构造方法、getter、setter省略
}

核心功能示例

1. 读取Excel文件

复制代码
public class ExcelReader {
    
    public void readExcel() {
        String fileName = "user_data.xlsx";
        
        // 简单读取
        EasyExcel.read(fileName, User.class, new UserDataListener())
                .sheet()
                .doRead();
    }
}
​
// 数据监听器
public class UserDataListener extends AnalysisEventListener<User> {
    
    @Override
    public void invoke(User user, AnalysisContext context) {
        // 处理每一行数据
        System.out.println("读取到用户:" + user.getUsername());
        // 可以进行数据验证、入库等操作
    }
    
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        System.out.println("所有数据解析完成!");
    }
}

2. 写入Excel文件

复制代码
public class ExcelWriter {
    
    public void writeExcel() {
        String fileName = "output_users.xlsx";
        
        // 准备数据
        List<User> users = getUserList();
        
        // 写入Excel
        EasyExcel.write(fileName, User.class)
                .sheet("用户信息")
                .doWrite(users);
    }
    
    private List<User> getUserList() {
        List<User> users = new ArrayList<>();
        users.add(new User(1L, "张三", "zhangsan@example.com", LocalDateTime.now()));
        users.add(new User(2L, "李四", "lisi@example.com", LocalDateTime.now()));
        return users;
    }
}

3. 自定义样式

复制代码
// 自定义样式写入
EasyExcel.write(fileName, User.class)
    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 自适应列宽
    .registerWriteHandler(getHorizontalCellStyleStrategy()) // 自定义样式
    .sheet("用户信息")
    .doWrite(users);
​
private HorizontalCellStyleStrategy getHorizontalCellStyleStrategy() {
    // 头部样式
    WriteCellStyle headWriteCellStyle = new WriteCellStyle();
    headWriteCellStyle.setFillForegroundColor(IndexedColors.BLUE.getIndex());
    WriteFont headWriteFont = new WriteFont();
    headWriteFont.setFontHeightInPoints((short) 12);
    headWriteFont.setBold(true);
    headWriteCellStyle.setWriteFont(headWriteFont);
    
    // 内容样式
    WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
    contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
    
    return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
}

高级特性

数据验证

复制代码
public class User {
    @ExcelProperty("用户名")
    @NotBlank(message = "用户名不能为空")
    private String username;
    
    @ExcelProperty("邮箱")
    @Email(message = "邮箱格式不正确")
    private String email;
    
    @ExcelProperty("年龄")
    @Min(value = 0, message = "年龄不能小于0")
    @Max(value = 150, message = "年龄不能大于150")
    private Integer age;
}

动态表头

复制代码
// 动态生成表头
List<List<String>> head = new ArrayList<>();
head.add(Arrays.asList("用户信息", "基本信息", "ID"));
head.add(Arrays.asList("用户信息", "基本信息", "姓名"));
head.add(Arrays.asList("用户信息", "联系方式", "邮箱"));
​
EasyExcel.write(fileName)
    .head(head)
    .sheet("动态表头")
    .doWrite(data);

最佳实践

1. 处理大文件

复制代码
// 使用分批处理避免内存问题
public class BatchUserDataListener extends AnalysisEventListener<User> {
    private static final int BATCH_COUNT = 1000;
    private List<User> cachedDataList = new ArrayList<>();
    
    @Override
    public void invoke(User user, AnalysisContext context) {
        cachedDataList.add(user);
        
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            cachedDataList.clear();
        }
    }
    
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        saveData();
    }
    
    private void saveData() {
        // 批量保存数据
        userService.saveBatch(cachedDataList);
    }
}

2. 异常处理

复制代码
try {
    EasyExcel.read(fileName, User.class, new UserDataListener())
            .sheet()
            .doRead();
} catch (Exception e) {
    log.error("Excel读取失败:{}", e.getMessage(), e);
    throw new BusinessException("文件解析失败,请检查文件格式");
}

总结

EasyExcel作为一个优秀的Excel处理框架,具有以下优势:

  1. 简单易用:基于注解的配置方式,降低学习成本

  2. 性能优异:内存占用低,处理速度快

  3. 功能全面:支持读写、样式、验证等多种特性

  4. 扩展性强:提供丰富的自定义接口

无论是简单的数据导入导出,还是复杂的报表生成,EasyExcel都能提供优雅的解决方案。在实际项目中,建议结合业务需求选择合适的使用方式,并注意异常处理和性能优化。

通过本文的介绍,相信你已经对EasyExcel有了基本的了解。更多高级用法和特性,建议查阅官方文档进行深入学习。让我们一起用EasyExcel让Excel操作变得更加简单高效!

相关推荐
计算机毕设指导63 小时前
基于SpringBoot校园学生健康监测管理系统【源码文末联系】
java·spring boot·后端·spring·tomcat·maven·intellij-idea
mysuking3 小时前
springboot与springcloud对应版本
java·spring boot·spring cloud
希望永不加班3 小时前
SpringBoot 数据库连接池配置(HikariCP)最佳实践
java·数据库·spring boot·后端·spring
迈巴赫车主3 小时前
蓝桥杯3500阶乘求和java
java·开发语言·数据结构·职场和发展·蓝桥杯
身如柳絮随风扬3 小时前
Lambda、方法引用与Stream流完全指南
java·开发语言
yaoyouzhong3 小时前
基于SpringBoot和PostGIS的云南与缅甸的千里边境线实战
java·spring boot·spring
前端精髓4 小时前
移除 Effect 依赖
前端·javascript·react.js
姗姗的鱼尾喵4 小时前
Spring/SpringBoot 面试高频(含IOC/AOP/事务)
java·spring boot·面试
码云之上4 小时前
从一个截图函数到一个 npm 包——pdf-snapshot 的诞生记
前端·node.js·github
Mr_Xuhhh4 小时前
从理论到实践:深入理解算法的时间与空间复杂度
java·开发语言·算法