You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by fa...@apache.org on 2022/07/26 21:42:24 UTC

svn commit: r1903037 - in /poi/trunk/poi-ooxml/src: main/java/org/apache/poi/xssf/streaming/ main/java/org/apache/poi/xssf/usermodel/ test/java/org/apache/poi/xssf/streaming/

Author: fanningpj
Date: Tue Jul 26 21:42:24 2022
New Revision: 1903037

URL: http://svn.apache.org/viewvc?rev=1903037&view=rev
Log:
[bug-65562] derive sheet dimensions when outputting SXSSFSheets

Modified:
    poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFRow.java
    poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFSheet.java
    poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java
    poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
    poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xssf/streaming/TestSXSSFWorkbook.java

Modified: poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFRow.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFRow.java?rev=1903037&r1=1903036&r2=1903037&view=diff
==============================================================================
--- poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFRow.java (original)
+++ poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFRow.java Tue Jul 26 21:42:24 2022
@@ -141,6 +141,7 @@ public class SXSSFRow implements Row, Co
         checkBounds(column);
         SXSSFCell cell = new SXSSFCell(this, type);
         _cells.put(column, cell);
+        _sheet.trackNewCell(cell);
         return cell;
     }
 

Modified: poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFSheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFSheet.java?rev=1903037&r1=1903036&r2=1903037&view=diff
==============================================================================
--- poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFSheet.java (original)
+++ poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFSheet.java Tue Jul 26 21:42:24 2022
@@ -27,6 +27,8 @@ import java.util.Set;
 import java.util.Spliterator;
 import java.util.TreeMap;
 
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 import org.apache.poi.ss.SpreadsheetVersion;
 import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.ss.util.CellAddress;
@@ -47,6 +49,8 @@ import org.openxmlformats.schemas.spread
  * Streaming version of XSSFSheet implementing the "BigGridDemo" strategy.
  */
 public class SXSSFSheet implements Sheet, OoxmlSheetExtensions {
+    private static final Logger LOG = LogManager.getLogger(SXSSFSheet.class);
+
     /*package*/ final XSSFSheet _sh;
     protected final SXSSFWorkbook _workbook;
     private final TreeMap<Integer,SXSSFRow> _rows = new TreeMap<>();
@@ -56,14 +60,38 @@ public class SXSSFSheet implements Sheet
     private int outlineLevelRow;
     private int lastFlushedRowNumber = -1;
     private boolean allFlushed;
+    private int leftMostColumn = SpreadsheetVersion.EXCEL2007.getLastColumnIndex();
+    private int rightMostColumn;
 
     protected SXSSFSheet(SXSSFWorkbook workbook, XSSFSheet xSheet, int randomAccessWindowSize) {
         _workbook = workbook;
         _sh = xSheet;
+        calculateLeftAndRightMostColumns(xSheet);
         setRandomAccessWindowSize(randomAccessWindowSize);
         _autoSizeColumnTracker = new AutoSizeColumnTracker(this);
     }
 
+    private void calculateLeftAndRightMostColumns(XSSFSheet xssfSheet) {
+        if (_workbook.shouldCalculateSheetDimensions()) {
+            int rowCount = 0;
+            int leftMostColumn = Integer.MAX_VALUE;
+            int rightMostColumn = 0;
+            for (Row row : xssfSheet) {
+                rowCount++;
+                if (row.getFirstCellNum() < leftMostColumn) {
+                    final int first = row.getFirstCellNum();
+                    final int last = row.getLastCellNum() - 1;
+                    leftMostColumn = Math.min(first, leftMostColumn);
+                    rightMostColumn = Math.max(last, rightMostColumn);
+                }
+            }
+            if (rowCount > 0) {
+                this.leftMostColumn = leftMostColumn;
+                this.rightMostColumn = rightMostColumn;
+            }
+        }
+    }
+
     public SXSSFSheet(SXSSFWorkbook workbook, XSSFSheet xSheet) throws IOException {
         _workbook = workbook;
         _sh = xSheet;
@@ -2106,4 +2134,21 @@ public class SXSSFSheet implements Sheet
     public void shiftColumns(int startColumn, int endColumn, int n){
         throw new UnsupportedOperationException("Not Implemented");
     }
+
+    void trackNewCell(SXSSFCell cell) {
+        leftMostColumn = Math.min(cell.getColumnIndex(), leftMostColumn);
+        rightMostColumn = Math.max(cell.getColumnIndex(), rightMostColumn);
+    }
+
+    void deriveDimension() {
+        if (_workbook.shouldCalculateSheetDimensions()) {
+            try {
+                CellRangeAddress cellRangeAddress = new CellRangeAddress(
+                        getFirstRowNum(), getLastRowNum(), leftMostColumn, rightMostColumn);
+                _sh.setDimensionOverride(cellRangeAddress);
+            } catch (Exception e) {
+                LOG.atDebug().log("Failed to set dimension details on sheet", e);
+            }
+        }
+    }
 }

Modified: poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java?rev=1903037&r1=1903036&r2=1903037&view=diff
==============================================================================
--- poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java (original)
+++ poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java Tue Jul 26 21:42:24 2022
@@ -136,6 +136,8 @@ public class SXSSFWorkbook implements Wo
      */
     protected Zip64Mode zip64Mode = Zip64Mode.Always;
 
+    private boolean shouldCalculateSheetDimensions = true;
+
     /**
      * Construct a new workbook with default row window size
      */
@@ -351,6 +353,24 @@ public class SXSSFWorkbook implements Wo
         _compressTmpFiles = compress;
     }
 
