]> source.dussan.org Git - poi.git/commitdiff
[bug-66213] hack clone table code to avoid failing with edge cases
authorPJ Fanning <fanningpj@apache.org>
Sun, 14 Aug 2022 09:47:16 +0000 (09:47 +0000)
committerPJ Fanning <fanningpj@apache.org>
Sun, 14 Aug 2022 09:47:16 +0000 (09:47 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1903409 13f79535-47bb-0310-9956-ffa450edef68

poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFTable.java
poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFTable.java

index c62183a493147d6f0352ceca7bc49ff602d9d0ba..b2b41ce7f89417754656e072511736b334ab3996 100644 (file)
@@ -4302,6 +4302,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet, OoxmlSheetEx
      * @param t table to remove
      */
     public void removeTable(XSSFTable t) {
+        String rId = getRelationId(t);
         long id = t.getCTTable().getId();
         Map.Entry<String, XSSFTable> toDelete = null;
 
@@ -4314,10 +4315,12 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet, OoxmlSheetEx
             toDelete.getValue().onTableDelete();
             CTTableParts tblParts = worksheet.getTableParts();
             int matchedPos = -1;
-            for (int i = 0; i < tblParts.sizeOfTablePartArray(); i++) {
-                if (toDelete.getKey().equals(tblParts.getTablePartArray(i).getId())) {
-                    matchedPos = i;
-                    break;
+            if (rId != null) {
+                for (int i = 0; i < tblParts.sizeOfTablePartArray(); i++) {
+                    if (rId.equals(tblParts.getTablePartArray(i).getId())) {
+                        matchedPos = i;
+                        break;
+                    }
                 }
             }
             if (matchedPos != -1) {
@@ -4875,82 +4878,86 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet, OoxmlSheetEx
 
     static void cloneTables(XSSFSheet sheet) {
         for (XSSFTable table : sheet.getTables()) {
-            // clone table
-            XSSFTable clonedTable = sheet.createTable(table.getArea());
-            clonedTable.updateHeaders();
-
-            // clone style
-            clonedTable.setStyleName(table.getStyleName());
-            XSSFTableStyleInfo style = (XSSFTableStyleInfo)table.getStyle();
-            XSSFTableStyleInfo clonedStyle = (XSSFTableStyleInfo)clonedTable.getStyle();
-            if (style != null && clonedStyle != null) {
-                clonedStyle.setShowColumnStripes(style.isShowColumnStripes());
-                clonedStyle.setShowRowStripes(style.isShowRowStripes());
-                clonedStyle.setFirstColumn(style.isShowFirstColumn());
-                clonedStyle.setLastColumn(style.isShowLastColumn());
+
+            // clone table; XSSFTable.setArea fails and throws exception for too small tables
+            XSSFTable clonedTable = null;
+            if (table.supportsAreaReference(table.getArea())) {
+                clonedTable = sheet.createTable(table.getArea());
             }
 
-            //clone autofilter
-            clonedTable.getCTTable().setAutoFilter(table.getCTTable().getAutoFilter());
+            if (clonedTable != null) {
+                clonedTable.updateHeaders();
+
+                // clone style
+                clonedTable.setStyleName(table.getStyleName());
+                XSSFTableStyleInfo style = (XSSFTableStyleInfo)table.getStyle();
+                XSSFTableStyleInfo clonedStyle = (XSSFTableStyleInfo)clonedTable.getStyle();
+                if (style != null && clonedStyle != null) {
+                    clonedStyle.setShowColumnStripes(style.isShowColumnStripes());
+                    clonedStyle.setShowRowStripes(style.isShowRowStripes());
+                    clonedStyle.setFirstColumn(style.isShowFirstColumn());
+                    clonedStyle.setLastColumn(style.isShowLastColumn());
+                }
 
-            //clone totalsrow
-            int totalsRowCount = table.getTotalsRowCount();
-            if (totalsRowCount == 1) { // never seen more than one totals row
-                XSSFRow totalsRow = sheet.getRow(clonedTable.getEndCellReference().getRow());
-                if (clonedTable.getCTTable().getTableColumns().getTableColumnList().size() > 0) {
-                    clonedTable.getCTTable().setTotalsRowCount(totalsRowCount);
-                    for (int i = 0; i < clonedTable.getCTTable().getTableColumns().getTableColumnList().size(); i++) {
-                        CTTableColumn tableCol = table.getCTTable().getTableColumns().getTableColumnList().get(i);
-                        CTTableColumn clonedTableCol = clonedTable.getCTTable().getTableColumns().getTableColumnList().get(i);
-                        clonedTableCol.setTotalsRowFunction(tableCol.getTotalsRowFunction());
-                        int intTotalsRowFunction = clonedTableCol.getTotalsRowFunction().intValue();
-                        sheet.getWorkbook().setCellFormulaValidation(false);
-                        if (intTotalsRowFunction == 10) { //custom
-                            CTTableFormula totalsRowFormula = tableCol.getTotalsRowFormula();
-                            clonedTableCol.setTotalsRowFormula(totalsRowFormula);
-                            totalsRow.getCell(clonedTable.getStartCellReference().getCol()+i).setCellFormula(totalsRowFormula.getStringValue());
-                        } else if (intTotalsRowFunction == 1) { //none
-                            //totalsRow.getCell(clonedTable.getStartCellReference().getCol()+i).setBlank();
-                        } else {
-                            String subtotalFormulaStart = getSubtotalFormulaStartFromTotalsRowFunction(intTotalsRowFunction);
-                            if (subtotalFormulaStart != null)
-                                totalsRow.getCell(clonedTable.getStartCellReference().getCol()+i).setCellFormula(subtotalFormulaStart + "," + clonedTable.getName() +"[" + clonedTableCol.getName()+ "])");
+                //clone autofilter
+                clonedTable.getCTTable().setAutoFilter(table.getCTTable().getAutoFilter());
+
+                //clone totalsrow
+                int totalsRowCount = table.getTotalsRowCount();
+                if (totalsRowCount == 1) { // never seen more than one totals row
+                    XSSFRow totalsRow = sheet.getRow(clonedTable.getEndCellReference().getRow());
+                    if (clonedTable.getCTTable().getTableColumns() != null
+                            && clonedTable.getCTTable().getTableColumns().getTableColumnList().size() > 0) {
+                        clonedTable.getCTTable().setTotalsRowCount(totalsRowCount);
+                        for (int i = 0; i < clonedTable.getCTTable().getTableColumns().getTableColumnList().size(); i++) {
+                            CTTableColumn tableCol = table.getCTTable().getTableColumns().getTableColumnList().get(i);
+                            CTTableColumn clonedTableCol = clonedTable.getCTTable().getTableColumns().getTableColumnList().get(i);
+                            clonedTableCol.setTotalsRowFunction(tableCol.getTotalsRowFunction());
+                            int intTotalsRowFunction = clonedTableCol.getTotalsRowFunction().intValue();
+                            sheet.getWorkbook().setCellFormulaValidation(false);
+                            if (intTotalsRowFunction == 10) { //custom
+                                CTTableFormula totalsRowFormula = tableCol.getTotalsRowFormula();
+                                clonedTableCol.setTotalsRowFormula(totalsRowFormula);
+                                totalsRow.getCell(clonedTable.getStartCellReference().getCol()+i).setCellFormula(totalsRowFormula.getStringValue());
+                            } else if (intTotalsRowFunction == 1) { //none
+                                //totalsRow.getCell(clonedTable.getStartCellReference().getCol()+i).setBlank();
+                            } else {
+                                String subtotalFormulaStart = getSubtotalFormulaStartFromTotalsRowFunction(intTotalsRowFunction);
+                                if (subtotalFormulaStart != null)
+                                    totalsRow.getCell(clonedTable.getStartCellReference().getCol()+i).setCellFormula(subtotalFormulaStart + "," + clonedTable.getName() +"[" + clonedTableCol.getName()+ "])");
+                            }
                         }
                     }
                 }
-            }
 
-            // clone calculated column formulas
-            if (clonedTable.getCTTable().getTableColumns() != null
-                    && clonedTable.getCTTable().getTableColumns().getTableColumnList().size() > 0) {
-                clonedTable.getCTTable().setTotalsRowCount(totalsRowCount);
-                for (int i = 0; i < clonedTable.getCTTable().getTableColumns().getTableColumnList().size(); i++) {
-                    CTTableColumn tableCol = table.getCTTable().getTableColumns().getTableColumnList().get(i);
-                    CTTableColumn clonedTableCol = clonedTable.getCTTable().getTableColumns().getTableColumnList().get(i);
-                    if (tableCol.getCalculatedColumnFormula() != null) {
-                        clonedTableCol.setCalculatedColumnFormula(tableCol.getCalculatedColumnFormula());
-                        CTTableFormula calculatedColumnFormula = clonedTableCol.getCalculatedColumnFormula();
-                        String formula = tableCol.getCalculatedColumnFormula().getStringValue();
-                        String clonedFormula = formula.replace(table.getName(), clonedTable.getName());
-                        calculatedColumnFormula.setStringValue(clonedFormula);
-                        int rFirst = clonedTable.getStartCellReference().getRow() + clonedTable.getHeaderRowCount();
-                        int rLast = clonedTable.getEndCellReference().getRow() - clonedTable.getTotalsRowCount();
-                        int c = clonedTable.getStartCellReference().getCol() + i;
-                        sheet.getWorkbook().setCellFormulaValidation(false);
-                        for (int r = rFirst; r <= rLast; r++) {
-                            XSSFRow row = sheet.getRow(r);
-                            if (row == null) {
-                                row = sheet.createRow(r);
+                // clone calculated column formulas
+                if (clonedTable.getCTTable().getTableColumns() != null
+                        && clonedTable.getCTTable().getTableColumns().getTableColumnList().size() > 0) {
+                    clonedTable.getCTTable().setTotalsRowCount(totalsRowCount);
+                    for (int i = 0; i < clonedTable.getCTTable().getTableColumns().getTableColumnList().size(); i++) {
+                        CTTableColumn tableCol = table.getCTTable().getTableColumns().getTableColumnList().get(i);
+                        CTTableColumn clonedTableCol = clonedTable.getCTTable().getTableColumns().getTableColumnList().get(i);
+                        if (tableCol.getCalculatedColumnFormula() != null) {
+                            clonedTableCol.setCalculatedColumnFormula(tableCol.getCalculatedColumnFormula());
+                            CTTableFormula calculatedColumnFormula = clonedTableCol.getCalculatedColumnFormula();
+                            String formula = tableCol.getCalculatedColumnFormula().getStringValue();
+                            String clonedFormula = formula.replace(table.getName(), clonedTable.getName());
+                            calculatedColumnFormula.setStringValue(clonedFormula);
+                            int rFirst = clonedTable.getStartCellReference().getRow() + clonedTable.getHeaderRowCount();
+                            int rLast = clonedTable.getEndCellReference().getRow() - clonedTable.getTotalsRowCount();
+                            int c = clonedTable.getStartCellReference().getCol() + i;
+                            sheet.getWorkbook().setCellFormulaValidation(false);
+                            for (int r = rFirst; r <= rLast; r++) {
+                                XSSFRow row = sheet.getRow(r); if (row == null) row = sheet.createRow(r);
+                                XSSFCell cell = row.getCell(c); if (cell == null) cell = row.createCell(c);
+                                cell.setCellFormula(clonedFormula);
                             }
-                            XSSFCell cell = row.getCell(c, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
-                            cell.setCellFormula(clonedFormula);
                         }
                     }
                 }
             }
 
             // remove old table
-            String rId = sheet.getRelationId(table);
             sheet.removeTable(table);
         }
     }
index 66d6898e456354945fa6f9eedc8ebdcd78b3d557..535683be6a09187a9c6da95baf765ba2521cb833 100644 (file)
@@ -508,13 +508,14 @@ public class XSSFTable extends POIXMLDocumentPart implements Table {
 
     boolean supportsAreaReference(final AreaReference tableArea) {
         int rowCount = (tableArea.getLastCell().getRow() - tableArea.getFirstCell().getRow()) + 1;
-        int minimumRowCount = 1 + getHeaderRowCount() + getTotalsRowCount();
+        int headerRowCount = Math.max(1, getHeaderRowCount());
+        int minimumRowCount = 1 + headerRowCount + getTotalsRowCount();
         return rowCount >= minimumRowCount;
     }
 
     /**
      * Set the area reference for the cells which this table covers. The area
-     * includes includes header rows and totals rows.
+     * includes header rows and totals rows.
      *
      * Updating the area with this method will create new column as necessary to
      * the right side of the table but will not modify any cell values.
index 4e716c55779d5144dbb6fbeb8320f281c8a36c65..2e3d1ec76e8596f5de3aa57b1e2e2474629c4177 100644 (file)
@@ -779,7 +779,7 @@ public final class TestXSSFTable {
                     XSSFSheet sheet0 = wb2.getSheetAt(0);
                     XSSFSheet sheet1 = wb2.getSheetAt(1);
                     assertEquals(1, sheet0.getTables().size());
-                    assertEquals(1, sheet1.getTables().size());
+                    assertEquals(0, sheet1.getTables().size());
                 }
             }
         }