環境
java 1.8
easyexcel 3.1.1
實現方式
自定義WriteHandler,實現AbstractMergeStrategy抽象類,實現merge 方法完成自定義的合并操作。
本測試代碼,實現了eques方法,用于判斷是否需要合并
核心代碼
實現AbstractMergeStrategy類的merge方法進行單元格合并
需要注意的是,單元格需要一次合并完成,合并了以后不能再次合并。所以判斷當前對象與前一個對象不相等時,才會對之前的對象進行合并操作
/*** 合并策略* @author dzh* @since 2025/4/17*/
public class MyMergeStrategy extends AbstractMergeStrategy {// 根據數據的下標判斷是否需要合并行private final Function<Integer, Boolean> eqBefore;// 根據列序號判斷該列列是否需要行合并,從0開始private final Function<Integer, Boolean> columnNeedMerge;public MyMergeStrategy(Function<Integer, Boolean> eqBefore, Function<Integer, Boolean> columnNeedMerge) {this.eqBefore = eqBefore;this.columnNeedMerge = columnNeedMerge;}@Overrideprotected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {if (relativeRowIndex == null || relativeRowIndex <= 1) {return;}if (!columnNeedMerge.apply(cell.getColumnIndex())) {return;}if (!eqBefore.apply(relativeRowIndex) && eqBefore.apply(relativeRowIndex - 1)) {int endRow = cell.getRowIndex() - 1;int firstRow = getFirstRow(endRow, relativeRowIndex - 1);CellRangeAddress rangeAddress = new CellRangeAddress(firstRow, endRow, cell.getColumnIndex(), cell.getColumnIndex());sheet.addMergedRegion(rangeAddress);}}private int getFirstRow(int rowIndex, int dataIndex) {if (dataIndex == 0) {return rowIndex;}if (this.eqBefore.apply(dataIndex)) {return getFirstRow(rowIndex - 1, dataIndex - 1);}return rowIndex;}
}
測試代碼
測試代碼中定義的對象覆蓋了eques方法,通過該方法判斷多個對象如果相等則進行合并操作
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.google.common.collect.Sets;
import lombok.Data;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;/*** @author dzh* @since 2023-06-28*/
public class ExportExcelTest {@Testpublic void template() throws IOException {InputStream in = new ClassPathResource("template.xlsx").getInputStream();File out = new File("c://temp/report.xlsx");List<Student> data = data();Function<Integer, Boolean> comp = (i) -> data.get(i - 1).equals(data.get(i));Function<Integer, Boolean> colMerge = (i) -> i < 2;MyMergeStrategy writeHandler = new MyMergeStrategy(comp, colMerge);ExcelWriterBuilder builder = EasyExcel.write(out).withTemplate(in).registerWriteHandler(writeHandler);try (ExcelWriter excelWriter = builder.build()) {WriteSheet writeSheet = EasyExcel.writerSheet().build();FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();excelWriter.fill(data, fillConfig, writeSheet);Map<String, Object> map = new HashMap<>();map.put("tableName", "成績報表");map.put("total", 886655);excelWriter.fill(map, writeSheet);} finally {in.close();}}@NotNullprivate static List<Student> data() {List<Student> list = new ArrayList<Student>() {{add(new Student("三年級一班", "lucy", "語文", 99));add(new Student("三年級一班", "lucy", "數學", 98));add(new Student("三年級一班", "lucy", "英語", 100));add(new Student("三年級一班", "jack", "語文", 87));add(new Student("三年級二班", "lucy", "語文", 78));add(new Student("三年級二班", "lily", "語文", 97));add(new Student("三年級二班", "lily", "數學", 79));add(new Student("三年級三班", "andy", "語文", 99));}};for (int i = 0; i < list.size(); i++) {Student cur = list.get(i);if (i == 0) {cur.setIndex(1);} else {Student pre = list.get(i - 1);if (pre.equals(cur)) {cur.setIndex(pre.getIndex());} else {cur.setIndex(pre.getIndex() + 1);}}}return list;}@Datastatic class Student {private Integer index;private String clas;private String name;private String subject;private Integer score;public Student(String clas, String name, String subject, Integer score) {this.clas = clas;this.name = name;this.subject = subject;this.score = score;}public boolean equals(Object obj) {Function<Student, Object> con = s -> String.join("-", s.getName(), s.getClas());Object a = con.apply(this);Object b = con.apply((Student) obj);System.out.println(a + "\t" + b);return a.equals(b);}}
}