From 12e87a1900dffc3105dcd7ffbce4c7c3bc90a82d Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Mon, 21 Jul 2014 12:23:54 +0000 Subject: [PATCH] Generalise the CollaboratingWorkbooksEnvironment setup, so that XSSF can use it too git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1612254 13f79535-47bb-0310-9956-ffa450edef68 --- .../hssf/usermodel/HSSFFormulaEvaluator.java | 15 ++++++-- .../CollaboratingWorkbooksEnvironment.java | 14 ++++++++ .../ss/formula/WorkbookEvaluatorProvider.java | 34 +++++++++++++++++++ .../poi/ss/usermodel/FormulaEvaluator.java | 13 ++++++- .../org/apache/poi/ss/util/SheetUtil.java | 19 ++++++++--- .../xssf/usermodel/XSSFFormulaEvaluator.java | 14 +++++++- .../usermodel/TestXSSFFormulaEvaluation.java | 32 +++++++++++++++-- 7 files changed, 131 insertions(+), 10 deletions(-) create mode 100644 src/java/org/apache/poi/ss/formula/WorkbookEvaluatorProvider.java diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java b/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java index 38f08cd2c..1e8098b9e 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java @@ -17,9 +17,12 @@ package org.apache.poi.hssf.usermodel; +import java.util.Map; + import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment; import org.apache.poi.ss.formula.IStabilityClassifier; import org.apache.poi.ss.formula.WorkbookEvaluator; +import org.apache.poi.ss.formula.WorkbookEvaluatorProvider; import org.apache.poi.ss.formula.eval.BoolEval; import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.NumericValueEval; @@ -40,7 +43,7 @@ import org.apache.poi.ss.usermodel.Workbook; * cell values. Be sure to call {@link #clearAllCachedResultValues()} if any workbook cells are changed between * calls to evaluate~ methods on this class. */ -public class HSSFFormulaEvaluator implements FormulaEvaluator { +public class HSSFFormulaEvaluator implements FormulaEvaluator, WorkbookEvaluatorProvider { private WorkbookEvaluator _bookEvaluator; private HSSFWorkbook _book; @@ -101,7 +104,15 @@ public class HSSFFormulaEvaluator implements FormulaEvaluator { CollaboratingWorkbooksEnvironment.setup(workbookNames, wbEvals); } - /** + public void setupReferencedWorkbooks(Map evaluators) { + CollaboratingWorkbooksEnvironment.setupFormulaEvaluator(evaluators); + } + + public WorkbookEvaluator _getWorkbookEvaluator() { + return _bookEvaluator; + } + + /** * Does nothing * @deprecated (Aug 2008) - not needed, since the current row can be derived from the cell */ diff --git a/src/java/org/apache/poi/ss/formula/CollaboratingWorkbooksEnvironment.java b/src/java/org/apache/poi/ss/formula/CollaboratingWorkbooksEnvironment.java index 1352b716c..00b3e8bfc 100644 --- a/src/java/org/apache/poi/ss/formula/CollaboratingWorkbooksEnvironment.java +++ b/src/java/org/apache/poi/ss/formula/CollaboratingWorkbooksEnvironment.java @@ -24,6 +24,7 @@ import java.util.Iterator; import java.util.Map; import java.util.Set; +import org.apache.poi.ss.usermodel.FormulaEvaluator; import org.apache.poi.util.Internal; /** @@ -73,6 +74,19 @@ public final class CollaboratingWorkbooksEnvironment { evaluatorsByName.values().toArray(new WorkbookEvaluator[evaluatorsByName.size()]); new CollaboratingWorkbooksEnvironment(evaluatorsByName, evaluators); } + public static void setupFormulaEvaluator(Map evaluators) { + Map evaluatorsByName = new HashMap(evaluators.size()); + for (String wbName : evaluators.keySet()) { + FormulaEvaluator eval = evaluators.get(wbName); + if (eval instanceof WorkbookEvaluatorProvider) { + evaluatorsByName.put(wbName, ((WorkbookEvaluatorProvider)eval)._getWorkbookEvaluator()); + } else { + throw new IllegalArgumentException("Formula Evaluator " + eval + + " provides no WorkbookEvaluator access"); + } + } + setup(evaluatorsByName); + } private CollaboratingWorkbooksEnvironment(String[] workbookNames, WorkbookEvaluator[] evaluators, int nItems) { this(toUniqueMap(workbookNames, evaluators, nItems), evaluators); diff --git a/src/java/org/apache/poi/ss/formula/WorkbookEvaluatorProvider.java b/src/java/org/apache/poi/ss/formula/WorkbookEvaluatorProvider.java new file mode 100644 index 000000000..dd6f09bd1 --- /dev/null +++ b/src/java/org/apache/poi/ss/formula/WorkbookEvaluatorProvider.java @@ -0,0 +1,34 @@ +/* ==================================================================== + 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.ss.formula; + +import org.apache.poi.util.Internal; + +/** + * Provides access to a {@link WorkbookEvaluator}, eg for use with + * {@link CollaboratingWorkbooksEnvironment} + * + *

For POI internal use only + */ +@Internal +public interface WorkbookEvaluatorProvider { + /** + * Provide the underlying WorkbookEvaluator + */ + WorkbookEvaluator _getWorkbookEvaluator(); +} diff --git a/src/java/org/apache/poi/ss/usermodel/FormulaEvaluator.java b/src/java/org/apache/poi/ss/usermodel/FormulaEvaluator.java index 17bb3bd57..3e8a33781 100644 --- a/src/java/org/apache/poi/ss/usermodel/FormulaEvaluator.java +++ b/src/java/org/apache/poi/ss/usermodel/FormulaEvaluator.java @@ -17,6 +17,8 @@ package org.apache.poi.ss.usermodel; +import java.util.Map; + /** * Evaluates formula cells.

* @@ -114,6 +116,16 @@ public interface FormulaEvaluator { * @param cell */ Cell evaluateInCell(Cell cell); + + /** + * Sets up the Formula Evaluator to be able to reference and resolve + * links to other workbooks, eg [Test.xls]Sheet1!A1. + *

For a workbook referenced as [Test.xls]Sheet1!A1, you should + * supply a map containing the key Test.xls (no square brackets), + * and an open FormulaEvaluator onto that Workbook. + * @param otherWorkbooks Map of workbook names (no square brackets) to an evaluator on that workbook + */ + void setupReferencedWorkbooks(Map workbooks); /** * Perform detailed output of formula evaluation for next evaluation only? @@ -124,5 +136,4 @@ public interface FormulaEvaluator { * @param value whether to perform detailed output */ void setDebugEvaluationOutputForNextEval(boolean value); - } diff --git a/src/java/org/apache/poi/ss/util/SheetUtil.java b/src/java/org/apache/poi/ss/util/SheetUtil.java index a5c1fb736..792ef31f6 100644 --- a/src/java/org/apache/poi/ss/util/SheetUtil.java +++ b/src/java/org/apache/poi/ss/util/SheetUtil.java @@ -17,13 +17,23 @@ package org.apache.poi.ss.util; -import org.apache.poi.ss.usermodel.*; - -import java.text.AttributedString; -import java.awt.font.TextLayout; import java.awt.font.FontRenderContext; import java.awt.font.TextAttribute; +import java.awt.font.TextLayout; import java.awt.geom.AffineTransform; +import java.text.AttributedString; +import java.util.Map; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.CellValue; +import org.apache.poi.ss.usermodel.DataFormatter; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.FormulaEvaluator; +import org.apache.poi.ss.usermodel.RichTextString; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; /** @@ -61,6 +71,7 @@ public class SheetUtil { public void notifyUpdateCell(Cell cell) {} public CellValue evaluate(Cell cell) {return null; } public Cell evaluateInCell(Cell cell) { return null; } + public void setupReferencedWorkbooks(Map workbooks) {} public void setDebugEvaluationOutputForNextEval(boolean value) {} public void evaluateAll() {} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFormulaEvaluator.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFormulaEvaluator.java index 4a429f4b4..90091a146 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFormulaEvaluator.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFormulaEvaluator.java @@ -17,9 +17,13 @@ package org.apache.poi.xssf.usermodel; +import java.util.Map; + import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; +import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment; import org.apache.poi.ss.formula.IStabilityClassifier; import org.apache.poi.ss.formula.WorkbookEvaluator; +import org.apache.poi.ss.formula.WorkbookEvaluatorProvider; import org.apache.poi.ss.formula.eval.BoolEval; import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.NumberEval; @@ -41,7 +45,7 @@ import org.apache.poi.ss.usermodel.Workbook; * @author Amol S. Deshmukh < amolweb at ya hoo dot com > * @author Josh Micich */ -public class XSSFFormulaEvaluator implements FormulaEvaluator { +public class XSSFFormulaEvaluator implements FormulaEvaluator, WorkbookEvaluatorProvider { private WorkbookEvaluator _bookEvaluator; private XSSFWorkbook _book; @@ -280,6 +284,14 @@ public class XSSFFormulaEvaluator implements FormulaEvaluator { throw new RuntimeException("Unexpected eval class (" + eval.getClass().getName() + ")"); } + public void setupReferencedWorkbooks(Map evaluators) { + CollaboratingWorkbooksEnvironment.setupFormulaEvaluator(evaluators); + } + + public WorkbookEvaluator _getWorkbookEvaluator() { + return _bookEvaluator; + } + /** {@inheritDoc} */ public void setDebugEvaluationOutputForNextEval(boolean value){ _bookEvaluator.setDebugEvaluationOutputForNextEval(value); diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java index 643a9cd26..1c1de721b 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java @@ -17,6 +17,10 @@ package org.apache.poi.xssf.usermodel; +import java.util.HashMap; +import java.util.Map; + +import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.ss.usermodel.BaseTestFormulaEvaluator; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellValue; @@ -126,8 +130,32 @@ public final class TestXSSFFormulaEvaluation extends BaseTestFormulaEvaluator { assertEquals("Test A1", cXSL_sNR.getStringCellValue()); assertEquals(142.0, cXSL_gNR.getNumericCellValue()); - // Try evaluating - // TODO + // Try to evaluate without references, won't work + // (At least, not unit we fix bug #56752 that is) + try { + evaluator.evaluate(cXSL_cell); + fail("Without a fix for #56752, shouldn't be able to evaluate a " + + "reference to a non-provided linked workbook"); + } catch(Exception e) {} + + // Setup the environment + Map evaluators = new HashMap(); + evaluators.put("ref2-56737.xlsx", evaluator); + evaluators.put("56737.xlsx", + _testDataProvider.openSampleWorkbook("56737.xlsx").getCreationHelper().createFormulaEvaluator()); + evaluators.put("56737.xls", + HSSFTestDataSamples.openSampleWorkbook("56737.xls").getCreationHelper().createFormulaEvaluator()); + evaluator.setupReferencedWorkbooks(evaluators); + + // Try evaluating all of them, ensure we don't blow up + for(Row r : s) { + for (Cell c : r) { + // TODO Fix and enable + // evaluator.evaluate(c); + } + } + + // Evaluate and check results } /**