EasyExcel按模板出使用自定义策略

本文介绍了如何在EasyExcel中使用模板和自定义策略处理复杂Excel导出需求,如多行表头、单元格合并等,通过实体类注解和`LoopMergeStrategy`、`CellStyleStrategy`来实现动态数据填充和格式调整。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

EasyExcel按模板出使用自定义策略

目标

要完成下面格式的Excel导出,在实体类上使用注解标注字段已经不好使了

前面的表头有多行,还有单元格合并,下面表格的行数也不是固定的

这种情况可以使用EasyExcel中的模板,下面的的表格使用填充导出

EasyExcel填充官方文档:https://easyexcel.opensource.alibaba.com/docs/current/quickstart/fill

实体类

表头字段

public class HbInvoiceExportForm {

    @ApiModelProperty(value = "信息平台编码")
    private String code3;

    @ApiModelProperty(value = "客户名称")
    private String bdCustomerName;

    @ApiModelProperty(value = "订单号")
    private String orderNo;

    @ApiModelProperty(value = "公司部门")
    private String corpDept;

    @ApiModelProperty(value = "业务员")
    private String salesman;

    @ApiModelProperty(value = "废危税率")
    private String wasteTaxRate;

    @ApiModelProperty(value = "运费税率")
    private String freightRate;

    @ApiModelProperty(value = "备注")
    private String remark;

    @ApiModelProperty(value = "行信息")
    private List<HbInvoiceExportRowForm> rows;

    @ApiModelProperty(value = "价税合计总共")
    private String totalAmount;

    @ApiModelProperty(value = "数量总共")
    private String totalNum;

    @ApiModelProperty(value = "开票员")
    private String drawer;

    @ApiModelProperty(value = "excel导出名称")
    private String text;
}

表体字段

public class HbInvoiceExportRowForm {
    @ApiModelProperty(value = "装运日期")
    private String shipmentDate;

    @ApiModelProperty(value = "联单号")
    private String systemManifestNo;

    @ApiModelProperty(value = "危废名称")
    private String wasteName;

    @ApiModelProperty(value = "主计量")
    private String mainMeasure;

    @ApiModelProperty(value = "数量")
    private String num;

    @ApiModelProperty(value = "报价")
    private String quote;

    @ApiModelProperty(value = "价税合计")
    private String totalAmount;

    @ApiModelProperty(value = "备注")
    private String remark;

    @ApiModelProperty(value = "空白字段,用来防止execl导出表格合并没有边框")
    private final String blankStr = "";

}

模板Excel

其中,{}中的是填充实体类变量名称,而data是多行模板填充时指定的变量名称

在模板中需要合并的单元格,拆分成每一个最小单元格,后面使用自定义策略合并,需要合并的第一列中绑定数值,后面需要合并的单元格绑定空字符串(data.blank是空字符串)

否则单元格合并会造成样式问题

实现代码

    InputStream template = null;
        try {
            template = new PathMatchingResourcePatternResolver()
                    .getResource("template-excel/HbInvoiceExport.XLSX").getInputStream();
        } catch (IOException e) {
            throw new RuntimeException("找不模板文件[" + "template-excel/HbInvoiceExport.XLSX" + "]");
        }
        //设置响应体,设置文件名称
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding("utf-8");
        String encodeName = null;
        try {
            encodeName = URLEncoder.encode(form.getText(), "UTF-8").replaceAll("\\+", "%20");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("导出文件名称格式错误");
        }
        response.setHeader("Content-disposition", "attachment; filename=" + encodeName + ".xlsx");
        // 创建导出
        try (OutputStream out = response.getOutputStream();
             BufferedOutputStream bos = new BufferedOutputStream(out);
             ExcelWriter excelWriter = EasyExcel.write(bos)
                     .excelType(ExcelTypeEnum.XLSX)
                     //按照模板导出
                     .withTemplate(template)
                     //合并列 从第三列开始, 合并本列和右边两列
                     .registerWriteHandler(new LoopMergeStrategy(1, 3, 2))
                     .registerWriteHandler(new CellStyleStrategy())
                     .build()) {
            WriteSheet writeSheet = EasyExcel.writerSheet().build();
            FillConfig fillConfig = FillConfig.builder().forceNewRow(true).autoStyle(true).direction(WriteDirectionEnum.VERTICAL).build();
            // 如果有多个list 模板上必须有{前缀.} 这里的前缀就是 data1,然后多个list必须用 FillWrapper包裹
            excelWriter.fill(new FillWrapper("data", form.getRows()), fillConfig, writeSheet);
            excelWriter.fill(form, writeSheet);
            bos.flush();
        } catch (IOException e) {
            log.error("导出异常", e);
            throw new RuntimeException("导出异常;" + e.getMessage());
        }

合并单元格策略

LoopMergeStrategy 是EasyExcel提供的,只会对循环填充的单元格生效

new LoopMergeStrategy(int eachRow, int columnExtend, int columnIndex)

  • eachRow:每一行,传1每一行都执行

  • columnExtend: 合并扩展列, 向右合并列

  • columnIndex: 列索引,从零开始,第columnIndex列开始执行合并,往右合并columnExtend列

数值格式设置策略

继承CellWriteHandler,重写afterCellDispose方法

指定单元格,将字符串转化为数值,否则数值在单元格上显示的还是字符串类型的

