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
This commit is contained in:
Josh Micich 2009-01-22 00:26:28 +00:00
parent c013d9b7c9
commit 59e334e8a5
12 changed files with 233 additions and 168 deletions

View 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);
}
}

View 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 + ")");
}

View File

@ -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,7 +41,6 @@ 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) {
@ -49,17 +49,14 @@ final class ExternalFunction implements FreeRefFunction {
throw new RuntimeException("First argument should be a NameEval, but got ("
+ nameArg.getClass().getName() + ")");
}
} catch (EvaluationException e) {
return e.getErrorEval();
}
int nOutGoingArgs = nIncomingArgs -1;
Eval[] outGoingArgs = new Eval[nOutGoingArgs];
System.arraycopy(args, 1, outGoingArgs, 0, nOutGoingArgs);
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);
}
}

View 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;
@ -35,7 +36,7 @@ public final class FuncVarEval extends FunctionEval {
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
Function f = getFunction();
if (f == null) {
return ErrorEval.FUNCTION_NOT_IMPLEMENTED;
throw new NotImplementedException("FuncIx=" + getFunctionIndex());
}
return f.evaluate(operands, srcRow, srcCol);
}

View 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;

View File

@ -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");
}
}

View 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 {
private final String _functionName;
protected NotImplementedFunction() {
_functionName = getClass().getName();
}
public NotImplementedFunction(String name) {
_functionName = name;
}
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
return ErrorEval.FUNCTION_NOT_IMPLEMENTED;
throw new NotImplementedException(_functionName);
}
}

View 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>

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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,6 +84,7 @@ public final class NumericFunctionInvoker {
throws NumericEvalEx {
Eval evalResult;
// TODO - make OperationEval extend Function
try {
if (target instanceof Function) {
Function ff = (Function) target;
evalResult = ff.evaluate(args, srcCellRow, (short)srcCellCol);
@ -90,6 +92,9 @@ public final class NumericFunctionInvoker {
OperationEval ff = (OperationEval) target;
evalResult = ff.evaluate(args, srcCellRow, (short)srcCellCol);
}
} catch (NotImplementedException e) {
throw new NumericEvalEx("Not implemented:" + e.getMessage());
}
if(evalResult == null) {
throw new NumericEvalEx("Result object was 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)";
}