Refactored finance functions.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@694050 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2008-09-10 22:43:30 +00:00
parent 562360b308
commit 4135c76ee5
14 changed files with 134 additions and 533 deletions

View File

@ -129,10 +129,10 @@ public abstract class FunctionEval implements OperationEval {
retval[52] = new Growth(); // GROWTH
retval[53] = new Goto(); // GOTO
retval[54] = new Halt(); // HALT
retval[56] = new Pv(); // PV
retval[57] = new Fv(); // FV
retval[58] = new Nper(); // NPER
retval[59] = new Pmt(); // PMT
retval[56] = FinanceFunction.PV;
retval[57] = FinanceFunction.FV;
retval[58] = FinanceFunction.NPER;
retval[59] = FinanceFunction.PMT;
retval[60] = new Rate(); // RATE
retval[61] = new Mirr(); // MIRR
retval[62] = new Irr(); // IRR

View File

@ -1,23 +1,20 @@
/*
* 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 14, 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.eval;
/**
@ -30,11 +27,7 @@ public final class ValueEvalToNumericXlator {
public static final int BOOL_IS_PARSED = 0x0002;
public static final int BLANK_IS_PARSED = 0x0004; // => blanks are not ignored, converted to 0
public static final int REF_STRING_IS_PARSED = 0x0008;
public static final int REF_BOOL_IS_PARSED = 0x0010;
public static final int REF_BLANK_IS_PARSED = 0x0020;
public static final int STRING_IS_INVALID_VALUE = 0x0800;
public static final int REF_BOOL_IS_PARSED = 0x0008;
private final int flags;
@ -68,11 +61,11 @@ public final class ValueEvalToNumericXlator {
if (eval instanceof BoolEval) {
return ((flags & BOOL_IS_PARSED) > 0)
? (NumericValueEval) eval
: xlateBlankEval(BLANK_IS_PARSED);
: xlateBlankEval();
}
if (eval instanceof StringEval) {
return xlateStringEval((StringEval) eval); // TODO: recursive call needed
return xlateStringEval((StringEval) eval);
}
if (eval instanceof RefEval) {
@ -84,7 +77,7 @@ public final class ValueEvalToNumericXlator {
}
if (eval instanceof BlankEval) {
return xlateBlankEval(BLANK_IS_PARSED);
return xlateBlankEval();
}
// probably AreaEval? then not acceptable.
@ -97,8 +90,8 @@ public final class ValueEvalToNumericXlator {
* valued numbereval is returned, else BlankEval.INSTANCE
* is returned.
*/
private ValueEval xlateBlankEval(int flag) {
return ((flags & flag) > 0)
private ValueEval xlateBlankEval() {
return ((flags & BLANK_IS_PARSED) > 0)
? (ValueEval) NumberEval.ZERO
: BlankEval.INSTANCE;
}
@ -122,7 +115,8 @@ public final class ValueEvalToNumericXlator {
}
if (eval instanceof StringEval) {
return xlateRefStringEval((StringEval) eval);
// all ref strings are blanks
return BlankEval.INSTANCE;
}
if (eval instanceof ErrorEval) {
@ -130,7 +124,7 @@ public final class ValueEvalToNumericXlator {
}
if (eval instanceof BlankEval) {
return xlateBlankEval(REF_BLANK_IS_PARSED);
return xlateBlankEval();
}
throw new RuntimeException("Invalid ValueEval type passed for conversion: ("
@ -151,29 +145,7 @@ public final class ValueEvalToNumericXlator {
}
return new NumberEval(d.doubleValue());
}
// strings are errors?
if ((flags & STRING_IS_INVALID_VALUE) > 0) {
return ErrorEval.VALUE_INVALID;
}
// ignore strings
return xlateBlankEval(BLANK_IS_PARSED);
}
/**
* uses the relevant flags to decode the StringEval
* @param eval
*/
private ValueEval xlateRefStringEval(StringEval sve) {
if ((flags & REF_STRING_IS_PARSED) > 0) {
String s = sve.getStringValue();
Double d = OperandResolver.parseDouble(s);
if(d == null) {
return ErrorEval.VALUE_INVALID;
}
return new NumberEval(d.doubleValue());
}
// strings are blanks
return BlankEval.INSTANCE;
// else strings are errors?
return ErrorEval.VALUE_INVALID;
}
}

View File

@ -19,6 +19,7 @@ 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.EvaluationException;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/**
@ -32,8 +33,8 @@ public abstract class AggregateFunction extends MultiOperandNumericFunction {
| ValueEvalToNumericXlator.STRING_IS_PARSED
));
protected final ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
protected ValueEval attemptXlateToNumeric(ValueEval ve) {
return DEFAULT_NUM_XLATOR.attemptXlateToNumeric(ve);
}

View File

@ -1,103 +1,77 @@
/*
* 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.
*/
/* ====================================================================
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.AreaEval;
import org.apache.poi.hssf.record.formula.eval.BoolEval;
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.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
import org.apache.poi.hssf.record.formula.eval.EvaluationException;
/**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
* Super class for all Evals for financial function evaluation.
*
*
*/
public abstract class FinanceFunction implements Function {
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (0
| ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
| ValueEvalToNumericXlator.BLANK_IS_PARSED
| ValueEvalToNumericXlator.REF_BLANK_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
));
/**
* this is the default impl of the factory(ish) method getXlator.
* Subclasses can override this method
* if they desire to return a different ValueEvalToNumericXlator instance
* than the default.
*/
protected final ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
protected final ValueEval singleOperandNumericAsBoolean(Eval eval, int srcRow, short srcCol) {
ValueEval retval = null;
retval = singleOperandEvaluate(eval, srcRow, srcCol);
if (retval instanceof NumericValueEval) {
NumericValueEval nve = (NumericValueEval) retval;
retval = (nve.getNumberValue() == 0)
? BoolEval.FALSE
: BoolEval.TRUE;
}
else {
retval = ErrorEval.VALUE_INVALID;
}
return retval;
}
protected final ValueEval singleOperandEvaluate(Eval eval, int srcRow, short srcCol) {
public abstract class FinanceFunction extends NumericFunction.MultiArg {
if (eval instanceof AreaEval) {
AreaEval ae = (AreaEval) eval;
if (ae.contains(srcRow, srcCol)) { // circular ref!
return ErrorEval.CIRCULAR_REF_ERROR;
}
if (ae.isRow()) {
if (ae.isColumn()) {
return ae.getRelativeValue(0, 0);
}
if (ae.containsColumn(srcCol)) {
ValueEval ve = ae.getValueAt(ae.getFirstRow(), srcCol);
ve = getXlator().attemptXlateToNumeric(ve);
return getXlator().attemptXlateToNumeric(ve);
}
return ErrorEval.VALUE_INVALID;
}
if (ae.isColumn()) {
if (ae.containsRow(srcRow)) {
ValueEval ve = ae.getValueAt(srcRow, ae.getFirstColumn());
return getXlator().attemptXlateToNumeric(ve);
}
return ErrorEval.VALUE_INVALID;
}
return ErrorEval.VALUE_INVALID;
}
return getXlator().attemptXlateToNumeric((ValueEval) eval);
}
protected FinanceFunction() {
super (3, 5);
}
protected double evaluate(double[] ds) throws EvaluationException {
// All finance functions have 3 to 5 args, first 4 are numbers, last is boolean
// default for last 2 args are 0.0 and false
// Text boolean literals are not valid for the last arg
double arg3 = 0.0;
double arg4 = 0.0;
switch(ds.length) {
case 5:
arg4 = ds[4];
case 4:
arg3 = ds[3];
case 3:
break;
default:
throw new IllegalStateException("Wrong number of arguments");
}
return evaluate(ds[0], ds[1], ds[2], arg3, arg4!=0.0);
}
protected abstract double evaluate(double rate, double arg1, double arg2, double arg3, boolean type) throws EvaluationException ;
public static final Function FV = new FinanceFunction() {
protected double evaluate(double rate, double arg1, double arg2, double arg3, boolean type) {
return FinanceLib.fv(rate, arg1, arg2, arg3, type);
}
};
public static final Function NPER = new FinanceFunction() {
protected double evaluate(double rate, double arg1, double arg2, double arg3, boolean type) {
return FinanceLib.nper(rate, arg1, arg2, arg3, type);
}
};
public static final Function PMT = new FinanceFunction() {
protected double evaluate(double rate, double arg1, double arg2, double arg3, boolean type) {
return FinanceLib.pmt(rate, arg1, arg2, arg3, type);
}
};
public static final Function PV = new FinanceFunction() {
protected double evaluate(double rate, double arg1, double arg2, double arg3, boolean type) {
return FinanceLib.pv(rate, arg1, arg2, arg3, type);
}
};
}

View File

@ -1,75 +0,0 @@
/*
* 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 15, 2005
*
*/
package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.BoolEval;
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.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
public class Fv extends FinanceFunction {
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double rate = 0, nper = 0, pmt = 0, pv = 0, d = 0;
boolean type = false;
ValueEval retval = null;
ValueEval ve = null;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 5:
ve = singleOperandNumericAsBoolean(operands[4], srcRow, srcCol);
if (ve instanceof ErrorEval) { retval = ErrorEval.VALUE_INVALID; break; }
type = ((BoolEval) ve).getBooleanValue();
case 4:
ve = singleOperandEvaluate(operands[3], srcRow, srcCol);
if (ve instanceof NumericValueEval) pv = ((NumericValueEval) ve).getNumberValue();
else { retval = ErrorEval.VALUE_INVALID; break; }
case 3:
ve = singleOperandEvaluate(operands[1], srcRow, srcCol);
if (ve instanceof NumericValueEval) nper = ((NumericValueEval) ve).getNumberValue();
else { retval = ErrorEval.VALUE_INVALID; break; }
ve = singleOperandEvaluate(operands[2], srcRow, srcCol);
if (ve instanceof NumericValueEval) pmt = ((NumericValueEval) ve).getNumberValue();
else { retval = ErrorEval.VALUE_INVALID; break; }
ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
if (ve instanceof NumericValueEval) rate = ((NumericValueEval) ve).getNumberValue();
else { retval = ErrorEval.VALUE_INVALID; break; }
}
if (retval == null) {
d = FinanceLib.fv(rate, nper, pmt, pv, type);
retval = (Double.isNaN(d))
? (ValueEval) ErrorEval.VALUE_INVALID
: (Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
}

View File

@ -17,6 +17,7 @@
package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/**
@ -29,19 +30,12 @@ public final class Maxa extends MultiOperandNumericFunction {
ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
| ValueEvalToNumericXlator.BLANK_IS_PARSED
| ValueEvalToNumericXlator.REF_BLANK_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
protected ValueEval attemptXlateToNumeric(ValueEval ve) {
return DEFAULT_NUM_XLATOR.attemptXlateToNumeric(ve);
}
public double evaluate(double[] values) {
return values.length > 0 ? MathX.max(values) : 0;

View File

@ -17,31 +17,25 @@
package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
*
*/
public class Mina extends MultiOperandNumericFunction {
public final class Mina extends MultiOperandNumericFunction {
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (
ValueEvalToNumericXlator.BOOL_IS_PARSED
| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
| ValueEvalToNumericXlator.REF_BLANK_IS_PARSED
| ValueEvalToNumericXlator.BLANK_IS_PARSED
));
protected ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
protected ValueEval attemptXlateToNumeric(ValueEval ve) {
return DEFAULT_NUM_XLATOR.attemptXlateToNumeric(ve);
}
public double evaluate(double[] values) {
return values.length > 0 ? MathX.min(values) : 0;

View File

@ -19,6 +19,7 @@ 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.EvaluationException;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/**
@ -26,39 +27,25 @@ import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
*
*/
public class Mode extends MultiOperandNumericFunction {
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator((short) (0
//| ValueEvalToNumericXlator.BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.STRING_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
//| ValueEvalToNumericXlator.STRING_TO_BOOL_IS_PARSED
//| ValueEvalToNumericXlator.REF_STRING_TO_BOOL_IS_PARSED
| ValueEvalToNumericXlator.STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.REF_STRING_IS_INVALID_VALUE
//| ValueEvalToNumericXlator.EVALUATED_REF_BLANK_IS_PARSED
//| ValueEvalToNumericXlator.REF_BLANK_IS_PARSED
//| ValueEvalToNumericXlator.BLANK_IS_PARSED
));
/**
* this is the default impl for the factory method getXlator
* of the super class NumericFunction. Subclasses can override this method
* if they desire to return a different ValueEvalToNumericXlator instance
* than the default.
*/
protected ValueEvalToNumericXlator getXlator() {
return DEFAULT_NUM_XLATOR;
}
private static final ValueEvalToNumericXlator DEFAULT_NUM_XLATOR =
new ValueEvalToNumericXlator(0);
protected double evaluate(double[] values) throws EvaluationException {
double d = StatsLib.mode(values);
if (Double.isNaN(d)) {
// TODO - StatsLib is returning NaN to denote 'no duplicate values'
throw new EvaluationException(ErrorEval.NA);
}
return d;
}
/**
* this is the default impl for the factory method getXlator
* of the super class NumericFunction. Subclasses can override this method
* if they desire to return a different ValueEvalToNumericXlator instance
* than the default.
*/
protected ValueEval attemptXlateToNumeric(ValueEval ve) {
return DEFAULT_NUM_XLATOR.attemptXlateToNumeric(ve);
}
protected double evaluate(double[] values) throws EvaluationException {
double d = StatsLib.mode(values);
if (Double.isNaN(d)) {
// TODO - StatsLib is returning NaN to denote 'no duplicate values'
throw new EvaluationException(ErrorEval.NA);
}
return d;
}
}

View File

@ -27,7 +27,6 @@ import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.Ref2DEval;
import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEvalToNumericXlator;
/**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
@ -74,9 +73,6 @@ public abstract class MultiOperandNumericFunction implements Function {
private static final int DEFAULT_MAX_NUM_OPERANDS = 30;
protected abstract ValueEvalToNumericXlator getXlator();
public final Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
double d;
@ -185,7 +181,5 @@ public abstract class MultiOperandNumericFunction implements Function {
}
protected ValueEval attemptXlateToNumeric(ValueEval ve) {
return getXlator().attemptXlateToNumeric(ve);
}
protected abstract ValueEval attemptXlateToNumeric(ValueEval ve);
}

View File

@ -1,75 +0,0 @@
/*
* 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 15, 2005
*
*/
package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.BoolEval;
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.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
public class Nper extends FinanceFunction {
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double rate = 0, fv = 0, pmt = 0, pv = 0, d = 0;
boolean type = false;
ValueEval retval = null;
ValueEval ve = null;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 5:
ve = singleOperandNumericAsBoolean(operands[4], srcRow, srcCol);
if (ve instanceof ErrorEval) { retval = ErrorEval.VALUE_INVALID; break; }
type = ((BoolEval) ve).getBooleanValue();
case 4:
ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
if (ve instanceof NumericValueEval) rate = ((NumericValueEval) ve).getNumberValue();
else { retval = ErrorEval.VALUE_INVALID; break; }
ve = singleOperandEvaluate(operands[1], srcRow, srcCol);
if (ve instanceof NumericValueEval) pmt = ((NumericValueEval) ve).getNumberValue();
else { retval = ErrorEval.VALUE_INVALID; break; }
ve = singleOperandEvaluate(operands[2], srcRow, srcCol);
if (ve instanceof NumericValueEval) pv = ((NumericValueEval) ve).getNumberValue();
else { retval = ErrorEval.VALUE_INVALID; break; }
ve = singleOperandEvaluate(operands[3], srcRow, srcCol);
if (ve instanceof NumericValueEval) fv = ((NumericValueEval) ve).getNumberValue();
else { retval = ErrorEval.VALUE_INVALID; break; }
}
if (retval == null) {
d = FinanceLib.nper(rate, pmt, pv, fv, type);
retval = (Double.isNaN(d))
? (ValueEval) ErrorEval.VALUE_INVALID
: (Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
}

View File

@ -1,91 +0,0 @@
/*
* 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.BoolEval;
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.EvaluationException;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/**
* Implementation for the PMT() Excel function.<p/>
*
* <b>Syntax:</b><br/>
* <b>PMT</b>(<b>rate</b>, <b>nper</b>, <b>pv</b>, fv, type)<p/>
*
* Returns the constant repayment amount required for a loan assuming a constant interest rate.<p/>
*
* <b>rate</b> the loan interest rate.<br/>
* <b>nper</b> the number of loan repayments.<br/>
* <b>pv</b> the present value of the future payments (or principle).<br/>
* <b>fv</b> the future value (default zero) surplus cash at the end of the loan lifetime.<br/>
* <b>type</b> whether payments are due at the beginning(1) or end(0 - default) of each payment period.<br/>
*
*/
public final class Pmt extends FinanceFunction {
public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
if(args.length < 3 || args.length > 5) {
return ErrorEval.VALUE_INVALID;
}
try {
// evaluate first three (always present) args
double rate = evalArg(args[0], srcRow, srcCol);
double nper = evalArg(args[1], srcRow, srcCol);
double pv = evalArg(args[2], srcRow, srcCol);
double fv = 0;
boolean arePaymentsAtPeriodBeginning = false;
switch (args.length) {
case 5:
ValueEval ve = singleOperandNumericAsBoolean(args[4], srcRow, srcCol);
if (ve instanceof ErrorEval) {
return ve;
}
arePaymentsAtPeriodBeginning = ((BoolEval) ve).getBooleanValue();
case 4:
fv = evalArg(args[3], srcRow, srcCol);
}
double d = FinanceLib.pmt(rate, nper, pv, fv, arePaymentsAtPeriodBeginning);
if (Double.isNaN(d)) {
return ErrorEval.VALUE_INVALID;
}
if (Double.isInfinite(d)) {
return ErrorEval.NUM_ERROR;
}
return new NumberEval(d);
} catch (EvaluationException e) {
return e.getErrorEval();
}
}
private double evalArg(Eval arg, int srcRow, short srcCol) throws EvaluationException {
ValueEval ve = singleOperandEvaluate(arg, srcRow, srcCol);
if(ve instanceof ErrorEval) {
throw new EvaluationException((ErrorEval) ve);
}
if (ve instanceof NumericValueEval) {
return ((NumericValueEval) ve).getNumberValue();
}
throw new EvaluationException(ErrorEval.VALUE_INVALID);
}
}

View File

@ -1,74 +0,0 @@
/*
* 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 15, 2005
*
*/
package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.BoolEval;
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.NumberEval;
import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
public class Pv extends FinanceFunction {
public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
double rate = 0, fv = 0, nper = 0, pmt = 0, d = 0;
boolean type = false;
ValueEval retval = null;
ValueEval ve = null;
switch (operands.length) {
default:
retval = ErrorEval.VALUE_INVALID;
break;
case 5:
ve = singleOperandNumericAsBoolean(operands[4], srcRow, srcCol);
if (ve instanceof ErrorEval) { retval = ErrorEval.VALUE_INVALID; break; }
type = ((BoolEval) ve).getBooleanValue();
case 4:
ve = singleOperandEvaluate(operands[3], srcRow, srcCol);
if (ve instanceof NumericValueEval) fv = ((NumericValueEval) ve).getNumberValue();
else { retval = ErrorEval.VALUE_INVALID; break; }
case 3:
ve = singleOperandEvaluate(operands[1], srcRow, srcCol);
if (ve instanceof NumericValueEval) nper = ((NumericValueEval) ve).getNumberValue();
else { retval = ErrorEval.VALUE_INVALID; break; }
ve = singleOperandEvaluate(operands[2], srcRow, srcCol);
if (ve instanceof NumericValueEval) pmt = ((NumericValueEval) ve).getNumberValue();
else { retval = ErrorEval.VALUE_INVALID; break; }
ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
if (ve instanceof NumericValueEval) rate = ((NumericValueEval) ve).getNumberValue();
else { retval = ErrorEval.VALUE_INVALID; break; }
}
if (retval == null) {
d = FinanceLib.pv(rate, nper, pmt, fv, type);
retval = (Double.isNaN(d))
? (ValueEval) ErrorEval.VALUE_INVALID
: (Double.isInfinite(d))
? (ValueEval) ErrorEval.NUM_ERROR
: new NumberEval(d);
}
return retval;
}
}

View File

@ -36,7 +36,7 @@ public final class TestPmt extends TestCase {
assertEquals(expected, ne.getNumberValue(), 0.00005);
}
private static Eval invoke(Eval[] args) {
return new Pmt().evaluate(args, -1, (short)-1);
return FinanceFunction.PMT.evaluate(args, -1, (short)-1);
}
/**
* Invocation when not expecting an error result