Combining Identical Adjacent Cells in Excel Files Generated with Java
When working with generated spreadsheets, you may need to merge neighboring cells that hold the same value to improve clarity. Apache POI provides a straightforwrad way to accomplish this in Java. Below is a complete example demonstrating how to create an Excel file, populate it with data, and dynamically merge cells in a given column when consecutive rows share identical content.
Dependencies
Add the following Maven coordinates to your project:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version>
</dependency>
Implementation
Start by preparing sample data and a method to apply merges based on a specific column.
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
public class ExcelMergeExample {
public static void main(String[] args) throws IOException {
String[] header = {"Category"};
String[] items = {"Fruit", "Fruit", "Vegetable", "Vegetable", "Vegetable", "Dairy"};
try (Workbook wb = new XSSFWorkbook()) {
Sheet sheet = wb.createSheet("Products");
Row headerRow = sheet.createRow(0);
headerRow.createCell(0).setCellValue(header[0]);
for (int i = 0; i < items.length; i++) {
Row row = sheet.createRow(i + 1);
row.createCell(0).setCellValue(items[i]);
}
mergeDuplicateCellsInColumn(sheet, 0, 1);
try (FileOutputStream fos = new FileOutputStream("merged_output.xlsx")) {
wb.write(fos);
}
}
}
private static void mergeDuplicateCellsInColumn(Sheet sheet, int colIndex, int dataStartRow) {
int lastRow = sheet.getLastRowNum();
if (lastRow < dataStartRow) return;
int mergeStart = dataStartRow;
String currentValue = sheet.getRow(dataStartRow).getCell(colIndex).getStringCellValue();
for (int r = dataStartRow + 1; r <= lastRow; r++) {
Row row = sheet.getRow(r);
if (row == null) continue;
Cell cell = row.getCell(colIndex);
if (cell == null) continue;
String cellValue = cell.getStringCellValue();
if (!cellValue.equals(currentValue)) {
if (r - 1 > mergeStart) {
sheet.addMergedRegion(new CellRangeAddress(mergeStart, r - 1, colIndex, colIndex));
}
mergeStart = r;
currentValue = cellValue;
}
}
if (lastRow > mergeStart) {
sheet.addMergedRegion(new CellRangeAddress(mergeStart, lastRow, colIndex, colIndex));
}
}
}
Running this code produces an merged_output.xlsx file where consecutive "Fruit", "Vegetable", and "Dairy" cels are merged, leaving the first cell of each group12