针对 阿里的easyexcel 自定义处理 任意单元格合并
官方给出的合并单元格 只给出固定规律的单元格合并,当然官方也指出可以自定义合并单元格的策略,我们跟进LoopMergeStrategy 这个合并策略的实例类,发现里面继承了AbstractRowWriteHandler,官方示例代码如下
/**
* 合并单元格
* <p>
* 1. 创建excel对应的实体对象 参照{@link DemoData} {@link DemoMergeData}
* <p>
* 2. 创建一个merge策略 并注册
* <p>
* 3. 直接写即可
*
* @since 2.2.0-beta1
*/
@Test
public void mergeWrite() {
// 方法1 注解
String fileName = TestFileUtil.getPath() + "mergeWrite" + System.currentTimeMillis() + ".xlsx";
// 在DemoStyleData里面加上ContentLoopMerge注解
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
EasyExcel.write(fileName, DemoMergeData.class).sheet("模板").doWrite(data());
// 方法2 自定义合并单元格策略
fileName = TestFileUtil.getPath() + "mergeWrite" + System.currentTimeMillis() + ".xlsx";
// 每隔2行会合并 把eachColumn 设置成 3 也就是我们数据的长度,所以就第一列会合并。
//当然其他合并策略也可以自己写
LoopMergeStrategy loopMergeStrategy = new LoopMergeStrategy(2, 0);
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
EasyExcel.write(fileName, DemoData.class).registerWriteHandler(loopMergeStrategy).sheet("模板").doWrite(data());
}
LoopMergeStrategy 的具体实现
/**
* The regions of the loop merge
*
* @author Jiaju Zhuang
*/
public class LoopMergeStrategy extends AbstractRowWriteHandler {
/**
* Each row
*/
private int eachRow;
/**
* Extend column
*/
private int columnExtend;
/**
* The number of the current column
*/
private int columnIndex;
public LoopMergeStrategy(int eachRow, int columnIndex) {
this(eachRow, 1, columnIndex);
}
public LoopMergeStrategy(int eachRow, int columnExtend, int columnIndex) {
if (eachRow < 1) {
throw new IllegalArgumentException("EachRows must be greater than 1");
}
if (columnExtend < 1) {
throw new IllegalArgumentException("ColumnExtend must be greater than 1");
}
if (columnExtend == 1 && eachRow == 1) {
throw new IllegalArgumentException("ColumnExtend or eachRows must be greater than 1");
}
if (columnIndex < 0) {
throw new IllegalArgumentException("ColumnIndex must be greater than 0");
}
this.eachRow = eachRow;
this.columnExtend = columnExtend;
this.columnIndex = columnIndex;
}
public LoopMergeStrategy(LoopMergeProperty loopMergeProperty, Integer columnIndex) {
this(loopMergeProperty.getEachRow(), loopMergeProperty.getColumnExtend(), columnIndex);
}
@Override
public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
Integer relativeRowIndex, Boolean isHead) {
if (isHead) {
return;
}
if (relativeRowIndex % eachRow == 0) {
CellRangeAddress cellRangeAddress = new CellRangeAddress(row.getRowNum(), row.getRowNum() + eachRow - 1,
columnIndex, columnIndex + columnExtend - 1);
writeSheetHolder.getSheet().addMergedRegionUnsafe(cellRangeAddress);
}
}
}
我们根据官方给出的AbstractRowWriteHandler行处理类 重写:
1.引入jar包
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.3</version>
</dependency>
2.声明需要合并单元格的定位实例
/** * easyExcel 单元格范围设定 */ @Data @AllArgsConstructor public class ExcelCellRange{ /** * 起始行 */ private int firstRow; /** * 终止行 */ private int lastRow; /** * 起始列 */ private int firstCol; /** * 终止列 */ private int lastCol; }
3.重写自定义合并策略类
/** * @Description:EasyExcel自定义合并单元格策略 * @Date: 2023/4/14 16:11 */ public class EasyExcelCustomMergeStrategy extends AbstractRowWriteHandler { /** * 单元格范围 */ private List<ExcelCellRange> cellRanges; public EasyExcelCustomMergeStrategy(List<ExcelCellRange> cellRanges) { this.cellRanges = cellRanges; } @Override public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) { if (!isHead) { for(ExcelCellRange cellRange :cellRanges) { if (relativeRowIndex % cellRange.getFirstRow() == 0) { CellRangeAddress cellRangeAddress = new CellRangeAddress(cellRange.getFirstRow(), cellRange.getLastRow(), cellRange.getFirstCol(), cellRange.getLastCol()); writeSheetHolder.getSheet().addMergedRegionUnsafe(cellRangeAddress); } } } } }
以上封装的实例 ,仅供参考,大家可以自行完善参数校验等逻辑
4.使用案例
// 定位合并数据 int rowIndex = 1; // 从第二行开始,因为第一行是表头 //存放合并单元格位置 List<ExcelCellRange> cellRanges = Lists.newArrayListWithCapacity(5); cellRanges.add(new ExcelCellRange(0, 1, 0, 0)); cellRanges.add(new ExcelCellRange(0, 1, 1, 1)); cellRanges.add(new ExcelCellRange(0, 1, 2, 2)); //合并策略 EasyExcelCustomMergeStrategy mergeStrategy = new EasyExcelCustomMergeStrategy(cellRanges); // 创建工作簿并指定写入的Excel文件 ExcelWriter excelWriter = EasyExcel.write(os) .head(TtRoomCheckInStateRes.class) .registerWriteHandler(mergeStrategy) .build(); // 创建一个只包含一行的Excel表格,用于合并单元格及为表格添加表头 WriteSheet writeSheet = EasyExcel.writerSheet(0, "房间入住情况").build(); //信息写入 excelWriter.write(roomRecordList, writeSheet); //关闭流 excelWriter.finish();
5.导出效果图