EasyExcel怎么使用?

wen python案例 3

本文目录导读:

EasyExcel怎么使用?

  1. EasyExcel 简介
  2. 快速入门:写 Excel
  3. 读 Excel
  4. 高级用法
  5. 性能优化建议
  6. 常见问题解决

下面我为你详细介绍 EasyExcel 的使用方法,这是阿里开源的一个非常好用的 Java Excel 工具库,特别适合处理大数据量、内存占用低的场景。

EasyExcel 简介

核心优势:

  • 内存占用极低(相比 POI,能节省 90% 以上)
  • 使用简单,API 友好
  • 支持大数据量的读写(百万级)
  • 支持模板填充

Maven 依赖:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.3.2</version>
</dependency>

注意:如果你的项目中使用 Lombok,建议搭配使用,可以少写很多 Getter/Setter 代码。


快速入门:写 Excel

最简单的写操作

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
// 1. 先定义数据模型
@Data
public class UserData {
    @ExcelProperty("用户ID")
    private Long userId;
    @ExcelProperty("用户名")
    private String userName;
    @ExcelProperty("年龄")
    private Integer age;
    @ExcelProperty("邮箱")
    private String email;
}
// 2. 写入数据
public class WriteTest {
    public static void main(String[] args) {
        // 准备数据
        List<UserData> userList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            UserData user = new UserData();
            user.setUserId((long) i);
            user.setUserName("用户" + i);
            user.setAge(20 + i);
            user.setEmail("user" + i + "@example.com");
            userList.add(user);
        }
        // 写入 Excel
        String fileName = "用户数据.xlsx";
        EasyExcel.write(fileName, UserData.class)
                .sheet("用户信息")
                .doWrite(userList);
        System.out.println("写入成功!");
    }
}

自定义样式和格式

import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
public class WriteWithStyle {
    public static void main(String[] args) {
        // 设置表头样式
        WriteCellStyle headStyle = new WriteCellStyle();
        WriteFont headFont = new WriteFont();
        headFont.setBold(true);
        headFont.setFontHeightInPoints((short) 12);
        headFont.setColor(IndexedColors.WHITE.getIndex());
        headStyle.setWriteFont(headFont);
        headStyle.setFillForegroundColor(IndexedColors.BLUE.getIndex());
        // 设置内容样式
        WriteCellStyle contentStyle = new WriteCellStyle();
        WriteFont contentFont = new WriteFont();
        contentFont.setFontHeightInPoints((short) 10);
        contentStyle.setWriteFont(contentFont);
        // 组合策略
        HorizontalCellStyleStrategy strategy = new HorizontalCellStyleStrategy(headStyle, contentStyle);
        String fileName = "带样式的用户数据.xlsx";
        EasyExcel.write(fileName, UserData.class)
                .registerWriteHandler(strategy)
                .sheet("用户信息")
                .doWrite(getUserList());
    }
}

读 Excel

同步读取(适合小文件)

import com.alibaba.excel.EasyExcel;
public class SimpleRead {
    public static void main(String[] args) {
        String fileName = "用户数据.xlsx";
        // 同步读取,直接返回 List
        List<UserData> list = EasyExcel.read(fileName)
                .head(UserData.class)
                .sheet()
                .doReadSync();
        // 打印读取到的数据
        list.forEach(System.out::println);
    }
}

异步读取(推荐,适合大数据量)

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
public class AsyncRead {
    public static void main(String[] args) {
        String fileName = "用户数据.xlsx";
        EasyExcel.read(fileName, UserData.class, new ReadListener<UserData>() {
            // 每读取一行,调用一次
            @Override
            public void invoke(UserData data, AnalysisContext context) {
                System.out.println("读取到数据:" + data);
            }
            // 所有数据读取完成后的操作
            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                System.out.println("所有数据读取完成!");
            }
        }).sheet().doRead();
    }
}

批量处理读取(推荐方式)

public class BatchRead {
    // 每批处理的条数
    private static final int BATCH_COUNT = 100;
    public static void main(String[] args) {
        String fileName = "用户数据.xlsx";
        EasyExcel.read(fileName, UserData.class, new ReadListener<UserData>() {
            private List<UserData> batchList = new ArrayList<>(BATCH_COUNT);
            @Override
            public void invoke(UserData data, AnalysisContext context) {
                batchList.add(data);
                // 达到 BATCH_COUNT 时,批量处理
                if (batchList.size() >= BATCH_COUNT) {
                    processBatch();
                    batchList.clear();
                }
            }
            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                // 处理剩余数据
                if (!batchList.isEmpty()) {
                    processBatch();
                }
                System.out.println("所有数据处理完成!");
            }
            private void processBatch() {
                // 批量处理数据,比如批量插入数据库
                System.out.println("批量处理 " + batchList.size() + " 条数据");
            }
        }).sheet().doRead();
    }
}

