code: private boolean processSavingMergedCell(final Cell currentCell, final Sheet sheet,
              final List<CellRangeAddress> mergedRanges, final Configuration config) {
  
          final int row = currentCell.getRowIndex();
          final int column = currentCell.getColumnIndex();
  
          if(row <= 0) {
              return false;
          }
  
          // 上のセルと比較する
          final String value = POIUtils.getCellContents(currentCell, config.getCellFormatter());
          String upperValue = POIUtils.getCellContents(POIUtils.getCell(sheet, column, row-1), config.getCellFormatter());
  
          // 結合されている場合、結合の先頭セルを取得する
          int startRow = row - 1;
          CellRangeAddress currentMergedRange = null;
          for(CellRangeAddress range : mergedRanges) {
              // 列が範囲外の場合
              if((range.getFirstColumn() > column) || (column > range.getLastColumn())) {
                  continue;
              }
  
              // 行が範囲外の場合
              if((range.getFirstRow() > startRow) || (startRow > range.getLastRow())) {
                  continue;
              }
  
              upperValue = POIUtils.getCellContents(POIUtils.getCell(sheet, column, range.getFirstRow()), config.getCellFormatter());
              currentMergedRange = range;
              break;
          }
  
          if(!value.equals(upperValue)) {
              // 値が異なる場合は結合しない
              return false;
          }
  
          // 既に結合済みの場合は一端解除する
          if(currentMergedRange != null) {
              startRow = currentMergedRange.getFirstRow();
              mergedRanges.remove(currentMergedRange);
              POIUtils.removeMergedRange(sheet, currentMergedRange);
          }
  
          final CellRangeAddress newRange = POIUtils.mergeCells(sheet, column, startRow, column, row);
          mergedRanges.add(newRange);
          return true;
  
      }
docs: 上部のセルと同じ値の場合マージする
  @param currentCell
  @param sheet
  @param mergedRanges
  @param config
  @return