From 9b208abd096ea79dcb2e9e731aa7f58f06d8d676 Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Sun, 14 Feb 2010 17:11:08 +0000 Subject: [PATCH] Support evaluation of indirect defined names in INDIRECT git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@910043 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/status.xml | 1 + .../formula/OperationEvaluationContext.java | 12 +++++----- .../poi/ss/formula/WorkbookEvaluator.java | 5 ++++- .../formula/functions/TestIndirect.java | 22 ++++++++++++++----- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 28c8f53b0..10ae36634 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + Support evaluation of indirect defined names in INDIRECT 43670 - Improve HDGF ChunkV11 separator detection, and short string detection, to solve the "Negative length of ChunkHeader" problem 48617 - Optionally allow the overriding of the Locale used by DataFormatter to control how the default number and date formats should look New event based xssf text extractor (XSSFEventBasedExcelExtractor) diff --git a/src/java/org/apache/poi/ss/formula/OperationEvaluationContext.java b/src/java/org/apache/poi/ss/formula/OperationEvaluationContext.java index 32bc460d0..147e07d7a 100644 --- a/src/java/org/apache/poi/ss/formula/OperationEvaluationContext.java +++ b/src/java/org/apache/poi/ss/formula/OperationEvaluationContext.java @@ -17,10 +17,7 @@ package org.apache.poi.ss.formula; -import org.apache.poi.hssf.record.formula.eval.AreaEval; -import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.record.formula.eval.RefEval; -import org.apache.poi.hssf.record.formula.eval.ValueEval; +import org.apache.poi.hssf.record.formula.eval.*; import org.apache.poi.hssf.record.formula.functions.FreeRefFunction; import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException; @@ -159,8 +156,11 @@ public final class OperationEvaluationContext { case BAD_CELL_OR_NAMED_RANGE: return ErrorEval.REF_INVALID; case NAMED_RANGE: - throw new RuntimeException("Cannot evaluate '" + refStrPart1 - + "'. Indirect evaluation of defined names not supported yet"); + EvaluationName nm = ((FormulaParsingWorkbook)_workbook).getName(refStrPart1, _sheetIndex); + if(!nm.isRange()){ + throw new RuntimeException("Specified name '" + refStrPart1 + "' is not a range as expected."); + } + return _bookEvaluator.evaluateNameFormula(nm.getNameDefinition(), this); } if (refStrPart2 == null) { // no ':' diff --git a/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java b/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java index 199217eb8..ad15b84e9 100644 --- a/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java +++ b/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java @@ -580,7 +580,10 @@ public final class WorkbookEvaluator { throw new RuntimeException("Unexpected ptg class (" + ptg.getClass().getName() + ")"); } - private ValueEval evaluateNameFormula(Ptg[] ptgs, OperationEvaluationContext ec) { + /** + * YK: Used by OperationEvaluationContext to resolve indirect names. + */ + /*package*/ ValueEval evaluateNameFormula(Ptg[] ptgs, OperationEvaluationContext ec) { if (ptgs.length > 1) { throw new RuntimeException("Complex name formulas not supported yet"); } diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndirect.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndirect.java index 50c206779..6be7b0330 100644 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndirect.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndirect.java @@ -21,14 +21,11 @@ import junit.framework.AssertionFailedError; import junit.framework.TestCase; import org.apache.poi.hssf.record.formula.eval.ErrorEval; -import org.apache.poi.hssf.usermodel.HSSFCell; -import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; -import org.apache.poi.hssf.usermodel.HSSFRow; -import org.apache.poi.hssf.usermodel.HSSFSheet; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.hssf.usermodel.*; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellValue; import org.apache.poi.ss.usermodel.FormulaEvaluator; +import org.apache.poi.ss.util.CellReference; /** * Tests for the INDIRECT() function.

@@ -62,6 +59,19 @@ public final class TestIndirect extends TestCase { createDataRow(sheet3, 0, 30, 31, 32); createDataRow(sheet3, 1, 33, 34, 35); + + HSSFName name1 = wb.createName(); + name1.setNameName("sales1"); + name1.setRefersToFormula("Sheet1!A1:D1"); + + HSSFName name2 = wb.createName(); + name2.setNameName("sales2"); + name2.setRefersToFormula("Sheet2!B1:C3"); + + HSSFRow row = sheet1.createRow(3); + row.createCell(0).setCellValue("sales1"); //A4 + row.createCell(1).setCellValue("sales2"); //B4 + return wb; } @@ -103,6 +113,8 @@ public final class TestIndirect extends TestCase { confirm(feA, c, "INDIRECT(\"A1:G1\")", 13); // de-reference area ref (note formula is in C4) + confirm(feA, c, "SUM(INDIRECT(A4))", 50); // indirect defined name + confirm(feA, c, "SUM(INDIRECT(B4))", 351); // indirect defined name pointinh to other sheet // simple error propagation: