EasyExcel配置详解:定制你的Excel处理行为
【免费下载链接】easyexcel 快速、简洁、解决大文件内存溢出的java处理Excel工具 项目地址: https://gitcode.com/gh_mirrors/ea/easyexcel
引言
在Java开发中,处理Excel文件是一项常见且重要的任务。然而,传统的Excel处理库往往存在内存占用高、API复杂等问题。EasyExcel作为一款快速、简洁、解决大文件内存溢出的Java处理Excel工具,为开发者提供了高效便捷的Excel读写方案。本文将深入探讨EasyExcel的配置选项,帮助你定制符合特定需求的Excel处理行为。
读完本文后,你将能够:
- 掌握EasyExcel的核心配置构建器
- 理解并配置Excel读取参数
- 定制Excel写入行为
- 实现数据转换器和监听器
- 应用样式策略美化Excel输出
- 解决常见的配置问题
EasyExcel配置体系概览
EasyExcel采用构建器模式(Builder Pattern)来组织配置选项,形成了一套层次分明的配置体系。这种设计使得配置过程直观且灵活,开发者可以根据需求精确调整Excel处理行为。
核心配置构建器
EasyExcel提供了多个构建器类,用于配置不同层级的Excel处理参数:
| 构建器类 | 用途 | 核心方法 |
|---|---|---|
| ExcelWriterBuilder | 配置工作簿级写入参数 | write(), excelType(), password() |
| ExcelWriterSheetBuilder | 配置工作表级写入参数 | sheetNo(), sheetName(), doWrite() |
| ExcelWriterTableBuilder | 配置表格级写入参数 | tableNo(), build() |
| ExcelReaderBuilder | 配置工作簿级读取参数 | read(), ignoreEmptyRow(), password() |
| ExcelReaderSheetBuilder | 配置工作表级读取参数 | sheetNo(), sheetName(), registerReadListener() |
这些构建器通过链式调用的方式组合使用,形成完整的配置流程。
配置层级结构
EasyExcel的配置体系分为三个主要层级,每层配置具有不同的作用域和优先级:
- 工作簿级(Workbook): 影响整个Excel文件的配置,如文件类型、密码保护、字符集等
- 工作表级(Sheet): 针对单个工作表的配置,如工作表名称、是否需要表头、数据起始行等
- 表格级(Table): 针对工作表内表格的配置,如表格编号、包含/排除列等
配置合并时,优先级从高到低为:表格级 > 工作表级 > 工作簿级。
Excel读取配置详解
ExcelReaderBuilder和ExcelReaderSheetBuilder提供了丰富的方法来配置Excel读取行为。通过合理设置这些参数,可以高效地读取各种复杂结构的Excel文件。
工作簿级读取配置
ExcelReaderBuilder提供了一系列方法来配置工作簿级别的读取参数:
ExcelReader reader = EasyExcel.read("input.xlsx")
.excelType(ExcelTypeEnum.XLSX) // 指定Excel文件类型
.password("secret") // 设置打开密码
.charset(StandardCharsets.UTF_8) // 设置字符集
.autoCloseStream(true) // 自动关闭输入流
.ignoreEmptyRow(true) // 忽略空行
.readCache(new MapReadCache()) // 设置读取缓存实现
.build();
关键配置项解析
| 配置方法 | 功能描述 | 默认值 | 适用场景 |
|---|---|---|---|
| excelType() | 指定Excel文件类型(XLS/XLSX/CSV) | 自动检测 | 明确知道文件类型时提高效率 |
| password() | 设置打开加密Excel文件的密码 | null | 处理加密保护的Excel文件 |
| ignoreEmptyRow() | 是否忽略空行 | true | 过滤无效空行数据 |
| readCache() | 设置读取缓存策略 | 默认实现 | 大文件读取时优化内存占用 |
| extraRead() | 配置额外读取内容(批注/超链接/合并单元格) | 无 | 需要读取Excel附加信息时 |
工作表级读取配置
ExcelReaderSheetBuilder用于配置单个工作表的读取参数:
ReadSheet sheet = EasyExcel.readSheet(0)
.sheetName("数据Sheet") // 设置工作表名称
.head(Student.class) // 指定表头映射类
.startRow(1) // 设置数据起始行
.endRow(1000) // 设置数据结束行
.registerReadListener(new AnalysisEventListener<Student>() {
// 实现数据处理逻辑
@Override
public void invoke(Student data, AnalysisContext context) {
// 处理每行数据
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 所有数据处理完成后操作
}
})
.build();
监听器配置
监听器是EasyExcel读取数据的核心机制,通过实现AnalysisEventListener接口,可以灵活处理读取到的数据:
public class StudentListener extends AnalysisEventListener<Student> {
private List<Student> dataList = new ArrayList<>();
private static final int BATCH_SIZE = 100; // 批处理大小
@Override
public void invoke(Student student, AnalysisContext context) {
dataList.add(student);
// 达到批处理大小则持久化数据
if (dataList.size() >= BATCH_SIZE) {
saveData();
dataList.clear();
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 处理剩余数据
if (!dataList.isEmpty()) {
saveData();
}
// 数据处理完成后的清理工作
}
private void saveData() {
// 将数据保存到数据库或其他存储
System.out.println("保存了" + dataList.size() + "条数据");
}
}
选择性读取配置
EasyExcel提供了多种方式来选择性读取Excel列:
// 方式1: 包含指定列索引
EasyExcel.readSheet().includeColumnIndexes(Arrays.asList(0, 2, 4)).build();
// 方式2: 包含指定列字段名
EasyExcel.readSheet().includeColumnFieldNames(Arrays.asList("name", "age", "score")).build();
// 方式3: 排除指定列索引
EasyExcel.readSheet().excludeColumnIndexes(Arrays.asList(1, 3)).build();
// 方式4: 排除指定列字段名
EasyExcel.readSheet().excludeColumnFieldNames(Arrays.asList("id", "createTime")).build();
Excel写入配置详解
ExcelWriterBuilder、ExcelWriterSheetBuilder和ExcelWriterTableBuilder构成了写入配置的核心,通过这些构建器可以精确控制Excel的生成过程。
工作簿级写入配置
ExcelWriterBuilder用于配置整个Excel文件的写入参数:
ExcelWriter writer = EasyExcel.write("output.xlsx")
.excelType(ExcelTypeEnum.XLSX) // 指定文件类型
.password("protect") // 设置文件密码
.inMemory(false) // 是否内存操作(大文件建议设为false)
.withTemplate("template.xlsx") // 设置模板文件
.autoCloseStream(true) // 自动关闭输出流
.build();
模板写入配置
EasyExcel支持基于模板写入数据,这在生成格式复杂的报表时非常有用:
ExcelWriter writer = EasyExcel.write("report.xlsx")
.withTemplate("template.xlsx") // 加载模板文件
.excelType(ExcelTypeEnum.XLSX)
.build();
// 填充模板中的简单占位符
FillConfig fillConfig = FillConfig.builder()
.direction(WriteDirectionEnum.HORIZONTAL) // 设置填充方向
.build();
writer.fill(data, fillConfig, EasyExcel.writerSheet().build());
writer.finish();
工作表级写入配置
ExcelWriterSheetBuilder用于配置单个工作表的写入参数:
WriteSheet sheet = EasyExcel.writerSheet(0)
.sheetName("学生成绩单") // 设置工作表名称
.head(Student.class) // 指定表头映射类
.needHead(true) // 是否需要表头
.relativeHeadRowIndex(1) // 表头相对起始行
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 自动列宽策略
.build();
写入处理器配置
通过注册写入处理器,可以自定义Excel的写入行为,例如设置单元格样式、调整列宽等:
// 注册多个写入处理器
WriteSheet sheet = EasyExcel.writerSheet()
.registerWriteHandler(new HorizontalCellStyleStrategy(
// 表头样式
WriteCellStyleBuilder.create().build(),
// 内容样式
WriteCellStyleBuilder.create().build()
))
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.build();
表格级写入配置
ExcelWriterTableBuilder用于配置工作表内的表格:
WriteTable table = EasyExcel.writerTable(0)
.tableNo(1) // 设置表格编号
.head(Student.class) // 指定表格表头
.includeColumnFieldNames(Arrays.asList("name", "age", "score")) // 包含指定列
.build();
表格配置在一个工作表中需要写入多个独立表格时非常有用:
ExcelWriter writer = EasyExcel.write("multi-tables.xlsx")
.head(Student.class)
.build();
// 第一个表格
WriteTable table1 = EasyExcel.writerTable(0)
.tableNo(0)
.build();
// 第二个表格,使用不同的表头
WriteTable table2 = EasyExcel.writerTable(1)
.tableNo(1)
.head(Teacher.class)
.build();
writer.write(studentData, EasyExcel.writerSheet().build(), table1);
writer.write(teacherData, EasyExcel.writerSheet().build(), table2);
writer.finish();
数据转换配置
EasyExcel提供了灵活的数据转换机制,通过转换器可以实现Excel单元格数据与Java对象属性之间的自定义转换。
内置转换器
EasyExcel内置了多种常用的数据转换器,覆盖了大部分基本数据类型:
| 转换器类 | 功能描述 |
|---|---|
| DateStringConverter | 日期与字符串之间的转换 |
| NumberStringConverter | 数字与字符串之间的转换 |
| BooleanStringConverter | 布尔值与字符串之间的转换 |
| LocalDateTimeStringConverter | Java 8日期时间与字符串之间的转换 |
| BigDecimalStringConverter | 大数与字符串之间的转换 |
自定义转换器
当内置转换器无法满足需求时,可以实现Converter接口自定义转换器:
public class GenderConverter implements Converter<String> {
@Override
public Class<?> supportJavaTypeKey() {
return String.class; // 支持的Java类型
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING; // 支持的Excel单元格类型
}
@Override
public String convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
// Excel数据转Java对象
String value = cellData.getStringValue();
if ("男".equals(value)) {
return "M";
} else if ("女".equals(value)) {
return "F";
}
return "U";
}
@Override
public WriteCellData<?> convertToExcelData(String value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
// Java对象转Excel数据
if ("M".equals(value)) {
return new WriteCellData<>("男");
} else if ("F".equals(value)) {
return new WriteCellData<>("女");
}
return new WriteCellData<>("未知");
}
}
注册自定义转换器:
// 全局注册
EasyExcel.write()
.registerConverter(new GenderConverter())
.head(Student.class)
.sheet()
.doWrite(data);
// 字段级别注册(通过@ExcelProperty注解)
public class Student {
@ExcelProperty(value = "姓名", index = 0)
private String name;
@ExcelProperty(value = "性别", index = 1, converter = GenderConverter.class)
private String gender;
// 其他字段...
}
样式配置策略
EasyExcel提供了多种样式配置策略,可以美化Excel输出,使其更易读和专业。
内置样式策略
EasyExcel内置了几种常用的样式策略:
| 样式策略类 | 功能描述 | 使用场景 |
|---|---|---|
| HorizontalCellStyleStrategy | 水平方向样式策略 | 为表头和内容设置不同样式 |
| LongestMatchColumnWidthStyleStrategy | 最长匹配列宽策略 | 自动根据内容调整列宽 |
| SimpleColumnWidthStyleStrategy | 简单列宽策略 | 设置固定列宽 |
| AbstractVerticalCellStyleStrategy | 垂直方向样式策略 | 为不同行设置不同样式 |
自定义单元格样式
通过实现WriteCellStyle可以自定义单元格样式:
// 创建表头样式
WriteCellStyle headStyle = new WriteCellStyle();
// 设置背景色
headStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex());
headStyle.setFillPatternType(FillPatternTypeEnum.SOLID_FOREGROUND);
// 设置边框
headStyle.setBorderBottom(BorderStyleEnum.THIN);
headStyle.setBorderLeft(BorderStyleEnum.THIN);
headStyle.setBorderRight(BorderStyleEnum.THIN);
headStyle.setBorderTop(BorderStyleEnum.THIN);
// 设置字体
WriteFont headFont = new WriteFont();
headFont.setFontName("宋体");
headFont.setFontHeightInPoints((short)12);
headFont.setBold(true);
headStyle.setWriteFont(headFont);
// 创建内容样式
WriteCellStyle contentStyle = new WriteCellStyle();
// 配置内容样式...
// 使用样式策略
WriteSheet sheet = EasyExcel.writerSheet()
.registerWriteHandler(new HorizontalCellStyleStrategy(headStyle, contentStyle))
.build();
列宽和行高配置
合理设置列宽和行高可以使Excel更易读:
// 使用简单列宽策略
WriteSheet sheet = EasyExcel.writerSheet()
.registerWriteHandler(new SimpleColumnWidthStyleStrategy(20)) // 所有列宽20
.build();
// 使用自定义列宽策略
public class CustomColumnWidthStrategy extends AbstractColumnWidthStyleStrategy {
@Override
protected Integer columnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList,
Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
if (isHead) {
return 20; // 表头列宽
} else {
// 根据列索引设置不同列宽
switch (cell.getColumnIndex()) {
case 0: return 15;
case 1: return 25;
case 2: return 18;
default: return 12;
}
}
}
}
// 设置行高
public class CustomRowHeightStrategy extends AbstractRowWriteHandler {
@Override
public void afterRowDispose(RowWriteHandlerContext context) {
if (context.getRelativeRowIndex() == -1) {
// 设置表头行高
context.getRow().setHeight((short)500);
} else {
// 设置内容行高
context.getRow().setHeight((short)400);
}
}
}
高级配置与最佳实践
大数据量处理配置
处理大数据量Excel时,合理的配置可以显著提升性能并避免内存溢出:
// 读取大数据量Excel
ExcelReader reader = EasyExcel.read("large-data.xlsx")
.readCache(new MapReadCache()) // 使用Map缓存
.autoCloseStream(true)
.ignoreEmptyRow(true)
.build();
// 写入大数据量Excel
ExcelWriter writer = EasyExcel.write("large-data-output.xlsx")
.inMemory(false) // 禁用内存操作,使用磁盘缓存
.excelType(ExcelTypeEnum.XLSX)
.build();
// 分批写入数据
List<Student> batchData = new ArrayList<>(1000);
for (Student student : allData) {
batchData.add(student);
if (batchData.size() >= 1000) {
writer.write(batchData, sheet);
batchData.clear();
}
}
// 写入剩余数据
if (!batchData.isEmpty()) {
writer.write(batchData, sheet);
}
writer.finish();
并发处理配置
EasyExcel本身不是线程安全的,但可以通过以下方式实现并发处理:
// 并发读取多个工作表
ExecutorService executor = Executors.newFixedThreadPool(5);
List<Future<?>> futures = new ArrayList<>();
for (int i = 0; i < sheetCount; i++) {
final int sheetNo = i;
futures.add(executor.submit(() -> {
try {
EasyExcel.read("multi-sheet.xlsx")
.sheet(sheetNo)
.registerReadListener(new DataListener())
.doRead();
} catch (Exception e) {
log.error("读取工作表{}失败", sheetNo, e);
}
}));
}
// 等待所有任务完成
for (Future<?> future : futures) {
future.get();
}
executor.shutdown();
常见配置问题解决
日期格式转换问题
日期转换是Excel处理中常见的问题,可通过以下方式解决:
// 全局配置日期格式
EasyExcel.write()
.registerConverter(new LocalDateTimeStringConverter("yyyy-MM-dd HH:mm:ss"))
.head(Order.class)
.sheet()
.doWrite(data);
// 字段级别配置
public class Order {
@ExcelProperty("订单日期")
@DateTimeFormat("yyyy-MM-dd") // 写入时格式化
@ExcelProperty("订单日期")
private LocalDateTime orderDate;
// 其他字段...
}
大数据量内存溢出问题
处理超大Excel文件时,可通过以下配置避免内存溢出:
// 读取时使用Sax模式并分批处理
EasyExcel.read("large-file.xlsx")
.head(Record.class)
.registerReadListener(new AnalysisEventListener<Record>() {
private List<Record> batchList = new ArrayList<>(1000);
@Override
public void invoke(Record data, AnalysisContext context) {
batchList.add(data);
if (batchList.size() >= 1000) {
processBatch(batchList); // 批处理数据
batchList.clear(); // 清理内存
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
if (!batchList.isEmpty()) {
processBatch(batchList); // 处理剩余数据
}
}
})
.inMemory(false) // 禁用内存处理
.doRead();
总结与展望
EasyExcel提供了丰富的配置选项,通过合理组合这些配置,可以满足各种复杂的Excel处理需求。本文详细介绍了EasyExcel的配置体系、读取配置、写入配置、数据转换、样式策略和高级配置技巧,希望能帮助开发者更好地使用这个强大的工具。
随着业务需求的不断变化,EasyExcel也在持续迭代发展。未来,我们可以期待更多高级功能的加入,如更丰富的图表生成、更智能的数据验证等。掌握EasyExcel的配置技巧,将为Java开发中的Excel处理任务带来极大的便利和效率提升。
鼓励与互动:如果你觉得本文对你有帮助,请点赞、收藏并关注,以便获取更多关于EasyExcel的高级使用技巧。你在使用EasyExcel时遇到过哪些配置问题?欢迎在评论区分享你的经验和问题!
下期预告:EasyExcel与Spring Boot集成实战,敬请期待!
【免费下载链接】easyexcel 快速、简洁、解决大文件内存溢出的java处理Excel工具 项目地址: https://gitcode.com/gh_mirrors/ea/easyexcel
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



