easyexcel 版本:3.0.5
自定义单元格合并WriterHandler
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
/**
* @author mori
* @date 2022/3/9
*/
public class CellMergeWriterHandler {
public static CellWriteHandler getCellMergeWriterHandler(CellMergeEnum cellMergeEnum) {
if (CellMergeEnum.ROW.equals(cellMergeEnum)) {
return new RowMergeWriterHandler();
}
if (CellMergeEnum.COLUMN.equals(cellMergeEnum)) {
return new ColumnMergeWriterHandler();
}
return null;
}
public static CellWriteHandler getRowMergeWriterHandler(List<Integer> rows) {
return getCellWriteHandler(CellMergeEnum.ROW, rows);
}
public static CellWriteHandler getColumnMergeWriterHandler(List<Integer> cols) {
return getCellWriteHandler(CellMergeEnum.COLUMN, cols);
}
public static CellWriteHandler getCellWriteHandler(CellMergeEnum cellMergeEnum, List<Integer> columnsOrRows) {
if (CellMergeEnum.ROW.equals(cellMergeEnum)) {
return new RowMergeWriterHandler(new HashSet<>(columnsOrRows));
}
if (CellMergeEnum.COLUMN.equals(cellMergeEnum)) {
return new ColumnMergeWriterHandler(new HashSet<>(columnsOrRows));
}
return null;
}
public static class ColumnMergeWriterHandler extends AbstractMergeStrategy {
private Set<Integer> mergeCols;
public ColumnMergeWriterHandler() {
}
public ColumnMergeWriterHandler(Set<Integer> mergeCols) {
this.mergeCols = mergeCols;
}
@Override
protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
if (CollectionUtils.isNotEmpty(this.mergeCols) && !this.mergeCols.contains(cell.getColumnIndex())) {
return;
}
mergeCell(cell.getSheet(), cell, CellMergeEnum.COLUMN);
}
}
public static class RowMergeWriterHandler extends AbstractMergeStrategy {
private Set<Integer> mergeCols;
public RowMergeWriterHandler() {
}
public RowMergeWriterHandler(Set<Integer> mergeCols) {
this.mergeCols = mergeCols;
}
@Override
protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
if (CollectionUtils.isNotEmpty(mergeCols) && !mergeCols.contains(cell.getColumnIndex())) {
return;
}
mergeCell(cell.getSheet(), cell, CellMergeEnum.ROW);
}
}
private static void mergeCell(Sheet sheet, Cell cell, CellMergeEnum cellMergeEnum) {
if (Objects.isNull(cell)) {
return;
}
int rowIndex = cell.getRowIndex(), colIndex = cell.getColumnIndex();
Row preRow = null;
Cell preCell = null;
if (CellMergeEnum.ROW.equals(cellMergeEnum)) {
if (rowIndex == 0) {
return;
}
preRow = sheet.getRow(rowIndex - 1);
if (Objects.isNull(preRow)) {
return;
}
preCell = preRow.getCell(colIndex);
}
if (CellMergeEnum.COLUMN.equals(cellMergeEnum)) {
if (colIndex == 0) {
return;
}
preRow = cell.getRow();
preCell = preRow.getCell(colIndex - 1);
}
if (Objects.isNull(preCell)) {
return;
}
Object preCellValue = getCellValue(preCell), curCellValue = getCellValue(cell);
if (Objects.isNull(preCellValue) || Objects.isNull(curCellValue) || !preCellValue.equals(curCellValue)) {
return;
}
merge(sheet, preCell, cell);
}
private static void merge(Sheet sheet, Cell preCell, Cell curCell) {
List<CellRangeAddress> list = sheet.getMergedRegions();
if (CollectionUtils.isEmpty(list)) {
sheet.addMergedRegionUnsafe(new CellRangeAddress(preCell.getRowIndex(), curCell.getRowIndex(), preCell.getColumnIndex(), curCell.getColumnIndex()));
return;
}
for (int i = 0; i < list.size(); i++) {
CellRangeAddress cellRangeAddress = list.get(i);
if (cellRangeAddress.containsRow(preCell.getRowIndex()) && cellRangeAddress.containsColumn(preCell.getColumnIndex())) {
int firstRowIndex = cellRangeAddress.getFirstRow(), firstColIndex = cellRangeAddress.getFirstColumn();
sheet.removeMergedRegion(i);
sheet.addMergedRegionUnsafe(new CellRangeAddress(firstRowIndex, curCell.getRowIndex(), firstColIndex, curCell.getColumnIndex()));
return;
}
}
sheet.addMergedRegionUnsafe(new CellRangeAddress(preCell.getRowIndex(), curCell.getRowIndex(), preCell.getColumnIndex(), curCell.getColumnIndex()));
}
protected static Object getCellValue(Cell cell) {
if (Objects.isNull(cell)) {
return null;
}
CellType cellTypeEnum = cell.getCellType();
switch (cellTypeEnum) {
case STRING:
return cell.getStringCellValue();
case BOOLEAN:
return cell.getBooleanCellValue();
case NUMERIC:
return cell.getNumericCellValue();
default:
return null;
}
}
public enum CellMergeEnum {
/**
* row
*/
ROW,
/**
* column
*/
COLUMN;
}
}
测试代码:
@Test
public void testTemplate() {
String templateFileName = "./src/test/resources/test_simple_list.xlsx";
String fileName = "./reports/listFill" + System.currentTimeMillis() + ".xlsx";
ByteArrayOutputStream out = new ByteArrayOutputStream();
ExcelWriter excelWriter = EasyExcel.write(out).withTemplate(templateFileName)
.registerWriteHandler(CellMergeWriterHandler.getRowMergeWriterHandler(Arrays.asList(0, 1)))
.autoCloseStream(Boolean.FALSE)
.build();
WriteSheet writeSheet = EasyExcel.writerSheet(0).build();
// 直接写入数据
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
excelWriter.fill(dataMap(), fillConfig, writeSheet);
excelWriter.finish();
File file = new File(fileName);
try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
fileOutputStream.write(out.toByteArray());
fileOutputStream.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
private List<Map<String, Object>> dataMap() {
List<Map<String, Object>> list = ListUtils.newArrayList();
for (int i = 0; i < 5; i++) {
Map<String, Object> object = new HashMap<>();
list.add(object);
if (i % 3 == 0) {
object.put("name", "张三3");
object.put("number", null);
} else {
object.put("number", 5.2);
object.put("name", "张三");
}
}
return list;
}
模板:
运行效果:
A列和B列相同数值行合并。