+    /**
+     * @param shouldCalculateSheetDimensions defaults to <code>true</code>, set to <code>false</code> if
+     *                                       the calculated dimensions are causing trouble
+     * @since POI 5.2.3
+     */
+    public void setShouldCalculateSheetDimensions(boolean shouldCalculateSheetDimensions) {
+        this.shouldCalculateSheetDimensions = shouldCalculateSheetDimensions;
+    }
+
+    /**
+     * @return shouldCalculateSheetDimensions defaults to <code>true</code>, set to <code>false</code> if
+     * the calculated dimensions are causing trouble
+     * @since POI 5.2.3
+     */
+    public boolean shouldCalculateSheetDimensions() {
+        return shouldCalculateSheetDimensions;
+    }
+
     @Internal
     protected SharedStringsTable getSharedStringSource() {
         return _sharedStringSource;
@@ -971,8 +991,10 @@ public class SXSSFWorkbook implements Wo
             }
 
             //Substitute the template entries with the generated sheet data files
-            try (ZipSecureFile zf = new ZipSecureFile(tmplFile);
-                 ZipFileZipEntrySource source = new ZipFileZipEntrySource(zf)) {
+            try (
+                    ZipSecureFile zf = new ZipSecureFile(tmplFile);
+                    ZipFileZipEntrySource source = new ZipFileZipEntrySource(zf)
+            ) {
                 injectData(source, stream);
             }
         } finally {
@@ -1012,8 +1034,8 @@ public class SXSSFWorkbook implements Wo
     }
 
     protected void flushSheets() throws IOException {
-        for (SXSSFSheet sheet : _xFromSxHash.values())
-        {
+        for (SXSSFSheet sheet : _xFromSxHash.values()) {
+            sheet.deriveDimension();
             sheet.flushRows();
         }
     }

Modified: poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java?rev=1903037&r1=1903036&r2=1903037&view=diff
==============================================================================
--- poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java (original)
+++ poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java Tue Jul 26 21:42:24 2022
@@ -106,6 +106,7 @@ public class XSSFSheet extends POIXMLDoc
     private List<CellRangeAddress> arrayFormulas;
     private final XSSFDataValidationHelper dataValidationHelper;
     private XSSFVMLDrawing xssfvmlDrawing;
+    private CellRangeAddress dimensionOverride;
 
     /**
      * Creates new XSSFSheet   - called by XSSFWorkbook to create a sheet from scratch.
@@ -3747,29 +3748,34 @@ public class XSSFSheet extends POIXMLDoc
             }*/
         }
 
