EasyExcel-合併單元格

默唸x發表於2022-06-09

pom版本

    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>easyexcel</artifactId>
      <version>2.2.7</version>
    </dependency>

1.自定義合併單元格 

在某些業務場景中可能會有合併單元格的需求,下面具體來說明如何實現

1.1 不合並單元格

先來看下不合並單元格的程式碼寫法,簡單複習下 

public static void writeExcel() {
    // 寫excel的路徑,當前專案路徑下
    String fileName = getPath();
    // 構建ExcelWriter
    ExcelWriter excelWriter = EasyExcel.write(fileName).excelType(ExcelTypeEnum.XLSX).build();

    // 構建sheet
    WriteSheet writeSheet = EasyExcel.writerSheet("模板1").head(DemoData.class).build();
    // 寫sheet
    excelWriter.write(data1(), writeSheet);
    excelWriter.finish();
  }

  private static String getPath() {
    return System.getProperty("user.dir") + "/" + System.currentTimeMillis() + ".xlsx";
  }

  private static List<DemoData> data1() {
    List<DemoData> list = Lists.newArrayList();
    for (int i = 0; i < 3; i++) {
      DemoData data = new DemoData();
      data.setString("字串" + 1);
      data.setDate(new Date());
      data.setDoubleData(0.56);
      list.add(data);
    }
    for (int i = 0; i < 3; i++) {
      DemoData data = new DemoData();
      data.setString("字串" + 2);
      data.setDate(new Date());
      data.setDoubleData(0.56);
      list.add(data);
    }
    for (int i = 0; i < 4; i++) {
      DemoData data = new DemoData();
      data.setString("字串" + 3);
      data.setDate(new Date());
      data.setDoubleData(0.57);
      list.add(data);
    }
    return list;
  }

  public static void main(String[] args) {
    writeExcel();
  }

開啟輸出的excel檔案後如下,可以看到單元格沒有合併。現在打算將第一列字串標題相同的合併

EasyExcel-合併單元格

 

1.2 合併單元格

// 自定義合併策略 該類繼承了AbstractMergeStrategy抽象合併策略,需要重寫merge()方法
  public static class CustomMergeStrategy extends AbstractMergeStrategy {

    /**
     * 分組,每幾行合併一次
     */
    private List<Integer> exportFieldGroupCountList;

    /**
     * 目標合併列index
     */
    private Integer targetColumnIndex;

    // 需要開始合併單元格的首行index
    private Integer rowIndex;

    // exportDataList為待合併目標列的值 
    public CustomMergeStrategy(List<String> exportDataList, Integer targetColumnIndex) {
      this.exportFieldGroupCountList = getGroupCountList(exportDataList);
      this.targetColumnIndex = targetColumnIndex;
    }


    @Override
    protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {

      if (null == rowIndex) {
        rowIndex = cell.getRowIndex();
      }
      // 僅從首行以及目標列的單元格開始合併,忽略其他
      if (cell.getRowIndex() == rowIndex && cell.getColumnIndex() == targetColumnIndex) {
        mergeGroupColumn(sheet);
      }
    }

    private void mergeGroupColumn(Sheet sheet) {
      int rowCount = rowIndex;
      for (Integer count : exportFieldGroupCountList) {
        if(count == 1) {
          rowCount += count;
          continue ;
        }
        // 合併單元格
        CellRangeAddress cellRangeAddress = new CellRangeAddress(rowCount, rowCount + count - 1, targetColumnIndex, targetColumnIndex);
        sheet.addMergedRegionUnsafe(cellRangeAddress);
        rowCount += count;
      }
    }

    // 該方法將目標列根據值是否相同連續可合併,儲存可合併的行數 
    private List<Integer> getGroupCountList(List<String> exportDataList){
      if (CollectionUtils.isEmpty(exportDataList)) {
        return new ArrayList<>();
      }

      List<Integer> groupCountList = new ArrayList<>();
      int count = 1;

      for (int i = 1; i < exportDataList.size(); i++) {
        if (exportDataList.get(i).equals(exportDataList.get(i - 1))) {
          count++;
        } else {
          groupCountList.add(count);
          count = 1;
        }
      }
      // 處理完最後一條後
      groupCountList.add(count);
      return groupCountList;
    }
  }

