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 2026/09/17 23:20:24 UTC
(poi) branch trunk updated: Add OperationEvaluationContext constructor that does not require an EvaluationTracker (#1274)
This is an automated email from the ASF dual-hosted git repository.
pjfanning pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/poi.git
The following commit(s) were added to refs/heads/trunk by this push:
new 31a35baa51 Add OperationEvaluationContext constructor that does not require an EvaluationTracker (#1274)
31a35baa51 is described below
commit 31a35baa5109fb8f3c2fa18dbb97388891055dd4
Author: PJ Fanning <pj...@users.noreply.github.com>
AuthorDate: Fri Sep 18 00:20:19 2026 +0100
Add OperationEvaluationContext constructor that does not require an EvaluationTracker (#1274)
* Add OperationEvaluationContext constructor that does not require an EvaluationTracker
The existing public constructors take an EvaluationTracker, but that class
(and the EvaluationCache it needs) is package-private, so code outside
org.apache.poi.ss.formula could not construct a context at all - even
though the rest of the evaluation SPI (EvaluationWorkbook, EvaluationCell,
FormulaParser.parse, WorkbookEvaluator, FreeRefFunction) is public.
The new constructor obtains a tracker backed by the WorkbookEvaluator's own
cache via a package-private factory, so the tracker and cache stay internal.
Co-Authored-By: Claude Opus 5 <no...@anthropic.com>
* Use assertInstanceOf instead of casts in test
Co-Authored-By: Claude Opus 5 <no...@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <no...@anthropic.com>
---
.../poi/ss/formula/OperationEvaluationContext.java | 20 +++++++++++++
.../apache/poi/ss/formula/WorkbookEvaluator.java | 8 +++++
.../poi/ss/formula/TestWorkbookEvaluator.java | 35 ++++++++++++++++++++++
3 files changed, 63 insertions(+)
diff --git a/poi/src/main/java/org/apache/poi/ss/formula/OperationEvaluationContext.java b/poi/src/main/java/org/apache/poi/ss/formula/OperationEvaluationContext.java
index ba09ef8c2c..4c3ed959bc 100644
--- a/poi/src/main/java/org/apache/poi/ss/formula/OperationEvaluationContext.java
+++ b/poi/src/main/java/org/apache/poi/ss/formula/OperationEvaluationContext.java
@@ -67,6 +67,26 @@ public final class OperationEvaluationContext {
*/
private SheetRangeEvaluator _currentSheetRefEvaluator;
+ /**
+ * Creates a context for evaluating formula tokens at the given position, using the
+ * evaluation tracker of the given {@link WorkbookEvaluator}.
+ *
+ * <p>This constructor is intended for code outside this package - e.g. custom
+ * {@link EvaluationWorkbook} implementations or {@link org.apache.poi.ss.formula.functions.FreeRefFunction}
+ * callers - that needs a context but has no access to the internal evaluation tracker.</p>
+ *
+ * @param bookEvaluator the evaluator of the workbook the formula belongs to
+ * @param workbook the workbook the formula belongs to
+ * @param sheetIndex the index of the sheet the formula is evaluated on
+ * @param srcRowNum the row index of the formula's position (base for relative references)
+ * @param srcColNum the column index of the formula's position (base for relative references)
+ * @since 6.0.0
+ */
+ public OperationEvaluationContext(WorkbookEvaluator bookEvaluator, EvaluationWorkbook workbook, int sheetIndex, int srcRowNum,
+ int srcColNum) {
+ this(bookEvaluator, workbook, sheetIndex, srcRowNum, srcColNum, bookEvaluator.createEvaluationTracker(), true);
+ }
+
public OperationEvaluationContext(WorkbookEvaluator bookEvaluator, EvaluationWorkbook workbook, int sheetIndex, int srcRowNum,
int srcColNum, EvaluationTracker tracker) {
this(bookEvaluator, workbook, sheetIndex, srcRowNum, srcColNum, tracker, true);
diff --git a/poi/src/main/java/org/apache/poi/ss/formula/WorkbookEvaluator.java b/poi/src/main/java/org/apache/poi/ss/formula/WorkbookEvaluator.java
index b6e17b15f0..38350c333b 100644
--- a/poi/src/main/java/org/apache/poi/ss/formula/WorkbookEvaluator.java
+++ b/poi/src/main/java/org/apache/poi/ss/formula/WorkbookEvaluator.java
@@ -154,6 +154,14 @@ public final class WorkbookEvaluator {
return _collaboratingWorkbookEnvironment.getWorkbookEvaluator(workbookName);
}
+ /**
+ * @return a new tracker backed by this evaluator's cache, for building an
+ * {@link OperationEvaluationContext}
+ */
+ /* package */ EvaluationTracker createEvaluationTracker() {
+ return new EvaluationTracker(_cache);
+ }
+
/* package */ IEvaluationListener getEvaluationListener() {
return _evaluationListener;
}
diff --git a/poi/src/test/java/org/apache/poi/ss/formula/TestWorkbookEvaluator.java b/poi/src/test/java/org/apache/poi/ss/formula/TestWorkbookEvaluator.java
index 966b6bd68f..0d396e2741 100644
--- a/poi/src/test/java/org/apache/poi/ss/formula/TestWorkbookEvaluator.java
+++ b/poi/src/test/java/org/apache/poi/ss/formula/TestWorkbookEvaluator.java
@@ -20,6 +20,7 @@ package org.apache.poi.ss.formula;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -38,7 +39,9 @@ import org.apache.poi.ss.formula.eval.BlankEval;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.MissingArgEval;
import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.StringEval;
import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.functions.FreeRefFunction;
import org.apache.poi.ss.formula.ptg.*;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
@@ -644,4 +647,36 @@ class TestWorkbookEvaluator {
assertEquals("3", cellC3.getStringCellValue());
}
}
+
+ @Test
+ void testOperationEvaluationContextWithoutTracker() throws IOException {
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ HSSFSheet sheet = wb.createSheet("Sheet1");
+ HSSFRow row = sheet.createRow(0);
+ HSSFCell a1 = row.createCell(0);
+ HSSFCell b1 = row.createCell(1);
+ a1.setCellValue(2);
+ b1.setCellValue(3);
+
+ HSSFEvaluationWorkbook ewb = HSSFEvaluationWorkbook.create(wb);
+ WorkbookEvaluator evaluator = new WorkbookEvaluator(ewb, null, null);
+ // the constructor available outside this package: no EvaluationTracker needed
+ OperationEvaluationContext ec = new OperationEvaluationContext(evaluator, ewb, 0, 0, 2);
+
+ // resolves references
+ ValueEval a1Value = ec.getRefEvaluatorForCurrentSheet().getSheetEvaluator(0).getEvalForCell(0, 0);
+ assertEquals(2.0, assertInstanceOf(NumberEval.class, a1Value).getNumberValue(), 0.0);
+
+ // usable with FreeRefFunctions
+ FreeRefFunction ifErrorFunc = evaluator.findUserDefinedFunction("IFERROR");
+ ValueEval ifError = ifErrorFunc.evaluate(new ValueEval[]{ErrorEval.DIV_ZERO, new StringEval("x")}, ec);
+ assertEquals("x", assertInstanceOf(StringEval.class, ifError).getStringValue());
+
+ // parse once, evaluate many times without a formula cell
+ Ptg[] ptgs = FormulaParser.parse("A1*B1", ewb, FormulaType.CELL, 0, 0);
+ assertEquals(6.0, assertInstanceOf(NumberEval.class, evaluator.evaluateFormula(ec, ptgs)).getNumberValue(), 0.0);
+ a1.setCellValue(5);
+ assertEquals(15.0, assertInstanceOf(NumberEval.class, evaluator.evaluateFormula(ec, ptgs)).getNumberValue(), 0.0);
+ }
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org