aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJosh Micich <josh@apache.org>2009-01-22 00:26:28 +0000
committerJosh Micich <josh@apache.org>2009-01-22 00:26:28 +0000
commit85f7da217e4a56792a518b3ac15ca9a8263d3e29 (patch)
tree0d69bc6127ada22e3fb9ae5d33eda16853775361 /src
parent647f94ed663ef3e6bdbfa101dec2478fab05fa83 (diff)
downloadpoi-85f7da217e4a56792a518b3ac15ca9a8263d3e29.tar.gz
poi-85f7da217e4a56792a518b3ac15ca9a8263d3e29.zip
Bugzilla 46580 - Replaced ErrorEval.FUNCTION_NOT_IMPLEMENTED with new exception NotImplementedException. Removed test case involving ISREF which was working for the wrong reasons.
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@736505 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src')
-rw-r--r--src/java/org/apache/poi/hssf/record/formula/atp/AnalysisToolPak.java23
-rw-r--r--src/java/org/apache/poi/hssf/record/formula/eval/ErrorEval.java2
-rwxr-xr-xsrc/java/org/apache/poi/hssf/record/formula/eval/ExternalFunction.java30
-rw-r--r--src/java/org/apache/poi/hssf/record/formula/eval/FuncVarEval.java31
-rw-r--r--src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java157
-rw-r--r--src/java/org/apache/poi/hssf/record/formula/functions/Indirect.java5
-rw-r--r--src/java/org/apache/poi/hssf/record/formula/functions/NotImplementedFunction.java59
-rw-r--r--src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java22
-rw-r--r--src/java/org/apache/poi/ss/formula/eval/NotImplementedException.java36
-rw-r--r--src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xlsbin157184 -> 157184 bytes
-rwxr-xr-xsrc/testcases/org/apache/poi/hssf/record/formula/eval/TestExternalFunction.java16
-rwxr-xr-xsrc/testcases/org/apache/poi/hssf/record/formula/functions/NumericFunctionInvoker.java20
12 files changed, 233 insertions, 168 deletions
diff --git a/src/java/org/apache/poi/hssf/record/formula/atp/AnalysisToolPak.java b/src/java/org/apache/poi/hssf/record/formula/atp/AnalysisToolPak.java
index ca9dd7d3e0..104b7a86d2 100644
--- a/src/java/org/apache/poi/hssf/record/formula/atp/AnalysisToolPak.java
+++ b/src/java/org/apache/poi/hssf/record/formula/atp/AnalysisToolPak.java
@@ -20,34 +20,39 @@ package org.apache.poi.hssf.record.formula.atp;
import java.util.HashMap;
import java.util.Map;
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
import org.apache.poi.ss.formula.EvaluationWorkbook;
+import org.apache.poi.ss.formula.eval.NotImplementedException;
public final class AnalysisToolPak {
- private static final FreeRefFunction NotImplemented = new FreeRefFunction() {
+ private static final class NotImplemented implements FreeRefFunction {
+ private final String _functionName;
+
+ public NotImplemented(String functionName) {
+ _functionName = functionName;
+ }
public ValueEval evaluate(Eval[] args, EvaluationWorkbook workbook, int srcCellSheet,
int srcCellRow, int srcCellCol) {
- return ErrorEval.FUNCTION_NOT_IMPLEMENTED;
+ throw new NotImplementedException(_functionName);
}
};
- private static Map _functionsByName = createFunctionsMap();
+ private static Map<String, FreeRefFunction> _functionsByName = createFunctionsMap();
private AnalysisToolPak() {
// no instances of this class
}
public static FreeRefFunction findFunction(String name) {
- return (FreeRefFunction)_functionsByName.get(name);
+ return _functionsByName.get(name);
}
- private static Map createFunctionsMap() {
- Map m = new HashMap(100);
+ private static Map<String, FreeRefFunction> createFunctionsMap() {
+ Map<String, FreeRefFunction> m = new HashMap<String, FreeRefFunction>(100);
r(m, "ACCRINT", null);
r(m, "ACCRINTM", null);
@@ -146,8 +151,8 @@ public final class AnalysisToolPak {
return m;
}
- private static void r(Map m, String functionName, FreeRefFunction pFunc) {
- FreeRefFunction func = pFunc == null ? NotImplemented : pFunc;
+ private static void r(Map<String, FreeRefFunction> m, String functionName, FreeRefFunction pFunc) {
+ FreeRefFunction func = pFunc == null ? new NotImplemented(functionName) : pFunc;
m.put(functionName, func);
}
}
diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/ErrorEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/ErrorEval.java
index e8e197d201..687052566b 100644
--- a/src/java/org/apache/poi/hssf/record/formula/eval/ErrorEval.java
+++ b/src/java/org/apache/poi/hssf/record/formula/eval/ErrorEval.java
@@ -48,7 +48,6 @@ public final class ErrorEval implements ValueEval {
private static final int CIRCULAR_REF_ERROR_CODE = 0xFFFFFFC4;
private static final int FUNCTION_NOT_IMPLEMENTED_CODE = 0xFFFFFFE2;
- public static final ErrorEval FUNCTION_NOT_IMPLEMENTED = new ErrorEval(FUNCTION_NOT_IMPLEMENTED_CODE);
// Note - Excel does not seem to represent this condition with an error code
public static final ErrorEval CIRCULAR_REF_ERROR = new ErrorEval(CIRCULAR_REF_ERROR_CODE);
@@ -68,7 +67,6 @@ public final class ErrorEval implements ValueEval {
case HSSFErrorConstants.ERROR_NA: return NA;
// non-std errors (conditions modeled as errors by POI)
case CIRCULAR_REF_ERROR_CODE: return CIRCULAR_REF_ERROR;
- case FUNCTION_NOT_IMPLEMENTED_CODE: return FUNCTION_NOT_IMPLEMENTED;
}
throw new RuntimeException("Unexpected error code (" + errorCode + ")");
}
diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/ExternalFunction.java b/src/java/org/apache/poi/hssf/record/formula/eval/ExternalFunction.java
index 8e8a9799e4..d4d6de6a6d 100755
--- a/src/java/org/apache/poi/hssf/record/formula/eval/ExternalFunction.java
+++ b/src/java/org/apache/poi/hssf/record/formula/eval/ExternalFunction.java
@@ -20,6 +20,7 @@ package org.apache.poi.hssf.record.formula.eval;
import org.apache.poi.hssf.record.formula.atp.AnalysisToolPak;
import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
import org.apache.poi.ss.formula.EvaluationWorkbook;
+import org.apache.poi.ss.formula.eval.NotImplementedException;
/**
*
* Common entry point for all user-defined (non-built-in) functions (where
@@ -40,17 +41,13 @@ final class ExternalFunction implements FreeRefFunction {
Eval nameArg = args[0];
FreeRefFunction targetFunc;
- try {
- if (nameArg instanceof NameEval) {
- targetFunc = findInternalUserDefinedFunction((NameEval) nameArg);
- } else if (nameArg instanceof NameXEval) {
- targetFunc = findExternalUserDefinedFunction(workbook, (NameXEval) nameArg);
- } else {
- throw new RuntimeException("First argument should be a NameEval, but got ("
- + nameArg.getClass().getName() + ")");
- }
- } catch (EvaluationException e) {
- return e.getErrorEval();
+ if (nameArg instanceof NameEval) {
+ targetFunc = findInternalUserDefinedFunction((NameEval) nameArg);
+ } else if (nameArg instanceof NameXEval) {
+ targetFunc = findExternalUserDefinedFunction(workbook, (NameXEval) nameArg);
+ } else {
+ throw new RuntimeException("First argument should be a NameEval, but got ("
+ + nameArg.getClass().getName() + ")");
}
int nOutGoingArgs = nIncomingArgs -1;
Eval[] outGoingArgs = new Eval[nOutGoingArgs];
@@ -58,8 +55,8 @@ final class ExternalFunction implements FreeRefFunction {
return targetFunc.evaluate(outGoingArgs, workbook, srcCellSheet, srcCellRow, srcCellCol);
}
- private FreeRefFunction findExternalUserDefinedFunction(EvaluationWorkbook workbook,
- NameXEval n) throws EvaluationException {
+ private static FreeRefFunction findExternalUserDefinedFunction(EvaluationWorkbook workbook,
+ NameXEval n) {
String functionName = workbook.resolveNameXText(n.getPtg());
if(false) {
@@ -71,10 +68,10 @@ final class ExternalFunction implements FreeRefFunction {
if (result != null) {
return result;
}
- throw new EvaluationException(ErrorEval.FUNCTION_NOT_IMPLEMENTED);
+ throw new NotImplementedException(functionName);
}
- private FreeRefFunction findInternalUserDefinedFunction(NameEval functionNameEval) throws EvaluationException {
+ private static FreeRefFunction findInternalUserDefinedFunction(NameEval functionNameEval) {
String functionName = functionNameEval.getFunctionName();
if(false) {
@@ -82,7 +79,6 @@ final class ExternalFunction implements FreeRefFunction {
}
// TODO find the implementation for the user defined function
- throw new EvaluationException(ErrorEval.FUNCTION_NOT_IMPLEMENTED);
+ throw new NotImplementedException(functionName);
}
}
-
diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/FuncVarEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/FuncVarEval.java
index d30c353599..76cfe7bb61 100644
--- a/src/java/org/apache/poi/hssf/record/formula/eval/FuncVarEval.java
+++ b/src/java/org/apache/poi/hssf/record/formula/eval/FuncVarEval.java
@@ -19,6 +19,7 @@ package org.apache.poi.hssf.record.formula.eval;
import org.apache.poi.hssf.record.formula.AbstractFunctionPtg;
import org.apache.poi.hssf.record.formula.functions.Function;
+import org.apache.poi.ss.formula.eval.NotImplementedException;
/**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
@@ -26,25 +27,25 @@ import org.apache.poi.hssf.record.formula.functions.Function;
*/
public final class FuncVarEval extends FunctionEval {
- private AbstractFunctionPtg delegate;
+ private AbstractFunctionPtg delegate;
- public FuncVarEval(AbstractFunctionPtg funcPtg) {
- delegate = funcPtg;
- }
+ public FuncVarEval(AbstractFunctionPtg funcPtg) {
+ delegate = funcPtg;
+ }
- public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
- Function f = getFunction();
- if (f == null) {
- return ErrorEval.FUNCTION_NOT_IMPLEMENTED;
+ public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
+ Function f = getFunction();
+ if (f == null) {
+ throw new NotImplementedException("FuncIx=" + getFunctionIndex());
}
return f.evaluate(operands, srcRow, srcCol);
- }
+ }
- public int getNumberOfOperands() {
- return delegate.getNumberOfOperands();
- }
+ public int getNumberOfOperands() {
+ return delegate.getNumberOfOperands();
+ }
- public short getFunctionIndex() {
- return delegate.getFunctionIndex();
- }
+ public short getFunctionIndex() {
+ return delegate.getFunctionIndex();
+ }
}
diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java
index e68b8ee67d..2940af6869 100644
--- a/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java
+++ b/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java
@@ -43,17 +43,14 @@ public abstract class FunctionEval implements OperationEval {
protected static Function[] functions = produceFunctions();
- private static Map freeRefFunctionsByIdMap;
+ private static Map<Integer, FreeRefFunction> freeRefFunctionsByIdMap;
static {
- Map m = new HashMap();
- addMapping(m, ID.INDIRECT, new Indirect());
- addMapping(m, ID.EXTERNAL_FUNC, new ExternalFunction());
+ Map<Integer, FreeRefFunction> m = new HashMap<Integer, FreeRefFunction>();
+ m.put(createFRFKey(ID.INDIRECT), new Indirect());
+ m.put(createFRFKey(ID.EXTERNAL_FUNC), new ExternalFunction());
freeRefFunctionsByIdMap = m;
}
- private static void addMapping(Map m, int offset, FreeRefFunction frf) {
- m.put(createFRFKey(offset), frf);
- }
private static Integer createFRFKey(int functionIndex) {
return new Integer(functionIndex);
}
@@ -67,7 +64,7 @@ public abstract class FunctionEval implements OperationEval {
return freeRefFunctionsByIdMap.containsKey(createFRFKey(getFunctionIndex()));
}
public FreeRefFunction getFreeRefFunction() {
- return (FreeRefFunction) freeRefFunctionsByIdMap.get(createFRFKey(getFunctionIndex()));
+ return freeRefFunctionsByIdMap.get(createFRFKey(getFunctionIndex()));
}
public abstract short getFunctionIndex();
@@ -164,11 +161,11 @@ public abstract class FunctionEval implements OperationEval {
retval[88] = new Setname(); // SETNAME
retval[89] = new Caller(); // CALLER
retval[90] = new Deref(); // DEREF
- retval[91] = new NotImplementedFunction(); // WINDOWS
+ retval[91] = new NotImplementedFunction("WINDOWS");
retval[92] = new Series(); // SERIES
- retval[93] = new NotImplementedFunction(); // DOCUMENTS
+ retval[93] = new NotImplementedFunction("DOCUMENTS");
retval[94] = new Activecell(); // ACTIVECELL
- retval[95] = new NotImplementedFunction(); // SELECTION
+ retval[95] = new NotImplementedFunction("SELECTION");
retval[96] = new Result(); // RESULT
retval[97] = NumericFunction.ATAN2;
retval[98] = NumericFunction.ASIN;
@@ -179,8 +176,8 @@ public abstract class FunctionEval implements OperationEval {
retval[103] = new Links(); // LINKS
retval[104] = new Input(); // INPUT
retval[105] = new Isref(); // ISREF
- retval[106] = new NotImplementedFunction(); // GETFORMULA
- retval[107] = new NotImplementedFunction(); // GETNAME
+ retval[106] = new NotImplementedFunction("GETFORMULA");
+ retval[107] = new NotImplementedFunction("GETNAME");
retval[108] = new Setvalue(); // SETVALUE
retval[109] = NumericFunction.LOG;
retval[110] = new Exec(); // EXEC
@@ -196,7 +193,7 @@ public abstract class FunctionEval implements OperationEval {
retval[120] = new Substitute(); // SUBSTITUTE
retval[121] = new Code(); // CODE
retval[122] = new Names(); // NAMES
- retval[123] = new NotImplementedFunction(); // DIRECTORY
+ retval[123] = new NotImplementedFunction("DIRECTORY");
retval[124] = new Find(); // FIND
retval[125] = new Cell(); // CELL
retval[126] = new Iserr(); // ISERR
@@ -205,36 +202,36 @@ public abstract class FunctionEval implements OperationEval {
retval[129] = new Isblank(); // ISBLANK
retval[130] = new T(); // T
retval[131] = new N(); // N
- retval[132] = new NotImplementedFunction(); // FOPEN
- retval[133] = new NotImplementedFunction(); // FCLOSE
- retval[134] = new NotImplementedFunction(); // FSIZE
- retval[135] = new NotImplementedFunction(); // FREADLN
- retval[136] = new NotImplementedFunction(); // FREAD
- retval[137] = new NotImplementedFunction(); // FWRITELN
- retval[138] = new NotImplementedFunction(); // FWRITE
+ retval[132] = new NotImplementedFunction("FOPEN");
+ retval[133] = new NotImplementedFunction("FCLOSE");
+ retval[134] = new NotImplementedFunction("FSIZE");
+ retval[135] = new NotImplementedFunction("FREADLN");
+ retval[136] = new NotImplementedFunction("FREAD");
+ retval[137] = new NotImplementedFunction("FWRITELN");
+ retval[138] = new NotImplementedFunction("FWRITE");
retval[139] = new Fpos(); // FPOS
retval[140] = new Datevalue(); // DATEVALUE
retval[141] = new Timevalue(); // TIMEVALUE
retval[142] = new Sln(); // SLN
retval[143] = new Syd(); // SYD
retval[144] = new Ddb(); // DDB
- retval[145] = new NotImplementedFunction(); // GETDEF
+ retval[145] = new NotImplementedFunction("GETDEF");
retval[146] = new Reftext(); // REFTEXT
retval[147] = new Textref(); // TEXTREF
retval[ID.INDIRECT] = null; // Indirect.evaluate has different signature
- retval[149] = new NotImplementedFunction(); // REGISTER
+ retval[149] = new NotImplementedFunction("REGISTER");
retval[150] = new Call(); // CALL
- retval[151] = new NotImplementedFunction(); // ADDBAR
- retval[152] = new NotImplementedFunction(); // ADDMENU
- retval[153] = new NotImplementedFunction(); // ADDCOMMAND
- retval[154] = new NotImplementedFunction(); // ENABLECOMMAND
- retval[155] = new NotImplementedFunction(); // CHECKCOMMAND
- retval[156] = new NotImplementedFunction(); // RENAMECOMMAND
- retval[157] = new NotImplementedFunction(); // SHOWBAR
- retval[158] = new NotImplementedFunction(); // DELETEMENU
- retval[159] = new NotImplementedFunction(); // DELETECOMMAND
- retval[160] = new NotImplementedFunction(); // GETCHARTITEM
- retval[161] = new NotImplementedFunction(); // DIALOGBOX
+ retval[151] = new NotImplementedFunction("ADDBAR");
+ retval[152] = new NotImplementedFunction("ADDMENU");
+ retval[153] = new NotImplementedFunction("ADDCOMMAND");
+ retval[154] = new NotImplementedFunction("ENABLECOMMAND");
+ retval[155] = new NotImplementedFunction("CHECKCOMMAND");
+ retval[156] = new NotImplementedFunction("RENAMECOMMAND");
+ retval[157] = new NotImplementedFunction("SHOWBAR");
+ retval[158] = new NotImplementedFunction("DELETEMENU");
+ retval[159] = new NotImplementedFunction("DELETECOMMAND");
+ retval[160] = new NotImplementedFunction("GETCHARTITEM");
+ retval[161] = new NotImplementedFunction("DIALOGBOX");
retval[162] = new Clean(); // CLEAN
retval[163] = new Mdeterm(); // MDETERM
retval[164] = new Minverse(); // MINVERSE
@@ -243,24 +240,24 @@ public abstract class FunctionEval implements OperationEval {
retval[167] = new Ipmt(); // IPMT
retval[168] = new Ppmt(); // PPMT
retval[169] = new Counta(); // COUNTA
- retval[170] = new NotImplementedFunction(); // CANCELKEY
+ retval[170] = new NotImplementedFunction("CANCELKEY");
retval[175] = new Initiate(); // INITIATE
retval[176] = new Request(); // REQUEST
- retval[177] = new NotImplementedFunction(); // POKE
- retval[178] = new NotImplementedFunction(); // EXECUTE
- retval[179] = new NotImplementedFunction(); // TERMINATE
- retval[180] = new NotImplementedFunction(); // RESTART
+ retval[177] = new NotImplementedFunction("POKE");
+ retval[178] = new NotImplementedFunction("EXECUTE");
+ retval[179] = new NotImplementedFunction("TERMINATE");
+ retval[180] = new NotImplementedFunction("RESTART");
retval[181] = new Help(); // HELP
- retval[182] = new NotImplementedFunction(); // GETBAR
+ retval[182] = new NotImplementedFunction("GETBAR");
retval[183] = AggregateFunction.PRODUCT;
retval[184] = NumericFunction.FACT;
- retval[185] = new NotImplementedFunction(); // GETCELL
- retval[186] = new NotImplementedFunction(); // GETWORKSPACE
- retval[187] = new NotImplementedFunction(); // GETWINDOW
- retval[188] = new NotImplementedFunction(); // GETDOCUMENT
+ retval[185] = new NotImplementedFunction("GETCELL");
+ retval[186] = new NotImplementedFunction("GETWORKSPACE");
+ retval[187] = new NotImplementedFunction("GETWINDOW");
+ retval[188] = new NotImplementedFunction("GETDOCUMENT");
retval[189] = new Dproduct(); // DPRODUCT
retval[190] = new Isnontext(); // ISNONTEXT
- retval[191] = new NotImplementedFunction(); // GETNOTE
+ retval[191] = new NotImplementedFunction("GETNOTE");
retval[192] = new Note(); // NOTE
retval[193] = new Stdevp(); // STDEVP
retval[194] = new Varp(); // VARP
@@ -269,8 +266,8 @@ public abstract class FunctionEval implements OperationEval {
retval[197] = new Trunc(); // TRUNC
retval[198] = new Islogical(); // ISLOGICAL
retval[199] = new Dcounta(); // DCOUNTA
- retval[200] = new NotImplementedFunction(); // DELETEBAR
- retval[201] = new NotImplementedFunction(); // UNREGISTER
+ retval[200] = new NotImplementedFunction("DELETEBAR");
+ retval[201] = new NotImplementedFunction("UNREGISTER");
retval[204] = new Usdollar(); // USDOLLAR
retval[205] = new Findb(); // FINDB
retval[206] = new Searchb(); // SEARCHB
@@ -297,37 +294,37 @@ public abstract class FunctionEval implements OperationEval {
retval[233] = NumericFunction.ACOSH;
retval[234] = NumericFunction.ATANH;
retval[235] = new Dget(); // DGET
- retval[236] = new NotImplementedFunction(); // CREATEOBJECT
+ retval[236] = new NotImplementedFunction("CREATEOBJECT");
retval[237] = new Volatile(); // VOLATILE
retval[238] = new Lasterror(); // LASTERROR
- retval[239] = new NotImplementedFunction(); // CUSTOMUNDO
+ retval[239] = new NotImplementedFunction("CUSTOMUNDO");
retval[240] = new Customrepeat(); // CUSTOMREPEAT
retval[241] = new Formulaconvert(); // FORMULACONVERT
- retval[242] = new NotImplementedFunction(); // GETLINKINFO
- retval[243] = new NotImplementedFunction(); // TEXTBOX
+ retval[242] = new NotImplementedFunction("GETLINKINFO");
+ retval[243] = new NotImplementedFunction("TEXTBOX");
retval[244] = new Info(); // INFO
retval[245] = new Group(); // GROUP
- retval[246] = new NotImplementedFunction(); // GETOBJECT
+ retval[246] = new NotImplementedFunction("GETOBJECT");
retval[247] = new Db(); // DB
- retval[248] = new NotImplementedFunction(); // PAUSE
- retval[250] = new NotImplementedFunction(); // RESUME
+ retval[248] = new NotImplementedFunction("PAUSE");
+ retval[250] = new NotImplementedFunction("RESUME");
retval[252] = new Frequency(); // FREQUENCY
- retval[253] = new NotImplementedFunction(); // ADDTOOLBAR
- retval[254] = new NotImplementedFunction(); // DELETETOOLBAR
+ retval[253] = new NotImplementedFunction("ADDTOOLBAR");
+ retval[254] = new NotImplementedFunction("DELETETOOLBAR");
retval[ID.EXTERNAL_FUNC] = null; // ExternalFunction is a FreeREfFunction
- retval[256] = new NotImplementedFunction(); // RESETTOOLBAR
+ retval[256] = new NotImplementedFunction("RESETTOOLBAR");
retval[257] = new Evaluate(); // EVALUATE
- retval[258] = new NotImplementedFunction(); // GETTOOLBAR
- retval[259] = new NotImplementedFunction(); // GETTOOL
- retval[260] = new NotImplementedFunction(); // SPELLINGCHECK
+ retval[258] = new NotImplementedFunction("GETTOOLBAR");
+ retval[259] = new NotImplementedFunction("GETTOOL");
+ retval[260] = new NotImplementedFunction("SPELLINGCHECK");
retval[261] = new Errortype(); // ERRORTYPE
- retval[262] = new NotImplementedFunction(); // APPTITLE
- retval[263] = new NotImplementedFunction(); // WINDOWTITLE
- retval[264] = new NotImplementedFunction(); // SAVETOOLBAR
- retval[265] = new NotImplementedFunction(); // ENABLETOOL
- retval[266] = new NotImplementedFunction(); // PRESSTOOL
- retval[267] = new NotImplementedFunction(); // REGISTERID
- retval[268] = new NotImplementedFunction(); // GETWORKBOOK
+ retval[262] = new NotImplementedFunction("APPTITLE");
+ retval[263] = new NotImplementedFunction("WINDOWTITLE");
+ retval[264] = new NotImplementedFunction("SAVETOOLBAR");
+ retval[265] = new NotImplementedFunction("ENABLETOOL");
+ retval[266] = new NotImplementedFunction("PRESSTOOL");
+ retval[267] = new NotImplementedFunction("REGISTERID");
+ retval[268] = new NotImplementedFunction("GETWORKBOOK");
retval[269] = AggregateFunction.AVEDEV;
retval[270] = new Betadist(); // BETADIST
retval[271] = new Gammaln(); // GAMMALN
@@ -392,33 +389,33 @@ public abstract class FunctionEval implements OperationEval {
retval[330] = new Mode(); // MODE
retval[331] = new Trimmean(); // TRIMMEAN
retval[332] = new Tinv(); // TINV
- retval[334] = new NotImplementedFunction(); // MOVIECOMMAND
- retval[335] = new NotImplementedFunction(); // GETMOVIE
+ retval[334] = new NotImplementedFunction("MOVIECOMMAND");
+ retval[335] = new NotImplementedFunction("GETMOVIE");
retval[336] = TextFunction.CONCATENATE;
retval[337] = NumericFunction.POWER;
- retval[338] = new NotImplementedFunction(); // PIVOTADDDATA
- retval[339] = new NotImplementedFunction(); // GETPIVOTTABLE
- retval[340] = new NotImplementedFunction(); // GETPIVOTFIELD
- retval[341] = new NotImplementedFunction(); // GETPIVOTITEM
+ retval[338] = new NotImplementedFunction("PIVOTADDDATA");
+ retval[339] = new NotImplementedFunction("GETPIVOTTABLE");
+ retval[340] = new NotImplementedFunction("GETPIVOTFIELD");
+ retval[341] = new NotImplementedFunction("GETPIVOTITEM");
retval[342] = NumericFunction.RADIANS;
retval[343] = NumericFunction.DEGREES;
retval[344] = new Subtotal(); // SUBTOTAL
retval[345] = new Sumif(); // SUMIF
retval[346] = new Countif(); // COUNTIF
retval[347] = new Countblank(); // COUNTBLANK
- retval[348] = new NotImplementedFunction(); // SCENARIOGET
- retval[349] = new NotImplementedFunction(); // OPTIONSLISTSGET
+ retval[348] = new NotImplementedFunction("SCENARIOGET");
+ retval[349] = new NotImplementedFunction("OPTIONSLISTSGET");
retval[350] = new Ispmt(); // ISPMT
retval[351] = new Datedif(); // DATEDIF
retval[352] = new Datestring(); // DATESTRING
retval[353] = new Numberstring(); // NUMBERSTRING
retval[354] = new Roman(); // ROMAN
- retval[355] = new NotImplementedFunction(); // OPENDIALOG
- retval[356] = new NotImplementedFunction(); // SAVEDIALOG
- retval[357] = new NotImplementedFunction(); // VIEWGET
- retval[358] = new NotImplementedFunction(); // GETPIVOTDATA
+ retval[355] = new NotImplementedFunction("OPENDIALOG");
+ retval[356] = new NotImplementedFunction("SAVEDIALOG");
+ retval[357] = new NotImplementedFunction("VIEWGET");
+ retval[358] = new NotImplementedFunction("GETPIVOTDATA");
retval[359] = new Hyperlink(); // HYPERLINK
- retval[360] = new NotImplementedFunction(); // PHONETIC
+ retval[360] = new NotImplementedFunction("PHONETIC");
retval[361] = new Averagea(); // AVERAGEA
retval[362] = MinaMaxa.MAXA;
retval[363] = MinaMaxa.MINA;
diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Indirect.java b/src/java/org/apache/poi/hssf/record/formula/functions/Indirect.java
index 567f29b2b1..acac8488d4 100644
--- a/src/java/org/apache/poi/hssf/record/formula/functions/Indirect.java
+++ b/src/java/org/apache/poi/hssf/record/formula/functions/Indirect.java
@@ -17,10 +17,10 @@
package org.apache.poi.hssf.record.formula.functions;
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.ss.formula.EvaluationWorkbook;
+import org.apache.poi.ss.formula.eval.NotImplementedException;
/**
* Implementation for Excel function INDIRECT<p/>
@@ -42,7 +42,6 @@ public final class Indirect implements FreeRefFunction {
public ValueEval evaluate(Eval[] args, EvaluationWorkbook workbook, int srcCellSheet, int srcCellRow, int srcCellCol) {
// TODO - implement INDIRECT()
- return ErrorEval.FUNCTION_NOT_IMPLEMENTED;
+ throw new NotImplementedException("INDIRECT");
}
-
}
diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/NotImplementedFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/NotImplementedFunction.java
index 49ed84fb46..19643abf66 100644
--- a/src/java/org/apache/poi/hssf/record/formula/functions/NotImplementedFunction.java
+++ b/src/java/org/apache/poi/hssf/record/formula/functions/NotImplementedFunction.java
@@ -1,41 +1,44 @@
-/*
-* 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.
-*/
-/*
- * Created on May 6, 2005
- *
- */
+/* ====================================================================
+ 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.hssf.record.formula.functions;
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
+import org.apache.poi.ss.formula.eval.NotImplementedException;
/**
*
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* This is the default implementation of a Function class.
- * The default behaviour is to return a non-standard ErrorEval
- * "ErrorEval.FUNCTION_NOT_IMPLEMENTED". This error should alert
+ * The default behaviour is to raise a POI internal error
+ * ({@link NotImplementedException}). This error should alert
* the user that the formula contained a function that is not
* yet implemented.
*/
public class NotImplementedFunction implements Function {
-
- public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
- return ErrorEval.FUNCTION_NOT_IMPLEMENTED;
- }
-
+ private final String _functionName;
+ protected NotImplementedFunction() {
+ _functionName = getClass().getName();
+ }
+ public NotImplementedFunction(String name) {
+ _functionName = name;
+ }
+
+ public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
+ throw new NotImplementedException(_functionName);
+ }
}
diff --git a/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java b/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java
index f913f924e2..cb26cb2470 100644
--- a/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java
+++ b/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java
@@ -63,6 +63,7 @@ import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet;
+import org.apache.poi.ss.formula.eval.NotImplementedException;
import org.apache.poi.ss.usermodel.Cell;
/**
@@ -220,6 +221,8 @@ public final class WorkbookEvaluator {
}
tracker.updateCacheResult(result);
+ } catch (NotImplementedException e) {
+ throw addExceptionInfo(e, sheetIndex, rowIndex, columnIndex);
} finally {
tracker.endEvaluate(cce);
}
@@ -236,6 +239,25 @@ public final class WorkbookEvaluator {
}
return cce.getValue();
}
+
+ /**
+ * Adds the current cell reference to the exception for easier debugging.
+ * Would be nice to get the formula text as well, but that seems to require
+ * too much digging around and casting to get the FormulaRenderingWorkbook.
+ */
+ private NotImplementedException addExceptionInfo(NotImplementedException inner, int sheetIndex, int rowIndex, int columnIndex) {
+
+ try {
+ String sheetName = _workbook.getSheetName(sheetIndex);
+ CellReference cr = new CellReference(sheetName, rowIndex, columnIndex, false, false);
+ String msg = "Error evaluating cell " + cr.formatAsString();
+ return new NotImplementedException(msg, inner);
+ } catch (Exception e) {
+ // avoid bombing out during exception handling
+ e.printStackTrace();
+ return inner; // preserve original exception
+ }
+ }
/**
* Gets the value from a non-formula cell.
* @param cell may be <code>null</code>
diff --git a/src/java/org/apache/poi/ss/formula/eval/NotImplementedException.java b/src/java/org/apache/poi/ss/formula/eval/NotImplementedException.java
new file mode 100644
index 0000000000..84480758ec
--- /dev/null
+++ b/src/java/org/apache/poi/ss/formula/eval/NotImplementedException.java
@@ -0,0 +1,36 @@
+/* ====================================================================
+ 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.eval;
+
+import org.apache.poi.ss.usermodel.FormulaEvaluator;
+
+/**
+ * An exception thrown by implementors of {@link FormulaEvaluator} when attempting to evaluate
+ * a formula which requires features that POI does not (yet) support.
+ *
+ * @author Josh Micich
+ */
+public final class NotImplementedException extends RuntimeException {
+
+ public NotImplementedException(String message) {
+ super(message);
+ }
+ public NotImplementedException(String message, NotImplementedException cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls b/src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls
index fd7a614574..8bd07c2f34 100644
--- a/src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls
+++ b/src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls
Binary files differ
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestExternalFunction.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestExternalFunction.java
index 45e49076c2..ebd0afb552 100755
--- a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestExternalFunction.java
+++ b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestExternalFunction.java
@@ -28,6 +28,7 @@ import org.apache.poi.hssf.usermodel.HSSFName;
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.ss.formula.eval.NotImplementedException;
import org.apache.poi.ss.usermodel.CellValue;
/**
*
@@ -66,11 +67,16 @@ public final class TestExternalFunction extends TestCase {
assertEquals("myFunc()", actualFormula);
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
- CellValue evalResult = fe.evaluate(cell);
-
- // Check the return value from ExternalFunction.evaluate()
+ // Check out what ExternalFunction.evaluate() does:
+ CellValue evalResult;
+ try {
+ evalResult = fe.evaluate(cell);
+ } catch (NotImplementedException e) {
+ assertEquals("Error evaluating cell Sheet1!B1", e.getMessage());
+ assertEquals("myFunc", e.getCause().getMessage());
+ return;
+ }
// TODO - make this test assert something more interesting as soon as ExternalFunction works a bit better
- assertEquals(HSSFCell.CELL_TYPE_ERROR, evalResult.getCellType());
- assertEquals(ErrorEval.FUNCTION_NOT_IMPLEMENTED.getErrorCode(), evalResult.getErrorValue());
+ assertNotNull(evalResult);
}
}
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/NumericFunctionInvoker.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/NumericFunctionInvoker.java
index d477231349..51340af49a 100755
--- a/src/testcases/org/apache/poi/hssf/record/formula/functions/NumericFunctionInvoker.java
+++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/NumericFunctionInvoker.java
@@ -24,6 +24,7 @@ import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.Eval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.OperationEval;
+import org.apache.poi.ss.formula.eval.NotImplementedException;
/**
* Test helper class for invoking functions with numeric results.
@@ -83,12 +84,16 @@ public final class NumericFunctionInvoker {
throws NumericEvalEx {
Eval evalResult;
// TODO - make OperationEval extend Function
- if (target instanceof Function) {
- Function ff = (Function) target;
- evalResult = ff.evaluate(args, srcCellRow, (short)srcCellCol);
- } else {
- OperationEval ff = (OperationEval) target;
- evalResult = ff.evaluate(args, srcCellRow, (short)srcCellCol);
+ try {
+ if (target instanceof Function) {
+ Function ff = (Function) target;
+ evalResult = ff.evaluate(args, srcCellRow, (short)srcCellCol);
+ } else {
+ OperationEval ff = (OperationEval) target;
+ evalResult = ff.evaluate(args, srcCellRow, (short)srcCellCol);
+ }
+ } catch (NotImplementedException e) {
+ throw new NumericEvalEx("Not implemented:" + e.getMessage());
}
if(evalResult == null) {
@@ -108,9 +113,6 @@ public final class NumericFunctionInvoker {
return result.getNumberValue();
}
private static String formatErrorMessage(ErrorEval ee) {
- if(errorCodesAreEqual(ee, ErrorEval.FUNCTION_NOT_IMPLEMENTED)) {
- return "Function not implemented";
- }
if(errorCodesAreEqual(ee, ErrorEval.VALUE_INVALID)) {
return "Error code: #VALUE! (invalid value)";
}