// 修改WriteSheet的程式碼如下 
  public static void writeExcel() {
    String fileName = getPath();
    ExcelWriter excelWriter = EasyExcel.write(fileName).excelType(ExcelTypeEnum.XLSX).build();

    List<DemoData> demoDataList = data1();
    // 寫sheet的時候註冊相應的自定義合併單元格策略
    WriteSheet writeSheet = EasyExcel.writerSheet("模板1").head(DemoData.class)
    .registerWriteHandler(new CustomMergeStrategy(demoDataList.stream().map(DemoData::getString).collect(Collectors.toList()), 0))
    .build();
    excelWriter.write(demoDataList, writeSheet);
    excelWriter.finish();
  }

開啟輸出的excel檔案後如下,可以看到第一列有相同值的單元格已經合併了,成功實現 

EasyExcel-合併單元格

同理若要合併第三列的資料,則可以在註冊一個sheet寫處理器,程式碼如下

  public static void writeExcel() {
    String fileName = getPath();
    ExcelWriter excelWriter = EasyExcel.write(fileName).excelType(ExcelTypeEnum.XLSX).build();

    List<DemoData> demoDataList = data1();
    WriteSheet writeSheet = EasyExcel.writerSheet("模板1").head(DemoData.class)
    .registerWriteHandler(new CustomMergeStrategy(demoDataList.stream().map(DemoData::getString).collect(Collectors.toList()), 0))
    .registerWriteHandler(new CustomMergeStrategy(demoDataList.stream().map(o -> o.getDoubleData().toString()).collect(Collectors.toList()), 2))
    .build();
    excelWriter.write(demoDataList, writeSheet);
    excelWriter.finish();
  }

excel開啟如下:

EasyExcel-合併單元格

1.3 寫多個sheet

  public static void writeExcel() {
    String fileName = getPath();
    ExcelWriter excelWriter = EasyExcel.write(fileName).excelType(ExcelTypeEnum.XLSX).build();

    List<DemoData> demoDataList = data1();
    WriteSheet writeSheet = EasyExcel.writerSheet("模板1").head(DemoData.class)
    .registerWriteHandler(new CustomMergeStrategy(demoDataList.stream().map(DemoData::getString).collect(Collectors.toList()), 0))
    .registerWriteHandler(new CustomMergeStrategy(demoDataList.stream().map(o -> o.getDoubleData().toString()).collect(Collectors.toList()), 2))
    .build();
    excelWriter.write(demoDataList, writeSheet);

    WriteSheet writeSheet1 = EasyExcel.writerSheet("模板2").head(DemoData.class).build();
    excelWriter.write(data1(), writeSheet1);
    excelWriter.finish();
  }

輸出excel可以看到已經有兩個sheet了

EasyExcel-合併單元格

 

1.4 WriteTable

若業務需求要求在同一個sheet中寫多個表,就需要用到WriteTable了。只定義一個WriteSheet,有幾個表就定義幾個WriteTable

  public static void writeExcel01() {
    String fileName = getPath();
    ExcelWriter excelWriter = EasyExcel.write(fileName).excelType(ExcelTypeEnum.XLSX).build();
    WriteSheet writeSheet = EasyExcel.writerSheet("模板").needHead(Boolean.FALSE).build();

    List<DemoData> demoDataList = data1();
    // 需要表頭設定為true,WriteTable一些屬性會繼承自WriteSheet
    WriteTable writeTable = EasyExcel.writerTable(1).head(DemoData.class).needHead(Boolean.TRUE)
        .registerWriteHandler(new CustomMergeStrategy(demoDataList.stream().map(DemoData::getString).collect(Collectors.toList()), 0))
        .registerWriteHandler(new CustomMergeStrategy(demoDataList.stream().map(o -> o.getDoubleData().toString()).collect(Collectors.toList()), 2))
        .build();
    excelWriter.write(demoDataList, writeSheet, writeTable);

    WriteTable writeTable1 = EasyExcel.writerTable(2).head(DemoData.class).needHead(Boolean.TRUE).build();
    excelWriter.write(data1(), writeSheet, writeTable1);
    excelWriter.finish();
  }

開啟excel表格如下 

EasyExcel-合併單元格

 

 

結語 

如有錯誤或者優化點歡迎指出,本文參考自EasyExcel文件

相關文章