]> source.dussan.org Git - poi.git/commitdiff
bugzilla 52575: added an option to ignore missing workbook references in formula...
authorYegor Kozlov <yegor@apache.org>
Mon, 6 Feb 2012 07:37:11 +0000 (07:37 +0000)
committerYegor Kozlov <yegor@apache.org>
Mon, 6 Feb 2012 07:37:11 +0000 (07:37 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1240903 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationCell.java
src/java/org/apache/poi/ss/formula/EvaluationCell.java
src/java/org/apache/poi/ss/formula/OperationEvaluationContext.java
src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java
src/java/org/apache/poi/ss/formula/eval/forked/ForkedEvaluationCell.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationCell.java
src/testcases/org/apache/poi/ss/formula/TestMissingWorkbook.java [new file with mode: 0644]
test-data/spreadsheet/52575_main.xls [new file with mode: 0644]
test-data/spreadsheet/52575_source.xls [new file with mode: 0644]

index c2a3693f6d9ab7c1a95dbe1e5e04a4c6b91be60f..b3f0f1182f5b14c598cd1d79f4f1a2bcccd46db9 100644 (file)
@@ -34,6 +34,7 @@
 
     <changes>
         <release version="3.8-beta6" date="2012-??-??">
+           <action dev="poi-developers" type="add">52575 - added an option to ignore missing workbook references in formula evaluator</action>
            <action dev="poi-developers" type="add">Validate address of hyperlinks in XSSF</action>
            <action dev="poi-developers" type="fix">52540 - Relax the M4.1 constraint on reading OOXML files, as some Office produced ones do have 2 Core Properties, despite the specification explicitly forbidding this</action>
            <action dev="poi-developers" type="add">52462 - Added implementation for SUMIFS()</action>
index 66069f8cbcdd302878289f0a0eece8355d46aeeb..462d92a5600db8bc11051804638db8d40cd79eaa 100644 (file)
@@ -66,7 +66,10 @@ final class HSSFEvaluationCell implements EvaluationCell {
        public EvaluationSheet getSheet() {
                return _evalSheet;
        }
-       public String getStringCellValue() {
-               return _cell.getRichStringCellValue().getString();
-       }
-}
+       public String getStringCellValue() {\r
+               return _cell.getRichStringCellValue().getString();\r
+       }\r
+       public int getCachedFormulaResultType() {\r
+               return _cell.getCachedFormulaResultType();\r
+       }\r
+}\r
index eef4da18da4b17a6f326d0e35850df36849e253f..a3de9e89454cdcb166753ce4d735e3166a480528 100644 (file)
@@ -38,7 +38,9 @@ public interface EvaluationCell {
        int getCellType();
 
        double getNumericCellValue();
-       String getStringCellValue();
-       boolean getBooleanCellValue();
-       int getErrorCellValue();
-}
+       String getStringCellValue();\r
+       boolean getBooleanCellValue();\r
+       int getErrorCellValue();\r
+\r
+       int getCachedFormulaResultType();\r
+}\r
index a1540892538a98d6d04227997bff244d08e83879..87018e6abe7fe2914f64fd74ec8a1466a308aeba 100644 (file)
@@ -83,13 +83,13 @@ public final class OperationEvaluationContext {
                } else {
                        // look up sheet by name from external workbook
                        String workbookName = externalSheet.getWorkbookName();
-                       try {
-                               targetEvaluator = _bookEvaluator.getOtherWorkbookEvaluator(workbookName);
-                       } catch (WorkbookNotFoundException e) {
-                               throw new RuntimeException(e.getMessage());
-                       }
-                       otherSheetIndex = targetEvaluator.getSheetIndex(externalSheet.getSheetName());
-                       if (otherSheetIndex < 0) {
+                       try {\r
+                               targetEvaluator = _bookEvaluator.getOtherWorkbookEvaluator(workbookName);\r
+                       } catch (WorkbookNotFoundException e) {\r
+                               throw new RuntimeException(e.getMessage(), e);\r
+                       }\r
+                       otherSheetIndex = targetEvaluator.getSheetIndex(externalSheet.getSheetName());\r
+                       if (otherSheetIndex < 0) {\r
                                throw new RuntimeException("Invalid sheet name '" + externalSheet.getSheetName()
                                                + "' in bool '" + workbookName + "'.");
                        }
index 1328c850b45a1629aff9eba58847e3a3928837b2..3807c9c291c3e370fc77c5e07a0a6742b0170406 100644 (file)
@@ -67,6 +67,8 @@ import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
 import org.apache.poi.ss.formula.eval.NotImplementedException;
 import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
 
 /**
  * Evaluates formula cells.<p/>
@@ -80,8 +82,16 @@ import org.apache.poi.ss.usermodel.Cell;
  * @author Josh Micich
  */
 public final class WorkbookEvaluator {
+       
+       private static final POILogger LOG = POILogFactory.getLogger(WorkbookEvaluator.class);
+
+    /**
+     * Whether to use cached formula results if external workbook references in a formula is not available.
+     * See Bugzilla 52575 for details.
+     */
+    private static final String IGNORE_MISSING_WORKBOOKS = WorkbookEvaluator.class.getName() + ".IGNORE_MISSING_WORKBOOKS";
 
-       private final EvaluationWorkbook _workbook;
+    private final EvaluationWorkbook _workbook;
        private EvaluationCache _cache;
        /** part of cache entry key (useful when evaluating multiple workbooks) */
        private int _workbookIx;
@@ -144,11 +154,19 @@ public final class WorkbookEvaluator {
        }
 
        private static boolean isDebugLogEnabled() {
-               return false;
+               return LOG.check(POILogger.DEBUG);
+       }
+       private static boolean isInfoLogEnabled() {
+               return LOG.check(POILogger.INFO);
        }
        private static void logDebug(String s) {
                if (isDebugLogEnabled()) {
-                       System.out.println(s);
+                       LOG.log(POILogger.DEBUG, s);
+               }
+       }
+       private static void logInfo(String s) {
+               if (isInfoLogEnabled()) {
+                       LOG.log(POILogger.INFO, s);
                }
        }
        /* package */ void attachToEnvironment(CollaboratingWorkbooksEnvironment collaboratingWorkbooksEnvironment, EvaluationCache cache, int workbookIx) {
@@ -288,9 +306,38 @@ public final class WorkbookEvaluator {
                                }
 
                                tracker.updateCacheResult(result);
-                       } catch (NotImplementedException e) {
+                       }
+                        catch (NotImplementedException e) {
                                throw addExceptionInfo(e, sheetIndex, rowIndex, columnIndex);
-                       } finally {
+                        } catch (RuntimeException re) {
+                                if (re.getCause() instanceof WorkbookNotFoundException 
+                                                //To be replaced by configuration infrastructure
+                                                && Boolean.valueOf(System.getProperty(IGNORE_MISSING_WORKBOOKS))) {
+                                       logInfo(re.getCause().getMessage() + " - Continuing with cached value!");
+                                       switch(srcCell.getCachedFormulaResultType()) {
+                                               case Cell.CELL_TYPE_NUMERIC:
+                                                       result = new NumberEval(srcCell.getNumericCellValue());
+                                                       break;
+                                               case Cell.CELL_TYPE_STRING:
+                                                       result =  new StringEval(srcCell.getStringCellValue());
+                                                       break;
+                                               case Cell.CELL_TYPE_BLANK:
+                                                       result = BlankEval.instance;
+                                                       break;
+                                               case Cell.CELL_TYPE_BOOLEAN:
+                                                       result =  BoolEval.valueOf(srcCell.getBooleanCellValue());
+                                                       break;
+                                               case Cell.CELL_TYPE_ERROR:
+                                                       result =  ErrorEval.valueOf(srcCell.getErrorCellValue());
+                                                       break;
+                                               case Cell.CELL_TYPE_FORMULA:
+                                               default:
+                                                       throw new RuntimeException("Unexpected cell type '" + srcCell.getCellType()+"' found!");
+                                       }
+                                } else {
+                                        throw re;
+                                }
+                        } finally {
                                tracker.endEvaluate(cce);
                        }
                } else {
index 8e8690257074ba49c91e3e742cb94a0176f45266..2c169e648e4f5240d284df0ab7dcee49aabe9854 100644 (file)
@@ -128,4 +128,8 @@ final class ForkedEvaluationCell implements EvaluationCell {
        public int getColumnIndex() {
                return _masterCell.getColumnIndex();
        }
+    public int getCachedFormulaResultType() {
+        return _masterCell.getCachedFormulaResultType();
+    }
+
 }
index 127e4da86aa21b1af3e7374316f8d0d81b938f62..46f10dc26d808be769943366b0aba3ece04eed65 100644 (file)
@@ -69,7 +69,10 @@ final class XSSFEvaluationCell implements EvaluationCell {
        public EvaluationSheet getSheet() {
                return _evalSheet;
        }
-       public String getStringCellValue() {
-               return _cell.getRichStringCellValue().getString();
-       }
-}
+       public String getStringCellValue() {\r
+               return _cell.getRichStringCellValue().getString();\r
+       }\r
+       public int getCachedFormulaResultType() {\r
+               return _cell.getCachedFormulaResultType();\r
+       }\r
+}\r
diff --git a/src/testcases/org/apache/poi/ss/formula/TestMissingWorkbook.java b/src/testcases/org/apache/poi/ss/formula/TestMissingWorkbook.java
new file mode 100644 (file)
index 0000000..7b639f9
--- /dev/null
@@ -0,0 +1,113 @@
+/*\r
+ *  ====================================================================\r
+ *    Licensed to the Apache Software Foundation (ASF) under one or more\r
+ *    contributor license agreements.  See the NOTICE file distributed with\r
+ *    this work for additional information regarding copyright ownership.\r
+ *    The ASF licenses this file to You under the Apache License, Version 2.0\r
+ *    (the "License"); you may not use this file except in compliance with\r
+ *    the License.  You may obtain a copy of the License at\r
+ *\r
+ *        http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ *    Unless required by applicable law or agreed to in writing, software\r
+ *    distributed under the License is distributed on an "AS IS" BASIS,\r
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ *    See the License for the specific language governing permissions and\r
+ *    limitations under the License.\r
+ * ====================================================================\r
+ */\r
+\r
+package org.apache.poi.ss.formula;\r
+\r
+import junit.framework.TestCase;\r
+import org.apache.poi.hssf.HSSFTestDataSamples;\r
+import org.apache.poi.hssf.usermodel.*;\r
+import org.apache.poi.ss.usermodel.Cell;\r
+import org.apache.poi.ss.usermodel.FormulaEvaluator;\r
+\r
+import java.io.IOException;\r
+\r
+public class TestMissingWorkbook extends TestCase {\r
+       private static final String MAIN_WORKBOOK_FILENAME = "52575_main.xls";\r
+       private static final String SOURCE_DUMMY_WORKBOOK_FILENAME = "source_dummy.xls";\r
+       private static final String SOURCE_WORKBOOK_FILENAME = "52575_source.xls";\r
+       \r
+       private static final String propertyKey = WorkbookEvaluator.class.getName() + ".IGNORE_MISSING_WORKBOOKS";\r
+       \r
+       private HSSFWorkbook mainWorkbook;\r
+       private HSSFWorkbook sourceWorkbook;\r
+       \r
+       @Override\r
+       protected void setUp() throws Exception {\r
+               mainWorkbook = HSSFTestDataSamples.openSampleWorkbook(MAIN_WORKBOOK_FILENAME);\r
+               sourceWorkbook = HSSFTestDataSamples.openSampleWorkbook(SOURCE_WORKBOOK_FILENAME);\r
+               \r
+               assertNotNull(mainWorkbook);\r
+               assertNotNull(sourceWorkbook);\r
+       }\r
+\r
+       public void testMissingWorkbookMissing() throws IOException {\r
+               FormulaEvaluator evaluator = mainWorkbook.getCreationHelper().createFormulaEvaluator();\r
+               \r
+               HSSFSheet lSheet = mainWorkbook.getSheetAt(0);\r
+               HSSFRow lARow = lSheet.getRow(0);\r
+               HSSFCell lA1Cell = lARow.getCell(0);\r
+               \r
+               assertEquals(Cell.CELL_TYPE_FORMULA, lA1Cell.getCellType());\r
+               try {\r
+                       evaluator.evaluateFormulaCell(lA1Cell);\r
+                       fail("Missing external workbook reference exception expected!");\r
+               }catch(RuntimeException re) {\r
+                       assertTrue("Unexpected exception: " + re, re.getMessage().indexOf(SOURCE_DUMMY_WORKBOOK_FILENAME) != -1);\r
+               }\r
+       }\r
+       \r
+       public void testMissingWorkbookMissingOverride() throws IOException {\r
+               HSSFSheet lSheet = mainWorkbook.getSheetAt(0);\r
+               HSSFCell lA1Cell = lSheet.getRow(0).getCell(0);\r
+               HSSFCell lB1Cell = lSheet.getRow(1).getCell(0);\r
+               HSSFCell lC1Cell = lSheet.getRow(2).getCell(0);\r
+               \r
+               assertEquals(Cell.CELL_TYPE_FORMULA, lA1Cell.getCellType());\r
+               assertEquals(Cell.CELL_TYPE_FORMULA, lB1Cell.getCellType());\r
+               assertEquals(Cell.CELL_TYPE_FORMULA, lC1Cell.getCellType());\r
+               \r
+               FormulaEvaluator evaluator = mainWorkbook.getCreationHelper().createFormulaEvaluator();\r
+               \r
+               System.setProperty(propertyKey, Boolean.toString(true));\r
+               assertEquals(Cell.CELL_TYPE_NUMERIC, evaluator.evaluateFormulaCell(lA1Cell));\r
+               assertEquals(Cell.CELL_TYPE_STRING, evaluator.evaluateFormulaCell(lB1Cell));\r
+               assertEquals(Cell.CELL_TYPE_BOOLEAN, evaluator.evaluateFormulaCell(lC1Cell));\r
+\r
+               assertEquals(10.0d, lA1Cell.getNumericCellValue(), 0.00001d);\r
+               assertEquals("POI rocks!", lB1Cell.getStringCellValue());\r
+               assertEquals(true, lC1Cell.getBooleanCellValue());\r
+       }\r
+       \r
+\r
+       public void testExistingWorkbook() throws IOException {\r
+               HSSFSheet lSheet = mainWorkbook.getSheetAt(0);\r
+               HSSFCell lA1Cell = lSheet.getRow(0).getCell(0);\r
+               HSSFCell lB1Cell = lSheet.getRow(1).getCell(0);\r
+               HSSFCell lC1Cell = lSheet.getRow(2).getCell(0);\r
+               \r
+               assertEquals(Cell.CELL_TYPE_FORMULA, lA1Cell.getCellType());\r
+               assertEquals(Cell.CELL_TYPE_FORMULA, lB1Cell.getCellType());\r
+               assertEquals(Cell.CELL_TYPE_FORMULA, lC1Cell.getCellType());\r
+\r
+               HSSFFormulaEvaluator lMainWorkbookEvaluator = new HSSFFormulaEvaluator(mainWorkbook);\r
+               HSSFFormulaEvaluator lSourceEvaluator = new HSSFFormulaEvaluator(sourceWorkbook);\r
+               HSSFFormulaEvaluator.setupEnvironment(\r
+                               new String[]{MAIN_WORKBOOK_FILENAME, SOURCE_DUMMY_WORKBOOK_FILENAME}, \r
+                               new HSSFFormulaEvaluator[] {lMainWorkbookEvaluator, lSourceEvaluator});\r
+               \r
+               assertEquals(Cell.CELL_TYPE_NUMERIC, lMainWorkbookEvaluator.evaluateFormulaCell(lA1Cell));\r
+               assertEquals(Cell.CELL_TYPE_STRING, lMainWorkbookEvaluator.evaluateFormulaCell(lB1Cell));\r
+               assertEquals(Cell.CELL_TYPE_BOOLEAN, lMainWorkbookEvaluator.evaluateFormulaCell(lC1Cell));\r
+\r
+               assertEquals(20.0d, lA1Cell.getNumericCellValue(), 0.00001d);\r
+               assertEquals("Apache rocks!", lB1Cell.getStringCellValue());\r
+               assertEquals(false, lC1Cell.getBooleanCellValue());\r
+       }\r
+\r
+}\r
diff --git a/test-data/spreadsheet/52575_main.xls b/test-data/spreadsheet/52575_main.xls
new file mode 100644 (file)
index 0000000..fbcf0dd
Binary files /dev/null and b/test-data/spreadsheet/52575_main.xls differ
diff --git a/test-data/spreadsheet/52575_source.xls b/test-data/spreadsheet/52575_source.xls
new file mode 100644 (file)
index 0000000..b75c142
Binary files /dev/null and b/test-data/spreadsheet/52575_source.xls differ