高级用法

动态头(表头不固定时)

public class DynamicHeadWrite {
    public static void main(String[] args) {
        // 动态构建表头
        List<List<String>> head = new ArrayList<>();
        head.add(Arrays.asList("姓名", "基本信息"));  // 合并单元格
        head.add(Arrays.asList("年龄", "基本信息"));
        head.add(Arrays.asList("邮箱", "联系方式"));
        head.add(Arrays.asList("电话", "联系方式"));
        // 准备数据
        List<List<String>> data = new ArrayList<>();
        data.add(Arrays.asList("张三", "25", "zhangsan@example.com", "13800138000"));
        data.add(Arrays.asList("李四", "30", "lisi@example.com", "13900139000"));
        String fileName = "动态表头.xlsx";
        EasyExcel.write(fileName)
                .head(head)
                .sheet("数据")
                .doWrite(data);
    }
}

模板填充

public class TemplateFill {
    public static void main(String[] args) {
        String templateFile = "模板.xlsx";
        String outputFile = "填充结果.xlsx";
        // 准备填充数据
        Map<String, Object> fillData = new HashMap<>();
        fillData.put("name", "张三");
        fillData.put("age", 25);
        fillData.put("createDate", new Date());
        // 填充单个对象
        EasyExcel.write(outputFile)
                .withTemplate(templateFile)
                .sheet()
                .doFill(fillData);
    }
}

数据验证

public class DataValidation {
    // 使用 @ExcelProperty 注解进行简单验证
    @Data
    public static class ValidatedData {
        @ExcelProperty("必填字段")
        @NotBlank(message = "不能为空")
        private String requiredField;
        @ExcelProperty("数字字段")
        @Min(value = 0, message = "不能小于0")
        @Max(value = 100, message = "不能大于100")
        private Integer numberField;
        @ExcelProperty("长度限制")
        @Size(max = 10, message = "长度不能超过10")
        private String limitedField;
    }
}

性能优化建议

大数据量写入

public class LargeDataWrite {
    public static void main(String[] args) {
        String fileName = "大数据.xlsx";
        EasyExcel.write(fileName, UserData.class)
                .sheet("数据")
                .doWrite(() -> {
                    // 数据分批获取,避免一次性加载到内存
                    for (int i = 0; i < 10000; i++) {
                        List<UserData> batch = getBatchData(i);
                        return batch;
                    }
                    return null;
                });
    }
}

内存优化配置

public class MemoryOptimized {
    public static void main(String[] args) {
        // 写入优化
        EasyExcel.write(fileName, UserData.class)
                .inMemory(false)  // 使用文件缓存,减少内存使用
                .sheet("数据")
                .doWrite(dataList);
        // 读取优化
        EasyExcel.read(fileName, UserData.class, new ReadListener<UserData>() {
            @Override
            public void invoke(UserData data, AnalysisContext context) {
                // 逐行处理,不加载全部到内存
                processLine(data);
            }
            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                // 完成
            }
        })
        .sheet()
        .doRead();
    }
}

常见问题解决

日期格式处理

@Data
public class DateDemo {
    @ExcelProperty("日期")
    @DateTimeFormat("yyyy年MM月dd日")
    private Date date;
    @ExcelProperty("时间")
    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
    private LocalDateTime localDateTime;
}

数字格式化

@Data
public class NumberDemo {
    @ExcelProperty("金额")
    @NumberFormat("#.##")
    private Double money;
    @ExcelProperty("百分比")
    @NumberFormat("#%")
    private Double percentage;
}

导入时忽略某些列

@Data
public class IgnoreColumnDemo {
    @ExcelProperty("姓名")
    private String name;
    @ExcelProperty("年龄")
    private Integer age;
    @ExcelIgnore  // 忽略这个字段
    private String ignoreField;
    @ExcelProperty(index = 3)  // 指定列索引
    private String otherField;
}

选择 EasyExcel 的场景:

  1. 需要处理大数据量 Excel(万级以上)
  2. 内存敏感的应用
  3. 需要高性能的 Excel 读写
  4. 想要简单易用的 API

注意事项:

  1. 尽量使用异步读取,避免 OOM
  2. 大数据量写入时,使用分批写入
  3. 注意文件路径和流资源的正确关闭
  4. 测试环境验证后再应用于生产

希望这个指南能帮助你快速上手 EasyExcel!如果你有具体的业务场景,可以告诉我,我可以提供更针对性的示例。

抱歉,评论功能暂时关闭!