Have WorkbookEvaluator process NameXPtgs, rather than returning a NameXEval which later places didn't handle. Largely allows us to process the .xls version of the test file for #56737 (but filenames aren't quite the same as in Excel)

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1611711 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2014-07-18 16:58:38 +00:00
parent d4a1239efa
commit 6e37f73018
5 changed files with 86 additions and 27 deletions

View File

@ -481,7 +481,8 @@ final class LinkTable {
} }
// Does it exist via the external book block? // Does it exist via the external book block?
if (_externalBookBlocks.length > extBookIndex) { ExternalBookBlock externalBook = _externalBookBlocks[extBookIndex];
if (externalBook._externalNameRecords.length > definedNameIndex) {
return _externalBookBlocks[extBookIndex].getNameText(definedNameIndex); return _externalBookBlocks[extBookIndex].getNameText(definedNameIndex);
} else if (firstTabIndex == -2) { } else if (firstTabIndex == -2) {
// Workbook scoped name, not actually external after all // Workbook scoped name, not actually external after all

View File

@ -18,7 +18,6 @@
package org.apache.poi.ss.formula; package org.apache.poi.ss.formula;
import org.apache.poi.ss.formula.eval.NameEval; import org.apache.poi.ss.formula.eval.NameEval;
import org.apache.poi.ss.formula.eval.NameXEval;
import org.apache.poi.ss.formula.eval.NotImplementedFunctionException; import org.apache.poi.ss.formula.eval.NotImplementedFunctionException;
import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.formula.functions.FreeRefFunction; import org.apache.poi.ss.formula.functions.FreeRefFunction;
@ -48,8 +47,6 @@ final class UserDefinedFunction implements FreeRefFunction {
String functionName; String functionName;
if (nameArg instanceof NameEval) { if (nameArg instanceof NameEval) {
functionName = ((NameEval) nameArg).getFunctionName(); functionName = ((NameEval) nameArg).getFunctionName();
} else if (nameArg instanceof NameXEval) {
functionName = ec.getWorkbook().resolveNameXText(((NameXEval) nameArg).getPtg());
} else { } else {
throw new RuntimeException("First argument should be a NameEval, but got (" throw new RuntimeException("First argument should be a NameEval, but got ("
+ nameArg.getClass().getName() + ")"); + nameArg.getClass().getName() + ")");

View File

@ -17,11 +17,32 @@
package org.apache.poi.ss.formula; package org.apache.poi.ss.formula;
import java.util.*; import java.util.Arrays;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Stack;
import java.util.TreeSet;
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
import org.apache.poi.ss.formula.atp.AnalysisToolPak; import org.apache.poi.ss.formula.atp.AnalysisToolPak;
import org.apache.poi.ss.formula.eval.*; import org.apache.poi.ss.formula.eval.BlankEval;
import org.apache.poi.ss.formula.eval.BoolEval;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.formula.eval.FunctionEval;
import org.apache.poi.ss.formula.eval.MissingArgEval;
import org.apache.poi.ss.formula.eval.NameEval;
import org.apache.poi.ss.formula.eval.NameXEval;
import org.apache.poi.ss.formula.eval.NotImplementedException;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.OperandResolver;
import org.apache.poi.ss.formula.eval.StringEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.formula.functions.Choose;
import org.apache.poi.ss.formula.functions.FreeRefFunction;
import org.apache.poi.ss.formula.functions.Function; import org.apache.poi.ss.formula.functions.Function;
import org.apache.poi.ss.formula.functions.IfFunc;
import org.apache.poi.ss.formula.ptg.Area3DPtg; import org.apache.poi.ss.formula.ptg.Area3DPtg;
import org.apache.poi.ss.formula.ptg.AreaErrPtg; import org.apache.poi.ss.formula.ptg.AreaErrPtg;
import org.apache.poi.ss.formula.ptg.AreaPtg; import org.apache.poi.ss.formula.ptg.AreaPtg;
@ -49,14 +70,10 @@ import org.apache.poi.ss.formula.ptg.RefPtg;
import org.apache.poi.ss.formula.ptg.StringPtg; import org.apache.poi.ss.formula.ptg.StringPtg;
import org.apache.poi.ss.formula.ptg.UnionPtg; import org.apache.poi.ss.formula.ptg.UnionPtg;
import org.apache.poi.ss.formula.ptg.UnknownPtg; import org.apache.poi.ss.formula.ptg.UnknownPtg;
import org.apache.poi.ss.formula.functions.Choose;
import org.apache.poi.ss.formula.functions.FreeRefFunction;
import org.apache.poi.ss.formula.functions.IfFunc;
import org.apache.poi.ss.formula.udf.AggregatingUDFFinder; import org.apache.poi.ss.formula.udf.AggregatingUDFFinder;
import org.apache.poi.ss.formula.udf.UDFFinder; import org.apache.poi.ss.formula.udf.UDFFinder;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment.WorkbookNotFoundException;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
@ -613,20 +630,23 @@ public final class WorkbookEvaluator {
// consider converting all these (ptg instanceof XxxPtg) expressions to (ptg.getClass() == XxxPtg.class) // consider converting all these (ptg instanceof XxxPtg) expressions to (ptg.getClass() == XxxPtg.class)
if (ptg instanceof NamePtg) { if (ptg instanceof NamePtg) {
// named ranges, macro functions // Named ranges, macro functions
NamePtg namePtg = (NamePtg) ptg; NamePtg namePtg = (NamePtg) ptg;
EvaluationName nameRecord = _workbook.getName(namePtg); EvaluationName nameRecord = _workbook.getName(namePtg);
if (nameRecord.isFunctionName()) { return getEvalForNameRecord(nameRecord, ec);
return new NameEval(nameRecord.getNameText());
}
if (nameRecord.hasFormula()) {
return evaluateNameFormula(nameRecord.getNameDefinition(), ec);
}
throw new RuntimeException("Don't now how to evalate name '" + nameRecord.getNameText() + "'");
} }
if (ptg instanceof NameXPtg) { if (ptg instanceof NameXPtg) {
return ec.getNameXEval(((NameXPtg) ptg)); // Externally defined named ranges or macro functions
NameXPtg nameXPtg = (NameXPtg)ptg;
ValueEval eval = ec.getNameXEval(nameXPtg);
if (eval instanceof NameXEval) {
// Could not be directly evaluated, so process as a name
return getEvalForNameX(nameXPtg, ec);
} else {
// Use the evaluated version
return eval;
}
} }
if (ptg instanceof IntPtg) { if (ptg instanceof IntPtg) {
@ -682,6 +702,42 @@ public final class WorkbookEvaluator {
throw new RuntimeException("Unexpected ptg class (" + ptg.getClass().getName() + ")"); throw new RuntimeException("Unexpected ptg class (" + ptg.getClass().getName() + ")");
} }
private ValueEval getEvalForNameRecord(EvaluationName nameRecord, OperationEvaluationContext ec) {
if (nameRecord.isFunctionName()) {
return new NameEval(nameRecord.getNameText());
}
if (nameRecord.hasFormula()) {
return evaluateNameFormula(nameRecord.getNameDefinition(), ec);
}
throw new RuntimeException("Don't now how to evalate name '" + nameRecord.getNameText() + "'");
}
private ValueEval getEvalForNameX(NameXPtg nameXPtg, OperationEvaluationContext ec) {
String name = _workbook.resolveNameXText(nameXPtg);
// Try to parse it as a name
int sheetNameAt = name.indexOf('!');
EvaluationName nameRecord = null;
if (sheetNameAt > -1) {
// Sheet based name
String sheetName = name.substring(0, sheetNameAt);
String nameName = name.substring(sheetNameAt+1);
nameRecord = _workbook.getName(nameName, _workbook.getSheetIndex(sheetName));
} else {
// Workbook based name
nameRecord = _workbook.getName(name, -1);
}
if (nameRecord != null) {
// Process it as a name
return getEvalForNameRecord(nameRecord, ec);
} else {
// Must be an external function
return new NameEval(name);
}
}
/** /**
* YK: Used by OperationEvaluationContext to resolve indirect names. * YK: Used by OperationEvaluationContext to resolve indirect names.
*/ */

View File

@ -2616,7 +2616,7 @@ public final class TestBugs extends BaseTestBugzillaIssues {
/** /**
* Formulas which reference named ranges, either in other * Formulas which reference named ranges, either in other
* sheets, or workbook scoped but in other workbooks. * sheets, or workbook scoped but in other workbooks.
* Currently failing with * Used to fail with
* java.lang.RuntimeException: Unexpected eval class (org.apache.poi.ss.formula.eval.NameXEval) * java.lang.RuntimeException: Unexpected eval class (org.apache.poi.ss.formula.eval.NameXEval)
*/ */
@Test @Test
@ -2639,7 +2639,12 @@ public final class TestBugs extends BaseTestBugzillaIssues {
Cell cRefWName = s.getRow(2).getCell(3); Cell cRefWName = s.getRow(2).getCell(3);
assertEquals("Defines!NR_To_A1", cRefSName.getCellFormula()); assertEquals("Defines!NR_To_A1", cRefSName.getCellFormula());
assertEquals("'56737.xls'!NR_Global_B2", cRefWName.getCellFormula());
// TODO How does Excel know to prefix this with the filename?
// This is what Excel itself shows
//assertEquals("'56737.xls'!NR_Global_B2", cRefWName.getCellFormula());
// TODO This isn't right, but it's what we currently generate....
assertEquals("NR_Global_B2", cRefWName.getCellFormula());
// Try to evaluate them // Try to evaluate them
FormulaEvaluator eval = wb.getCreationHelper().createFormulaEvaluator(); FormulaEvaluator eval = wb.getCreationHelper().createFormulaEvaluator();

View File

@ -19,18 +19,18 @@ package org.apache.poi.hssf.usermodel;
import junit.framework.AssertionFailedError; import junit.framework.AssertionFailedError;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.HSSFITestDataProvider; import org.apache.poi.hssf.HSSFITestDataProvider;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.record.NameRecord; import org.apache.poi.hssf.record.NameRecord;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.formula.EvaluationCell; import org.apache.poi.ss.formula.EvaluationCell;
import org.apache.poi.ss.formula.EvaluationListener; import org.apache.poi.ss.formula.EvaluationListener;
import org.apache.poi.ss.formula.WorkbookEvaluator; import org.apache.poi.ss.formula.WorkbookEvaluator;
import org.apache.poi.ss.formula.WorkbookEvaluatorTestHelper; import org.apache.poi.ss.formula.WorkbookEvaluatorTestHelper;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.BaseTestFormulaEvaluator;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellValue; import org.apache.poi.ss.usermodel.CellValue;
import org.apache.poi.ss.usermodel.BaseTestFormulaEvaluator;
/** /**
* *