EasyExcel配置详解:定制你的Excel处理行为

EasyExcel配置详解:定制你的Excel处理行为

【免费下载链接】easyexcel 快速、简洁、解决大文件内存溢出的java处理Excel工具 【免费下载链接】easyexcel 项目地址: 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的配置体系分为三个主要层级,每层配置具有不同的作用域和优先级:

mermaid

  • 工作簿级(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布尔值与字符串之间的转换
LocalDateTimeStringConverterJava 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工具 【免费下载链接】easyexcel 项目地址: https://gitcode.com/gh_mirrors/ea/easyexcel

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值