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操作变得更加简单高效!

相关推荐
爱学习的小可爱卢1 小时前
JavaSE基础-Java字符串转整数与拼接实战指南
java·开发语言
GISer_Jing1 小时前
从零到架构师:Taro 全链路学习与实战指南
前端·react.js·taro
phltxy1 小时前
快速上手 ElementPlus:核心用法精讲
前端·javascript·vue.js
星辰_mya1 小时前
Kafka Producer 发送慢 → TPS 骤降 90%
java·数据库·kafka
SuperEugene2 小时前
数组的 10 个常用操作:map / filter / reduce 实战套路
前端·javascript
晓得迷路了2 小时前
栗子前端技术周刊第 117 期 - TypeScript 6.0 Beta、webpack 2026 年路线图、React 最新生态调查报告结果...
前端·javascript·react.js
摇滚侠2 小时前
bootstrap 框架讲解-快速上手,最适合后端开发人员的bootstrap 保姆级使用教程
前端·bootstrap·html
网小鱼的学习笔记2 小时前
leetcode283移动零元素
java·开发语言·算法
自在极意功。2 小时前
Spring Boot 自动配置原理基本理解
java·spring boot·后端·自动配置原理