diff --git a/odfdom/src/main/java/org/odftoolkit/odfdom/doc/table/OdfTableRow.java b/odfdom/src/main/java/org/odftoolkit/odfdom/doc/table/OdfTableRow.java index c2635583e..c186bf0a1 100644 --- a/odfdom/src/main/java/org/odftoolkit/odfdom/doc/table/OdfTableRow.java +++ b/odfdom/src/main/java/org/odftoolkit/odfdom/doc/table/OdfTableRow.java @@ -287,16 +287,18 @@ public OdfTableCell getCellByIndex(int index) { * @return the cell count */ public int getCellCount() { - OdfTable table = getTable(); - Set realCells = new HashSet<>(); - List coverList = - table.getCellCoverInfos(0, 0, table.getColumnCount() - 1, table.getRowCount() - 1); - int rowIndex = getRowIndex(); - for (int i = 0; i < table.getColumnCount(); i++) { - OdfTableCell cell = table.getOwnerCellByPosition(coverList, i, rowIndex); - realCells.add(cell); + // count cells by skipping covered-table-cell and taking into account number-columns-repeated attribute + int cellCount = 0; + for (Node node : new DomNodeList(maRowElement.getChildNodes())) { + if (node instanceof TableTableCellElement tableCell) { + if (tableCell.getTableNumberColumnsRepeatedAttribute() == null) { + cellCount++; + } else { + cellCount += tableCell.getTableNumberColumnsRepeatedAttribute(); + } + } } - return realCells.size(); + return cellCount; } /** diff --git a/odfdom/src/test/java/org/odftoolkit/odfdom/doc/table/TableCellCountTest.java b/odfdom/src/test/java/org/odftoolkit/odfdom/doc/table/TableCellCountTest.java new file mode 100644 index 000000000..4ab6b9ad5 --- /dev/null +++ b/odfdom/src/test/java/org/odftoolkit/odfdom/doc/table/TableCellCountTest.java @@ -0,0 +1,92 @@ +package org.odftoolkit.odfdom.doc.table; + +import static org.junit.Assert.assertEquals; +import static org.odftoolkit.odfdom.utils.ResourceUtilities.getAbsoluteInputPath; + +import junit.framework.AssertionFailedError; +import org.junit.Test; +import org.odftoolkit.odfdom.doc.OdfSpreadsheetDocument; + +public class TableCellCountTest { + + // The number of columns that Excel always uses. + // For example Excel puts if no cell values or covered cells + private static final int EXCEL_COLUMN_COUNT = 16384; + + @Test + public void verifyCellCountForLibreOfficeGeneratedSpreadsheet() { + // Spreadsheet created by LibreOffice on Mac version 25.8.4.2 (AARCH64) + try (OdfSpreadsheetDocument spreadsheet = loadSpreadsheetDocument("TestLibreOfficeSpreadsheetTableCellCount.ods")) { + OdfTable sheet = spreadsheet.getSpreadsheetTables().get(0); + assertEquals(3, sheet.getColumnCount()); + + // 3 cells merged so 2 covered cells + assertEquals(3 - 2 /* covered cells */, sheet.getRowByIndex(0).getCellCount()); + + // 2 cells merged so 1 covered cell + assertEquals(3 - 1 /* covered cell */, sheet.getRowByIndex(1).getCellCount()); + + // no merged cells + assertEquals(3, sheet.getRowByIndex(2).getCellCount()); + + // 2 cells merged over 2 rows (simplified XML): + // + // + // 1 + // + // + // + // 2 + // + // + // + // + // + // 2 + // + // + // so 1 covered cell in first row + assertEquals(3 - 1 /* covered cell */, sheet.getRowByIndex(3).getCellCount()); + // ... and 2 covered cells in second row + assertEquals(3 - 2 /* covered cells */, sheet.getRowByIndex(4).getCellCount()); + } + } + + @Test + public void verifyCellCountForExcelGeneratedSpreadsheet() { + // Spreadsheet created by Microsoft® Excel for Mac Version 16.106 (26020821) + try (OdfSpreadsheetDocument spreadsheet = loadSpreadsheetDocument("TestExcelSpreadsheetTableCellCount.ods")) { + OdfTable sheet = spreadsheet.getSpreadsheetTables().get(0); + assertEquals(EXCEL_COLUMN_COUNT, sheet.getColumnCount()); + + // 3 cells merged so 2 covered cells + assertEquals(EXCEL_COLUMN_COUNT - 2 /* covered cells */, sheet.getRowByIndex(0).getCellCount()); + + // 2 cells merged so 1 covered cell + assertEquals(EXCEL_COLUMN_COUNT - 1 /* covered cell */, sheet.getRowByIndex(1).getCellCount()); + + // no merged cells + assertEquals(EXCEL_COLUMN_COUNT, sheet.getRowByIndex(2).getCellCount()); + + // 2 cells merged over 2 rows so 1 covered cell in first row + assertEquals(EXCEL_COLUMN_COUNT - 1 /* covered cell */, sheet.getRowByIndex(3).getCellCount()); + // ... and 2 covered cells in second row + assertEquals(EXCEL_COLUMN_COUNT - 2 /* covered cells */, sheet.getRowByIndex(4).getCellCount()); + + // Excel always adds + // + // + // + assertEquals(EXCEL_COLUMN_COUNT, sheet.getRowByIndex(5).getCellCount()); + } + } + + private OdfSpreadsheetDocument loadSpreadsheetDocument(String filename) { + try { + return OdfSpreadsheetDocument.loadDocument( + getAbsoluteInputPath(filename)); + } catch (Exception ex) { + throw new AssertionFailedError(ex.getMessage()); + } + } +} diff --git a/odfdom/src/test/resources/test-input/TestExcelSpreadsheetTableCellCount.ods b/odfdom/src/test/resources/test-input/TestExcelSpreadsheetTableCellCount.ods new file mode 100644 index 000000000..8c4737fff Binary files /dev/null and b/odfdom/src/test/resources/test-input/TestExcelSpreadsheetTableCellCount.ods differ diff --git a/odfdom/src/test/resources/test-input/TestLibreOfficeSpreadsheetTableCellCount.ods b/odfdom/src/test/resources/test-input/TestLibreOfficeSpreadsheetTableCellCount.ods new file mode 100644 index 000000000..b194c2375 Binary files /dev/null and b/odfdom/src/test/resources/test-input/TestLibreOfficeSpreadsheetTableCellCount.ods differ