From: Greg Woolsey Date: Sat, 30 Mar 2019 18:14:14 +0000 (+0000) Subject: #63302 Formula evaluation of names with offset or row function is incorrect X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=95fe97b15229777f33ddad8f45f5713db4787b5d;p=poi.git #63302 Formula evaluation of names with offset or row function is incorrect thanks to John Lincoln White for the patch, including new unit tests. git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1856644 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java b/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java index 2116456f34..060f274ef0 100644 --- a/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java +++ b/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java @@ -773,10 +773,12 @@ public final class WorkbookEvaluator { * YK: Used by OperationEvaluationContext to resolve indirect names. */ /*package*/ ValueEval evaluateNameFormula(Ptg[] ptgs, OperationEvaluationContext ec) { - if (ptgs.length == 1) { - return getEvalForPtg(ptgs[0], ec); - } - return evaluateFormula(ec, ptgs); + if (ptgs.length == 1 && !(ptgs[0] instanceof FuncVarPtg)) { + return getEvalForPtg(ptgs[0], ec); + } + + OperationEvaluationContext anyValueContext = new OperationEvaluationContext(this, ec.getWorkbook(), ec.getSheetIndex(), ec.getRowIndex(), ec.getColumnIndex(), new EvaluationTracker(_cache), false); + return evaluateFormula(anyValueContext, ptgs); } /** diff --git a/src/testcases/org/apache/poi/ss/formula/TestWorkbookEvaluator.java b/src/testcases/org/apache/poi/ss/formula/TestWorkbookEvaluator.java index 4441a4fb53..be2cc54cde 100644 --- a/src/testcases/org/apache/poi/ss/formula/TestWorkbookEvaluator.java +++ b/src/testcases/org/apache/poi/ss/formula/TestWorkbookEvaluator.java @@ -274,12 +274,22 @@ public class TestWorkbookEvaluator { Name name3 = wb.createName(); name3.setNameName("aSet"); name3.setRefersToFormula("Sheet1!$A$2:$A$4"); - + + Name name4 = wb.createName(); + name4.setNameName("offsetFormula"); + name4.setRefersToFormula("OFFSET(Sheet1!$A$1:$A$4,2,0,2,1)"); + + Name name5 = wb.createName(); + name5.setNameName("rowFormula"); + name5.setRefersToFormula("ROW()"); Row row0 = sheet.createRow(0); Row row1 = sheet.createRow(1); Row row2 = sheet.createRow(2); Row row3 = sheet.createRow(3); + Row row4 = sheet.createRow(4); + Row row5 = sheet.createRow(5); + row0.createCell(0).setCellValue(2); row1.createCell(0).setCellValue(5); row2.createCell(0).setCellValue(3); @@ -289,16 +299,20 @@ public class TestWorkbookEvaluator { row1.createCell(2).setCellFormula("aFormula"); row2.createCell(2).setCellFormula("SUM(aSet)"); row3.createCell(2).setCellFormula("aConstant+aFormula+SUM(aSet)"); + row4.createCell(2).setCellFormula("SUM(offsetFormula)"); + row5.createCell(2).setCellFormula("rowFormula"); FormulaEvaluator fe = wb.getCreationHelper().createFormulaEvaluator(); assertEquals(3.14, fe.evaluate(row0.getCell(2)).getNumberValue(), EPSILON); assertEquals(10.0, fe.evaluate(row1.getCell(2)).getNumberValue(), EPSILON); assertEquals(15.0, fe.evaluate(row2.getCell(2)).getNumberValue(), EPSILON); assertEquals(28.14, fe.evaluate(row3.getCell(2)).getNumberValue(), EPSILON); + assertEquals(10.0, fe.evaluate(row4.getCell(2)).getNumberValue(), EPSILON); + assertEquals(6.0, fe.evaluate(row5.getCell(2)).getNumberValue(), EPSILON); wb.close(); } - + @Test public void testIgnoreMissingWorkbooks() { // TODO: update this test for meaningful functional behavior diff --git a/test-data/spreadsheet/external_name.xls b/test-data/spreadsheet/external_name.xls new file mode 100644 index 0000000000..b87e6a92d0 Binary files /dev/null and b/test-data/spreadsheet/external_name.xls differ