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

相关推荐
pjw198809033 分钟前
Spring Framework 中文官方文档
java·后端·spring
lxh01137 分钟前
数据流的中位数
开发语言·前端·javascript
神仙别闹13 分钟前
基于NodeJS+Vue+MySQL实现一个在线编程笔试平台
前端·vue.js·mysql
jgyzl25 分钟前
2026.3.11MyBatis-Plus基本使用与思考
java·数据库·mybatis
Full Stack Developme1 小时前
Java 常用通信协议及对应的框架
java·开发语言
( •̀∀•́ )9201 小时前
Spring Boot 启动报错 `BindException: Permission denied`
java·spring boot·后端
zadyd1 小时前
Workflow or ReAct ?
前端·react.js·前端框架
杰克尼1 小时前
苍穹外卖--day10
java·数据库·spring boot·mybatis·notepad++
sjmaysee1 小时前
Windows操作系统部署Tomcat详细讲解
java·windows·tomcat
1.14(java)3 小时前
Spring-boot快速上手
java·开发语言·javaee