This is an automated email from the ASF dual-hosted git repository.

centic pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/poi.git

commit d93a29ae678ebd82c7a488bd3a9202326fd5fa3b
Author: Dominik Stadler <[email protected]>
AuthorDate: Sun Jan 11 18:10:46 2026 +0100

    Optimize handling of large XSSFTables
    
    The current implementation calls updateHeaders() very often
    causing cloning a sheet to take very long with high CPU.
    
    We can optimize a number of things here:
    * Use getTableColumnArray() as the List-based methods
    have very costly implementations of hasNext()/next()
    * Avoid some duplicated calls to updateHeaders()
    
    There are likely more aggressive optimizations like
    only calling updateHeaders() once after cloning,
    but this would require more invasive changes in this
    rarely used code-area.
---
 .../org/apache/poi/xssf/usermodel/XSSFTable.java   | 25 ++++++++++++++++------
 .../apache/poi/xssf/usermodel/TestXSSFTable.java   | 16 +++++++++++++-
 2 files changed, 33 insertions(+), 8 deletions(-)

diff --git 
a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFTable.java 
b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFTable.java
index 15cd3bbaf8..8b279fc720 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFTable.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFTable.java
@@ -211,7 +211,9 @@ public class XSSFTable extends POIXMLDocumentPart 
implements Table {
            List<XSSFTableColumn> columns = new ArrayList<>();
             CTTableColumns ctTableColumns = ctTable.getTableColumns();
             if (ctTableColumns != null) {
-                for (CTTableColumn column : 
ctTableColumns.getTableColumnList()) {
+                // Use Array and not List-based access, as list-iteration is
+                // very slow for large tables
+                for (CTTableColumn column : 
ctTableColumns.getTableColumnArray()) {
                     XSSFTableColumn tableColumn = new XSSFTableColumn(this, 
column);
                     columns.add(tableColumn);
                 }
@@ -308,11 +310,12 @@ public class XSSFTable extends POIXMLDocumentPart 
implements Table {
                     tableStart.getCol() + newColumnCount - 1);
             AreaReference newTableArea = new AreaReference(tableStart, 
newTableEnd, version);
 
+            // setCellRef also calls updateHeaders()
             setCellRef(newTableArea);
+        } else {
+            updateHeaders();
         }
 
-        updateHeaders();
-
         return getColumns().get(columnIndex);
     }
 
@@ -353,7 +356,9 @@ public class XSSFTable extends POIXMLDocumentPart 
implements Table {
 
         CTTableColumns tableColumns = ctTable.getTableColumns();
         tableColumns.removeTableColumn(columnIndex);
-        tableColumns.setCount(tableColumns.getTableColumnList().size());
+        // Use Array and not List-based access, as list-iteration is
+        // very slow for large tables
+        tableColumns.setCount(tableColumns.getTableColumnArray().length);
         updateReferences();
         updateHeaders();
     }
@@ -406,7 +411,7 @@ public class XSSFTable extends POIXMLDocumentPart 
implements Table {
                 try {
                     ctTable.getTableStyleInfo().unsetName();
                 } catch (Exception e) {
-                    LOG.atDebug().log("Failed to unset style name", e);
+                    LOG.atDebug().log("Failed to unset style name: {}", e);
                 }
             }
             styleName = null;
@@ -821,13 +826,19 @@ public class XSSFTable extends POIXMLDocumentPart 
implements Table {
             int cellnum = firstHeaderColumn;
             CTTableColumns ctTableColumns = getCTTable().getTableColumns();
             if(ctTableColumns != null) {
-                for (CTTableColumn col : ctTableColumns.getTableColumnList()) {
+                // Use Array and not List-based access, as list-iteration is
+                // very slow for large tables
+                for (CTTableColumn col : ctTableColumns.getTableColumnArray()) 
{
                     XSSFCell cell = row.getCell(cellnum);
                     if (cell != null) {
                         String colName = formatter.formatCellValue(cell);
                         colName = colName.replace("\n", "_x000a_");
                         colName = colName.replace("\r", "_x000d_");
-                        col.setName(colName);
+
+                        // setName() is costly, let's only run it when 
necessary
+                        if (!colName.equals(col.getName())) {
+                            col.setName(colName);
+                        }
                     }
                     cellnum++;
                 }
diff --git 
a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFTable.java 
b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFTable.java
index 8cdf4706f3..5fb20b6152 100644
--- a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFTable.java
+++ b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFTable.java
@@ -39,7 +39,6 @@ import org.junit.jupiter.api.Test;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTable;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableStyleInfo;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
 
 import static org.junit.jupiter.api.Assertions.*;
 
@@ -784,4 +783,19 @@ public final class TestXSSFTable {
             }
         }
     }
+
+    @Test
+    void testGetStyleNameNull() throws IOException {
+        try (XSSFWorkbook wb = new XSSFWorkbook()) {
+            XSSFSheet sh = wb.createSheet();
+            AreaReference tableArea = new AreaReference("B2:B6", 
wb.getSpreadsheetVersion());
+            XSSFTable table = sh.createTable(tableArea);
+
+            assertNull(table.getStyleName());
+
+            
table.getCTTable().setTableStyleInfo(CTTableStyleInfo.Factory.newInstance());
+
+            assertNull(table.getStyleName());
+        }
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to