]> source.dussan.org Git - poi.git/commitdiff
Bugzilla 46580 - Replaced ErrorEval.FUNCTION_NOT_IMPLEMENTED with new exception NotIm...
authorJosh Micich <josh@apache.org>
Thu, 22 Jan 2009 00:26:28 +0000 (00:26 +0000)
committerJosh Micich <josh@apache.org>
Thu, 22 Jan 2009 00:26:28 +0000 (00:26 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@736505 13f79535-47bb-0310-9956-ffa450edef68

12 files changed:
src/java/org/apache/poi/hssf/record/formula/atp/AnalysisToolPak.java
src/java/org/apache/poi/hssf/record/formula/eval/ErrorEval.java
src/java/org/apache/poi/hssf/record/formula/eval/ExternalFunction.java
src/java/org/apache/poi/hssf/record/formula/eval/FuncVarEval.java
src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java
src/java/org/apache/poi/hssf/record/formula/functions/Indirect.java
src/java/org/apache/poi/hssf/record/formula/functions/NotImplementedFunction.java
src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java
src/java/org/apache/poi/ss/formula/eval/NotImplementedException.java [new file with mode: 0644]
src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls
src/testcases/org/apache/poi/hssf/record/formula/eval/TestExternalFunction.java
src/testcases/org/apache/poi/hssf/record/formula/functions/NumericFunctionInvoker.java

index ca9dd7d3e00a5a6896ae8f0bcc09f8c5f8d8f82f..104b7a86d22fef9f2655909f1a9018621f294e50 100644 (file)
@@ -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);
        }
 }
index e8e197d201588769ca68f6006ff4d1f7ec26d9ad..687052566b5b3f0270f44a3827737cfd57c2b955 100644 (file)
@@ -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 + ")");
     }
index 8e8a9799e45052a01249e05d924dd5a85cdec463..d4d6de6a6d6f69d15a9758e6bad6c6839c4a0942 100755 (executable)
@@ -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);
        }
 }
-
index d30c353599a2419aa60aa9f1fcdd1b76b6ce6ad5..76cfe7bb61998e7e18cebe166ba53442578bfb9d 100644 (file)
@@ -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();
+       }
 }
index e68b8ee67dd7b7dd76163ae1fbac5818dc7dceda..2940af686953a8acd719afde452d4c33039097a7 100644 (file)
@@ -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;
index 567f29b2b1bba24323a4a081118bd0cfe8b92a65..acac8488d42436bf84e230153135fab8d6da6f81 100644 (file)
 
 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");
        }
-
 }
index 49ed84fb4697898d101f5f130af1d112f87cf10b..19643abf66af217df65c7be7881298167064a0e4 100644 (file)
@@ -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);
+       }
 }
index f913f924e2edd615638f98f3a6dc38bb437c1be7..cb26cb2470382cf306afc6263b9f1e0513bf1c0f 100644 (file)
@@ -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 (file)
index 0000000..8448075
--- /dev/null
@@ -0,0 +1,36 @@
+/* ====================================================================\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.ss.formula.eval;\r
+\r
+import org.apache.poi.ss.usermodel.FormulaEvaluator;\r
+\r
+/**\r
+ * An exception thrown by implementors of {@link FormulaEvaluator} when attempting to evaluate\r
+ * a formula which requires features that POI does not (yet) support.\r
+ * \r
+ * @author Josh Micich\r
+ */\r
+public final class NotImplementedException extends RuntimeException {\r
+\r
+       public NotImplementedException(String message) {\r
+               super(message);\r
+       }\r
+       public NotImplementedException(String message, NotImplementedException cause) {\r
+               super(message, cause);\r
+       }\r
+}\r
index fd7a614574a42bba5eace7177f8e9ca97d08dd53..8bd07c2f341470ddc8d46941c6606ac02770e61e 100644 (file)
Binary files a/src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls and b/src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls differ
index 45e49076c2dddf1bc439b95821f53458a2a9d5ae..ebd0afb552cff2fd29869e1cb074fcb4082f1f99 100755 (executable)
@@ -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);
        }
 }
index d477231349644c4c31f39a6cd311f0a618721ec8..51340af49a78044c46e1e205098a06ee9d0cea2b 100755 (executable)
@@ -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)";
                }