2

I am getting the below Excel error when I use addMergedRegion. This is my code:

spreadsheet.addMergedRegion(new CellRangeAddress(a+1, b, 1, 1));

The error I get in Excel says that the downloaded file has "unreadable content" and asks if I want to recover the contents. I click yes.

Excel then opens the file and a window says that it repaired or removed what was wrong and then it says:

enter image description here

I check those sheets for the cell I wanted merged, and it's merged exactly the way I want it.

So why is Excel giving me this error, and how do I fix it? Thanks.

Edit 1: Added additional code. I have a sheet like this and I want to merge the rows with same value. Input enter image description here

Output enter image description here

        int i=primrowCountSplice; int b=i; int a=i;
        for (i=primrowCountSplice;i<primrowCount-1;i++) {

         if(spreadsheet.getRow(i).getCell(1).getStringCellValue().equals(spreadsheet.getRow(i+1).getCell(1).getStringCellValue()))
            {
                out.println("i: " + i);
                out.println(spreadsheet.getRow(i).getCell(1).getStringCellValue());
                out.println(spreadsheet.getRow(i+1).getCell(1).getStringCellValue());
                a = b;
                out.println("a: " + a);
            } else {

              b = i;
             out.println("b:  " + b);
         }
            spreadsheet.addMergedRegion(new CellRangeAddress(a+1, b, 1, 1));
  • This one line of code is not sufficient. What is `a`? What is `b`? Are there more merged regions in that sheet? To be able to answer we would need a [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example). – Axel Richter Jan 23 '23 at 11:30
  • 1
    What `apache poi` version are you using? According to your program logic: `a = b;` ... `spreadsheet.addMergedRegion(new CellRangeAddress(a+1, b, 1, 1));`; `firstRow` can be greater than `lastRow` in `CellRangeAddress` and that should not be so. And current `apache poi` versions would not allow this. – Axel Richter Jan 23 '23 at 14:42

1 Answers1

1

Your programming logic is wrong and produces overlapping merged regions. That is what Excel does not tolerate and alerts the error about.

Your program does the following: It starts with int b=i; int a=i; where i points to the first row. The values in first row and second row are equal. So your program sets a = b; so that now both a and b point to the first row. Then it merges spreadsheet.addMergedRegion(new CellRangeAddress(a+1, b, 1, 1));. So it creates <mergeCell ref="B2:B1"/>. This is not really correct as it should be <mergeCell ref="B1:B2"/>. But that Excel would tolerate. Now i increases and points to second row. The values in second row and third row are not equal. So your program sets b = i;. Now b points to second row but a has not changed and points to first row. Now your code merges a+1 and b which both points to second row. So it creates <mergeCell ref="B2:B2"/>. That one-cell-merged-region is useless but would be tolerated by Excel. But it additionally overlaps the former created <mergeCell ref="B2:B1"/>. And here Excel's tolerance ends.

The following Minimal, Reproducible Example shows a working program logic. It additional shows what Minimal, Reproducible Example really means.

Have a Excel workbook ExcelExample.xlsx containing following in columns A and B of first sheet:

Col1        Col2
Record1     Value1
Record2     Value1
Record3     Value2
Record4     Value3
Record5     Value3
Record6     Value3
Record7     Value4
Record8     Value5
Record9     Value5
Record10    Value5
Record11    Value6
Record12    Value7
Record13    Value7
Record14    Value7
Record15    Value8
Record16    Value9
Record17    Value10
Record18    Value10
Record19    Value10
Record20    Value10

Then do running the following code:

import java.io.FileInputStream;
import java.io.FileOutputStream;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;

public class ExcelMergeRowsByContent {
    
 static void mergeRowsByContent(Sheet sheet, int col) {
  int firstRow = sheet.getFirstRowNum();
  int lastRow = sheet.getLastRowNum();
  DataFormatter dataFormatter = new DataFormatter();
  dataFormatter.setUseCachedValuesForFormulaCells(true);
  int fromRow = firstRow;
  int toRow = 0;
  boolean merge = false;
  while(fromRow <= lastRow) {
   Row row1 = sheet.getRow(fromRow); if (row1 == null) row1 = sheet.createRow(fromRow);
   Cell cell1 = row1.getCell(col);
   String cellValue1 = dataFormatter.formatCellValue(cell1);
   toRow = fromRow + 1;
   while (toRow <= lastRow) { // check whether following values are equal
    Row row2 = sheet.getRow(toRow); if (row2 == null) row2 = sheet.createRow(toRow);
    Cell cell2 = row2.getCell(col);
    String cellValue2 = dataFormatter.formatCellValue(cell2);
    System.out.println("cell value in row " + fromRow + " = " + cellValue1 + "; cell value in row " + toRow + " = " + cellValue2);
    if (cellValue2.equals(cellValue1)) {
     merge = true; // merging is needed      
     toRow++; // try whether next row also has equal value
    } else {
     break; // values were not equal, so break searching       
    }
   }
   if (merge) {
    toRow--; // merge only rows where values are equal, last toRow was not
    System.out.println("merging from row " + fromRow + " to row " + toRow);
    sheet.addMergedRegion(new CellRangeAddress(fromRow, toRow, col, col));
    fromRow = toRow;
   } 
   merge = false;
   fromRow++;
  }
 }

 public static void main(String[] args) throws Exception {
  try (
   FileInputStream in = new FileInputStream("./ExcelExample.xlsx"); FileOutputStream out = new FileOutputStream("./ExcelExampleNew.xlsx");
   //FileInputStream in = new FileInputStream("./ExcelExample.xls"); FileOutputStream out = new FileOutputStream("./ExcelExampleNew.xls");
   Workbook workbook = WorkbookFactory.create(in); ) {
   
   Sheet sheet = workbook.getSheetAt(0);

   mergeRowsByContent(sheet, 1);
  
   workbook.write(out);
  }
 }
}

After that it should have produced following result in ExcelExampleNew.xlsx:

enter image description here

Disclaimer: This code is tested and runs using current apache poi 5.2.3. Older apache poi versions are outdated and not supported anymore.

Axel Richter
  • 56,077
  • 6
  • 60
  • 87