-        int minCell = Integer.MAX_VALUE, maxCell = Integer.MIN_VALUE;
-        for(Map.Entry<Integer, XSSFRow> entry : _rows.entrySet()) {
-            XSSFRow row = entry.getValue();
-
-            // first perform the normal write actions for the row
-            row.onDocumentWrite();
-
-            // then calculate min/max cell-numbers for the worksheet-dimension
-            if(row.getFirstCellNum() != -1) {
-                minCell = Math.min(minCell, row.getFirstCellNum());
+        CellRangeAddress cellRangeAddress = dimensionOverride;
+        if (cellRangeAddress == null) {
+            int minCell = Integer.MAX_VALUE, maxCell = Integer.MIN_VALUE;
+            for(Map.Entry<Integer, XSSFRow> entry : _rows.entrySet()) {
+                XSSFRow row = entry.getValue();
+
+                // first perform the normal write actions for the row
+                row.onDocumentWrite();
+
+                // then calculate min/max cell-numbers for the worksheet-dimension
+                if(row.getFirstCellNum() != -1) {
+                    minCell = Math.min(minCell, row.getFirstCellNum());
+                }
+                if(row.getLastCellNum() != -1) {
+                    maxCell = Math.max(maxCell, row.getLastCellNum()-1);
+                }
             }
-            if(row.getLastCellNum() != -1) {
-                maxCell = Math.max(maxCell, row.getLastCellNum()-1);
+
+            // finally, if we had at least one cell we can populate the optional dimension-field
+            if(minCell != Integer.MAX_VALUE) {
+                cellRangeAddress = new CellRangeAddress(getFirstRowNum(), getLastRowNum(), minCell, maxCell);
             }
         }
-
-        // finally, if we had at least one cell we can populate the optional dimension-field
-        if(minCell != Integer.MAX_VALUE) {
-            String ref = new CellRangeAddress(getFirstRowNum(), getLastRowNum(), minCell, maxCell).formatAsString();
-            if(worksheet.isSetDimension()) {
-                worksheet.getDimension().setRef(ref);
+        if (cellRangeAddress != null) {
+            if (worksheet.isSetDimension()) {
+                worksheet.getDimension().setRef(cellRangeAddress.formatAsString());
             } else {
-                worksheet.addNewDimension().setRef(ref);
+                worksheet.addNewDimension().setRef(cellRangeAddress.formatAsString());
             }
         }
 
@@ -4051,6 +4057,9 @@ public class XSSFSheet extends POIXMLDoc
      * @since POI 5.2.3
      */
     public CellRangeAddress getDimension() {
+        if (dimensionOverride != null) {
+            return dimensionOverride;
+        }
         CTSheetDimension ctSheetDimension = worksheet.getDimension();
         String ref = ctSheetDimension == null ? null : ctSheetDimension.getRef();
         if (ref != null) {
@@ -4845,4 +4854,14 @@ public class XSSFSheet extends POIXMLDoc
     public XSSFHeaderFooterProperties getHeaderFooterProperties() {
         return new XSSFHeaderFooterProperties(getSheetTypeHeaderFooter());
     }
+
+    /**
+     * Currently, this is for internal use. Overrides the default dimensions of the sheet.
+     * @param dimension {@link CellRangeAddress}, <code>null</code> removes the existing override
+     * @since POI 5.2.3
+     */
+    @Beta
+    public void setDimensionOverride(CellRangeAddress dimension) {
+        this.dimensionOverride = dimension;
+    }
 }

Modified: poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xssf/streaming/TestSXSSFWorkbook.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xssf/streaming/TestSXSSFWorkbook.java?rev=1903037&r1=1903036&r2=1903037&view=diff
==============================================================================
--- poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xssf/streaming/TestSXSSFWorkbook.java (original)
+++ poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xssf/streaming/TestSXSSFWorkbook.java Tue Jul 26 21:42:24 2022
@@ -48,6 +48,7 @@ import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.poi.ss.usermodel.Workbook;
 import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.xssf.SXSSFITestDataProvider;
 import org.apache.poi.xssf.XSSFTestDataSamples;
@@ -559,6 +560,45 @@ public final class TestSXSSFWorkbook ext
             }
         }
     }
+
+    @Test
+    void addDimension() throws IOException {
+        try (
+                SXSSFWorkbook wb = new SXSSFWorkbook();
+                UnsynchronizedByteArrayOutputStream bos = new UnsynchronizedByteArrayOutputStream()
+        ) {
+            SXSSFSheet sheet = wb.createSheet();
+            sheet.createRow(2).createCell(3).setCellValue("top left");
+            sheet.createRow(6).createCell(5).setCellValue("bottom right");
+            assertEquals(2, sheet.getFirstRowNum());
+            assertEquals(6, sheet.getLastRowNum());
+            wb.write(bos);
+            try (XSSFWorkbook xssfWorkbook = new XSSFWorkbook(bos.toInputStream())) {
+                XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(0);
+                assertEquals(CellRangeAddress.valueOf("D3:F7"), xssfSheet.getDimension());
+            }
+        }
+    }
+
+    @Test
+    void addDimensionDisabled() throws IOException {
+        try (
+                SXSSFWorkbook wb = new SXSSFWorkbook();
+                UnsynchronizedByteArrayOutputStream bos = new UnsynchronizedByteArrayOutputStream()
+        ) {
+            wb.setShouldCalculateSheetDimensions(false);
+            SXSSFSheet sheet = wb.createSheet();
+            sheet.createRow(2).createCell(3).setCellValue("top left");
+            sheet.createRow(6).createCell(5).setCellValue("bottom right");
+            assertEquals(2, sheet.getFirstRowNum());
+            assertEquals(6, sheet.getLastRowNum());
+            wb.write(bos);
+            try (XSSFWorkbook xssfWorkbook = new XSSFWorkbook(bos.toInputStream())) {
+                XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(0);
+                assertEquals(CellRangeAddress.valueOf("A1:A1"), xssfSheet.getDimension());
+            }
+        }
+    }
 
     @Override
     @Disabled("not implemented")



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org