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/>
* @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;
}
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) {
}
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 {
--- /dev/null
+/*\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