]> source.dussan.org Git - poi.git/commitdiff
#58200 Prepare for evaluating SXSSF cell formulas in limited cases
authorNick Burch <nick@apache.org>
Fri, 31 Jul 2015 19:19:33 +0000 (19:19 +0000)
committerNick Burch <nick@apache.org>
Fri, 31 Jul 2015 19:19:33 +0000 (19:19 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1693641 13f79535-47bb-0310-9956-ffa450edef68

src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCreationHelper.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFFormulaEvaluator.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java
src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java
src/ooxml/java/org/apache/poi/xssf/streaming/SheetDataWriter.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCreationHelper.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFormulaEvaluator.java

diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCreationHelper.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCreationHelper.java
new file mode 100644 (file)
index 0000000..d641583
--- /dev/null
@@ -0,0 +1,48 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.xssf.streaming;
+
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+import org.apache.poi.xssf.usermodel.XSSFCreationHelper;
+import org.apache.poi.xssf.usermodel.XSSFRichTextString;
+
+/**
+ * Streaming Creation Helper, which performs some actions
+ *  based on the Streaming Workbook, and some on the related
+ *  regular XSSF Workbook
+ */
+public class SXSSFCreationHelper extends XSSFCreationHelper {
+    private static POILogger logger = POILogFactory.getLogger(SXSSFCreationHelper.class);
+    
+    private SXSSFWorkbook wb;
+    
+    public SXSSFCreationHelper(SXSSFWorkbook workbook) {
+        super(workbook.getXSSFWorkbook());
+        this.wb = workbook;
+    }
+
+    public XSSFRichTextString createRichTextString(String text) {
+        logger.log(POILogger.INFO, "SXSSF doesn't support Rich Text Strings, any formatting information will be lost");
+        return new XSSFRichTextString(text);
+    }
+
+    public SXSSFFormulaEvaluator createFormulaEvaluator() {
+        return new SXSSFFormulaEvaluator(wb);
+    }
+}
diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFFormulaEvaluator.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFFormulaEvaluator.java
new file mode 100644 (file)
index 0000000..21ae8c2
--- /dev/null
@@ -0,0 +1,77 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.xssf.streaming;
+
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
+
+/**
+ * Streaming-specific Formula Evaluator, which is able to 
+ *  lookup cells within the current Window.
+ */
+public class SXSSFFormulaEvaluator extends XSSFFormulaEvaluator {
+    private static POILogger logger = POILogFactory.getLogger(SXSSFFormulaEvaluator.class);
+    
+    private SXSSFWorkbook wb;
+    
+    public SXSSFFormulaEvaluator(SXSSFWorkbook workbook) {
+        super(workbook.getXSSFWorkbook());
+        this.wb = workbook;
+    }
+    
+    /**
+     * For active worksheets only, will loop over rows and
+     *  cells, evaluating formula cells there.
+     * If formula cells are outside the window for that sheet,
+     *  it can either skip them silently, or give an exception
+     */
+    public static void evaluateAllFormulaCells(SXSSFWorkbook wb, boolean skipOutOfWindow) {
+        // Check they're all available
+        for (int i=0; i<wb.getNumberOfSheets(); i++) {
+            SXSSFSheet s = wb.getSheetAt(i);
+            if (s.isFlushed()) {
+                throw new SheetsFlushedException();
+            }
+        }
+        
+        // Process the sheets as best we can
+        for (int i=0; i<wb.getNumberOfSheets(); i++) {
+            SXSSFSheet s = wb.getSheetAt(i);
+            // TODO Detect if rows have been flushed
+        }
+    }
+    
+    /**
+     * Loops over rows and cells, evaluating formula cells there.
+     * If any sheets are inactive, or any cells outside of the window,
+     *  will give an Exception.
+     * For SXSSF, you generally don't want to use this method, instead
+     *  evaluate your formulas as you go before they leave the window.
+     */
+    public void evaluateAll() {
+        // Have the evaluation done, with exceptions
+        evaluateAllFormulaCells(wb, false);
+    }
+    
+    public static class SheetsFlushedException extends IllegalStateException {
+        protected SheetsFlushedException() {
+            super("One or more sheets have been flushed, cannot evaluate all cells");
+        }
+    }
+}
index 7ffe50cb0d168ea82fde00fe45f12ee2a9e2d262..b9380170062fdc1dedcc2be8fb72c2317862c32a 100644 (file)
@@ -50,25 +50,22 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
 
 /**
  * Streaming version of XSSFSheet implementing the "BigGridDemo" strategy.
- *
- * @author Alex Geller, Four J's Development Tools
 */
 public class SXSSFSheet implements Sheet, Cloneable
 {
-    SXSSFWorkbook _workbook;
     XSSFSheet _sh;
-    TreeMap<Integer,SXSSFRow> _rows=new TreeMap<Integer,SXSSFRow>();
-    SheetDataWriter _writer;
-    int _randomAccessWindowSize = SXSSFWorkbook.DEFAULT_WINDOW_SIZE;
-    int outlineLevelRow = 0;
-
-    public SXSSFSheet(SXSSFWorkbook workbook, XSSFSheet xSheet) throws IOException
-    {
-        _workbook=workbook;
-        _sh=xSheet;
+    private SXSSFWorkbook _workbook;
+    private TreeMap<Integer,SXSSFRow> _rows=new TreeMap<Integer,SXSSFRow>();
+    private SheetDataWriter _writer;
+    private int _randomAccessWindowSize = SXSSFWorkbook.DEFAULT_WINDOW_SIZE;
+    private int outlineLevelRow = 0;
+    private boolean flushed = false;
+
+    public SXSSFSheet(SXSSFWorkbook workbook, XSSFSheet xSheet) throws IOException {
+        _workbook = workbook;
+        _sh = xSheet;
         _writer = workbook.createSheetDataWriter();
         setRandomAccessWindowSize(_workbook.getRandomAccessWindowSize());
-
     }
 
     /**
@@ -138,6 +135,7 @@ public class SXSSFSheet implements Sheet, Cloneable
             initialAllocationSize=10;
         SXSSFRow newRow=new SXSSFRow(this,initialAllocationSize);
         _rows.put(new Integer(rownum),newRow);
+        flushed = false;
         if(_randomAccessWindowSize>=0&&_rows.size()>_randomAccessWindowSize)
         {
             try
@@ -1464,6 +1462,13 @@ public class SXSSFSheet implements Sheet, Cloneable
          }
          _randomAccessWindowSize=value;
     }
+    
+    /**
+     * Are all rows flushed to disk?
+     */
+    public boolean isFlushed() {
+        return flushed;
+    }
 
     /**
      * Specifies how many rows can be accessed at most via getRow().
@@ -1473,6 +1478,7 @@ public class SXSSFSheet implements Sheet, Cloneable
     public void flushRows(int remaining) throws IOException
     {
         while(_rows.size() > remaining) flushOneRow();
+        if (remaining == 0) flushed = true;
     }
 
     /**
@@ -1517,7 +1523,8 @@ public class SXSSFSheet implements Sheet, Cloneable
      * Deletes the temporary file that backed this sheet on disk.
      * @return true if the file was deleted, false if it wasn't.
      */
-    boolean dispose() {
+    boolean dispose() throws IOException {
+        if (!flushed) flushRows();
         return _writer.dispose();
     }
 
index d48dbc059445bd7d1de34afa5b98845617c4f2cf..f437b6a1a7a85c7ab16b109abbc9d7556a558964 100644 (file)
@@ -44,6 +44,8 @@ import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
 import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.poi.ss.usermodel.Workbook;
 import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
 import org.apache.poi.util.TempFile;
 import org.apache.poi.xssf.model.SharedStringsTable;
 import org.apache.poi.xssf.usermodel.XSSFSheet;
@@ -62,8 +64,7 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  * Carefully review your memory budget and compatibility needs before deciding
  * whether to enable shared strings or not.
  */
-public class SXSSFWorkbook implements Workbook
-{
+public class SXSSFWorkbook implements Workbook {
     /**
      * Specifies how many rows can be accessed at most via getRow().
      * When a new node is created via createRow() and the total number
@@ -72,6 +73,7 @@ public class SXSSFWorkbook implements Workbook
      * via getRow() anymore.
      */
     public static final int DEFAULT_WINDOW_SIZE = 100;
+    private static POILogger logger = POILogFactory.getLogger(SXSSFWorkbook.class);
 
     XSSFWorkbook _wb;
 
@@ -650,7 +652,7 @@ public class SXSSFWorkbook implements Workbook
      * @throws IllegalArgumentException if the name is greater than 31 chars or contains <code>/\?*[]</code>
      */
     @Override
-    public Sheet createSheet(String sheetname)
+    public SXSSFSheet createSheet(String sheetname)
     {
         return createAndRegisterSXSSFSheet(_wb.createSheet(sheetname));
     }
@@ -685,7 +687,7 @@ public class SXSSFWorkbook implements Workbook
      * @return Sheet at the provided index
      */
     @Override
-    public Sheet getSheetAt(int index)
+    public SXSSFSheet getSheetAt(int index)
     {
         return getSXSSFSheet(_wb.getSheetAt(index));
     }
@@ -697,7 +699,7 @@ public class SXSSFWorkbook implements Workbook
      * @return Sheet with the name provided or <code>null</code> if it does not exist
      */
     @Override
-    public Sheet getSheet(String name)
+    public SXSSFSheet getSheet(String name)
     {
         return getSXSSFSheet(_wb.getSheet(name));
     }
@@ -719,7 +721,11 @@ public class SXSSFWorkbook implements Workbook
         deregisterSheetMapping(xSheet);
         
         // Clean up temporary resources
-        sxSheet.dispose();
+        try {
+            sxSheet.dispose();
+        } catch (IOException e) {
+            logger.log(POILogger.WARN, e);
+        }
     }
 
     /**
@@ -909,7 +915,12 @@ public class SXSSFWorkbook implements Workbook
         boolean success = true;
         for (SXSSFSheet sheet : _sxFromXHash.keySet())
         {
-            success = sheet.dispose() && success;
+            try {
+                success = sheet.dispose() && success;
+            } catch (IOException e) {
+                logger.log(POILogger.WARN, e);
+                success = false;
+            }
         }
         return success;
     }
@@ -1114,12 +1125,12 @@ public class SXSSFWorkbook implements Workbook
 
     /**
      * Returns an object that handles instantiating concrete
-     * classes of the various instances one needs for  HSSF and XSSF.
+     *  classes of the various instances one needs for HSSF, XSSF
+     *  and SXSSF.
      */
     @Override
-    public CreationHelper getCreationHelper()
-    {
-        return _wb.getCreationHelper();
+    public CreationHelper getCreationHelper() {
+        return new SXSSFCreationHelper(this);
     }
 
     protected boolean isDate1904() {
index 95b3a0bcb9c742fa86fc86b01f349b9a13ab2912..fe72146617b609d7b9f1871f1ad3ef8bf3b369b2 100644 (file)
@@ -367,12 +367,8 @@ public class SheetDataWriter {
      * Deletes the temporary file that backed this sheet on disk.\r
      * @return true if the file was deleted, false if it wasn't.\r
      */\r
-    boolean dispose() {\r
-        try {\r
-            _out.close();\r
-            return _fd.delete();\r
-        } catch (IOException e){\r
-            return false;\r
-        }\r
+    boolean dispose() throws IOException {\r
+        _out.close();\r
+        return _fd.delete();\r
     }\r
 }\r
index 086311494554acd639401ac3e8f59eb278ae9773..2e5ca2d95808194355ee00943dbb624982f07e72 100644 (file)
@@ -18,11 +18,13 @@ package org.apache.poi.xssf.usermodel;
 
 import org.apache.poi.ss.usermodel.CreationHelper;
 import org.apache.poi.ss.usermodel.Hyperlink;
+import org.apache.poi.util.Internal;
 
 public class XSSFCreationHelper implements CreationHelper {
     private XSSFWorkbook workbook;
 
-    XSSFCreationHelper(XSSFWorkbook wb) {
+    @Internal
+    public XSSFCreationHelper(XSSFWorkbook wb) {
         workbook = wb;
     }
 
index 27317345cd1d0483153f0e2579164145d01336e8..adbd843a7cb92a1c50c52e8ae9aa01c73e29b3a0 100644 (file)
@@ -235,22 +235,22 @@ public class XSSFFormulaEvaluator implements FormulaEvaluator, WorkbookEvaluator
         *  cells, and calling evaluateFormulaCell on each one.
         */
        public static void evaluateAllFormulaCells(XSSFWorkbook wb) {
-          HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
+           HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
+       }
+       /**
+        * Loops over all cells in all sheets of the supplied
+        *  workbook.
+        * For cells that contain formulas, their formulas are
+        *  evaluated, and the results are saved. These cells
+        *  remain as formula cells.
+        * For cells that do not contain formulas, no changes
+        *  are made.
+        * This is a helpful wrapper around looping over all
+        *  cells, and calling evaluateFormulaCell on each one.
+        */
+       public void evaluateAll() {
+           HSSFFormulaEvaluator.evaluateAllFormulaCells(_book);
        }
-   /**
-    * Loops over all cells in all sheets of the supplied
-    *  workbook.
-    * For cells that contain formulas, their formulas are
-    *  evaluated, and the results are saved. These cells
-    *  remain as formula cells.
-    * For cells that do not contain formulas, no changes
-    *  are made.
-    * This is a helpful wrapper around looping over all
-    *  cells, and calling evaluateFormulaCell on each one.
-    */
-   public void evaluateAll() {
-      HSSFFormulaEvaluator.evaluateAllFormulaCells(_book);
-   }
 
        /**
         * Returns a CellValue wrapper around the supplied ValueEval instance.