使用EasyExcel自定义拦截器做动态单元格合并
AbstractMergeStrategy
EasyExcel提供了一个抽象类AbstractMergeStrategy,通过实现merge方法来实现复杂的表格合并逻辑。
以下是我自定义的一个合并单元格的拦截器,目的是将第一列中包含年度两个字的单元格向右合并四个单元格。
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
public class ReportMergeWriterHandler extends AbstractMergeStrategy implements CellWriteHandler {
/**
* 合并单元格
* <p> 自定义合并单元格策略, 只有每一个行的第一列的单元格的包含"年度"两字时, 当前单元格横向合并4个 </p>
*
* @param sheet 工作表
* @param cell 单元格
* @param head 头
* @param integer 行索引
*/
@Override
protected void merge(Sheet sheet, Cell cell, Head head, Integer integer) {
// 检查当前单元格的值是否为数字0
if (cell.getColumnIndex() == 0 && cell.getCellType() == CellType.STRING && cell.getStringCellValue().contains("年度")) {
// 横向合并4个单元格(当前单元格及其右侧4个单元格)设置居中
cell.getCellStyle().setAlignment(HorizontalAlignment.CENTER);
CellRangeAddress cellRangeAddress = new CellRangeAddress(
cell.getRowIndex(), // 起始行
cell.getRowIndex(), // 结束行
cell.getColumnIndex(), // 起始列
cell.getColumnIndex() + 4 // 结束列(当前列+4)
);
sheet.addMergedRegion(cellRangeAddress);
}
}
}在调用的时候使用自定义策略,使用registerWriteHandler注册拦截器
ProjectInvestReportMergeWriterHandler mergeWriterHandler = new ProjectInvestReportMergeWriterHandler();
ExcelWriter excelWriter = EasyExcel.write(os)
.registerWriteHandler(mergeWriterHandler)
.withTemplate(templateResource.getStream())
.autoCloseStream(false)
.build();实现的merge方法有4个入参,可以再方法中获取到当前填充sheet表,填充的单元格cell、表头head、以及行号index,意味着这个方法会没有填入的单元格时都会进入这个方法,扩展我们对单元格操作的能力。除了合并单元格的操作外,我们还可以做一些做对cell的值进行修改,例如在拦截器中设置cell.setCellValue("自定义单元格固定值")。
LoopMergeStrategy 和 OnceAbsoluteMergeStrategy
EasyExcel还提供了另外两种合并单元格的策略,LoopMergeStrategy和OnceAbsoluteMergeStrategy。
LoopMergeStrategy策略可以做到循环合并
// 第一列每个两行进行合并
LoopMergeStrategy loopMergeStrategy = new LoopMergeStrategy(2, 0);OnceAbsoluteMergeStrategy策略可以需要一次性指定单元格坐标进行合并,如果实现多个指定合并需要通过registerWriteHandler(onceAbsoluteMergeStrategy)多次注册
// 指定第2行第2列,向下合并三个
OnceAbsoluteMergeStrategy onceAbsoluteMergeStrategy = new OnceAbsoluteMergeStrategy(1, 3, 1, 1);