@Data
public class CellStyleStrategy implements CellWriteHandler {
    /**
     * 在单元格上的所有操作完成后调用
     * 每个单元格都会执行,Cell cell对象就是单元格对象
     */
    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList,
                                 Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        //当前行和列序号
        int curRowIndex = cell.getRowIndex();
        int curColIndex = cell.getColumnIndex();
        //数值列更改数值类型
        if (curRowIndex >= 6 && (curColIndex >= 6 && curColIndex <= 8)) {
            String value = cell.toString();
            try {
                cell.setCellType(CellType.NUMERIC);
                cell.setCellValue(Double.parseDouble(value));
            } catch (Exception ignore) {

            }
        }
    }
}
<think>好的,我现在需要解决用户的问题:如何使用EasyExcel根据模板填充导,并合并相同单元格。用户提到了示例教程,所以我需要提供一个清晰的步骤说明,并且结合代码示例。首先,我得回忆一下EasyExcel的相关文档和之前的使用经验。 首先,EasyExcel模板填充功能允许用户通过预定义的模板来生成Excel文件,这样可以保持格式的一致性。合并单元格通常需要自定义单元格合并策略,这应该是通过实现CellWriteHandler接口来完成的。用户需要将相同内容的单元格合并,所以应该在填充数据的时候应用这个策略。 接下来,我需要考虑如何编模板。用户需要创建一个包含占位符的Excel模板,比如使用{{name}}这样的变量。然后在代码中,通过填充配置将数据填入这些占位符。同时,合并策略需要在填充时被注册,这样EasyExcel入数据时会自动处理合并。 然后,代码部分需要包括填充配置的设置,合并策略的实现,以及如何读取模板并导文件。合并策略的逻辑应该是,在每次处理单元格内容后,检查当前单元格的值是否与前一行相同,如果是,则合并这些单元格。这里需要注意的是,合并的行数需要动态计算,可能需要维护一个状态来记录连续的相同值。 另外,用户可能希望合并的列是动态指定的,所以合并策略应该可以配置需要合并的列索引。例如,在示例中合并第二列,所以需要传入列索引参数。 测试的时候,需要准备测试数据和模板文件,运行代码后检查导Excel文件是否正确合并了单元格。同时,要处理可能的异常情况,比如空数据或者不同列的情况。 可能遇到的问题包括模板路径不正确、数据格式不匹配、合并策略未正确应用等。需要确保模板文件存在,并且占位符与代码中的键对应。此外,合并策略的实现需要正确处理每一行的数据,避免现合并错误或性能问题。 最后,整理这些思路,分步骤说明,并提供完整的代码示例,确保用户能够按照步骤操作。同时,生成的相关问题需要与EasyExcel使用和合并单元格相关,帮助用户进一步了解扩展功能。</think>以下是如何使用EasyExcel根据模板填充数据并合并相同单元格的详细步骤及示例: ### 一、操作流程 1. **准备模板文件** 创建带有占位符的Excel模板,如:`template.xlsx`,其中使用`{{.}}`表示动态填充区域。模板需标注需要合并的列,例如: ``` | 姓名(A列) | 部门(B列) | | {{name}} | {{dept}} | ``` 2. **定义合并策略** 继承`CellWriteHandler`接口实现自动合并逻辑,核心判断连续相同值: ```java public class CustomMergeStrategy implements CellWriteHandler { private final int mergeColumnIndex; private int totalRows = 0; public CustomMergeStrategy(int mergeColumnIndex) { this.mergeColumnIndex = mergeColumnIndex; } @Override public void afterCellDispose(WriteSheetHolder sheetHolder, WriteTableHolder tableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { if (cell.getRowIndex() > 0 && cell.getColumnIndex() == mergeColumnIndex) { String currentVal = cell.getStringCellValue(); String prevVal = cell.getSheet().getRow(cell.getRowIndex()-1).getCell(mergeColumnIndex).getStringCellValue(); if (currentVal.equals(prevVal)) { totalRows++; } else { if (totalRows > 0) { Sheet sheet = cell.getSheet(); CellRangeAddress region = new CellRangeAddress(cell.getRowIndex()-totalRows-1, cell.getRowIndex()-1, mergeColumnIndex, mergeColumnIndex); sheet.addMergedRegion(region); } totalRows = 0; } } } } ``` 3. **数据填充与导** 通过`ExcelWriter`绑定模板并应用策略: ```java public class ExportDemo { public static void main(String[] args) { List<Employee> dataList = Arrays.asList( new Employee("张三", "技术部"), new Employee("李四", "技术部"), new Employee("王五", "市场部") ); String templatePath = "template.xlsx"; String outputPath = "result.xlsx"; ExcelWriter excelWriter = EasyExcel.write(outputPath) .withTemplate(templatePath) .registerWriteHandler(new CustomMergeStrategy(1)) // 合并第二列(B列) .build(); WriteSheet writeSheet = EasyExcel.writerSheet().build(); excelWriter.fill(dataList, writeSheet); excelWriter.finish(); } } ``` ### 二、关键配置说明 | 组件 | 作用 | |--------------------|----------------------------------------------------------------------| | `@ExcelProperty` | 实体类字段与模板占位符的映射 | | `CellWriteHandler` | 控制单元格入时的合并行为[^1] | | `ExcelWriter` | 核心入器,支持模板填充和策略叠加 | ### 三、生成效果 导Excel会自动将`部门`列中连续相同的值合并,如技术部的两行会合并为一个单元格。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值