From 4135c76ee52372ea1a8786e03ea0c38c0b48b590 Mon Sep 17 00:00:00 2001 From: Josh Micich Date: Wed, 10 Sep 2008 22:43:30 +0000 Subject: [PATCH] Refactored finance functions. git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@694050 13f79535-47bb-0310-9956-ffa450edef68 --- .../record/formula/eval/FunctionEval.java | 8 +- .../eval/ValueEvalToNumericXlator.java | 84 +++------ .../formula/functions/AggregateFunction.java | 5 +- .../formula/functions/FinanceFunction.java | 160 ++++++++---------- .../poi/hssf/record/formula/functions/Fv.java | 75 -------- .../hssf/record/formula/functions/Maxa.java | 14 +- .../hssf/record/formula/functions/Mina.java | 16 +- .../hssf/record/formula/functions/Mode.java | 55 +++--- .../MultiOperandNumericFunction.java | 8 +- .../hssf/record/formula/functions/Nper.java | 75 -------- .../hssf/record/formula/functions/Pmt.java | 91 ---------- .../poi/hssf/record/formula/functions/Pv.java | 74 -------- .../poi/hssf/data/FormulaEvalTestData.xls | Bin 155136 -> 156160 bytes .../record/formula/functions/TestPmt.java | 2 +- 14 files changed, 134 insertions(+), 533 deletions(-) delete mode 100644 src/java/org/apache/poi/hssf/record/formula/functions/Fv.java delete mode 100644 src/java/org/apache/poi/hssf/record/formula/functions/Nper.java delete mode 100644 src/java/org/apache/poi/hssf/record/formula/functions/Pmt.java delete mode 100644 src/java/org/apache/poi/hssf/record/formula/functions/Pv.java diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java index e78ab5f8e6..6f14a1e856 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java @@ -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 diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/ValueEvalToNumericXlator.java b/src/java/org/apache/poi/hssf/record/formula/eval/ValueEvalToNumericXlator.java index 46aa0ddf69..37f0b9b4b1 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/ValueEvalToNumericXlator.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/ValueEvalToNumericXlator.java @@ -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; } } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/AggregateFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/AggregateFunction.java index be0b1e44c7..f04e64070b 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/AggregateFunction.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/AggregateFunction.java @@ -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); } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/FinanceFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/FinanceFunction.java index a6956752be..01fcf9ef0b 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/FinanceFunction.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/FinanceFunction.java @@ -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 -package org.apache.poi.hssf.record.formula.functions; + 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. +==================================================================== */ -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; +package org.apache.poi.hssf.record.formula.functions; +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 { + + 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 ; + - 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); - } - + 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); + } + }; } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Fv.java b/src/java/org/apache/poi/hssf/record/formula/functions/Fv.java deleted file mode 100644 index fd0335c388..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Fv.java +++ /dev/null @@ -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; - } - -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Maxa.java b/src/java/org/apache/poi/hssf/record/formula/functions/Maxa.java index 9d7011f049..7ae722889e 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Maxa.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Maxa.java @@ -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; diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Mina.java b/src/java/org/apache/poi/hssf/record/formula/functions/Mina.java index bbc7da8248..b3965eefd4 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Mina.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Mina.java @@ -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; diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Mode.java b/src/java/org/apache/poi/hssf/record/formula/functions/Mode.java index 940b9f40e6..64f017e8e2 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Mode.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Mode.java @@ -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; + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java index 1337e2fe4d..ec65d0f127 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java @@ -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); } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Nper.java b/src/java/org/apache/poi/hssf/record/formula/functions/Nper.java deleted file mode 100644 index 95411edb77..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Nper.java +++ /dev/null @@ -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; - } - -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Pmt.java b/src/java/org/apache/poi/hssf/record/formula/functions/Pmt.java deleted file mode 100644 index 68a8d43dce..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Pmt.java +++ /dev/null @@ -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.

- * - * Syntax:
- * PMT(rate, nper, pv, fv, type)

- * - * Returns the constant repayment amount required for a loan assuming a constant interest rate.

- * - * rate the loan interest rate.
- * nper the number of loan repayments.
- * pv the present value of the future payments (or principle).
- * fv the future value (default zero) surplus cash at the end of the loan lifetime.
- * type whether payments are due at the beginning(1) or end(0 - default) of each payment period.
- * - */ -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); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Pv.java b/src/java/org/apache/poi/hssf/record/formula/functions/Pv.java deleted file mode 100644 index 1d54bee93d..0000000000 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Pv.java +++ /dev/null @@ -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; - } -} diff --git a/src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls b/src/testcases/org/apache/poi/hssf/data/FormulaEvalTestData.xls index ad41de8efc8f5b842a38675d3bf81210b71444d3..acf9c8b166c6232dcf06d900cd4db20613b26621 100644 GIT binary patch delta 3452 zcma)rix}q?dXp6)tZT>I@L^#QERo;)M^?VpKQNp7YUgCqj&i2=iJ{t z=XcNf{l52}Oa1R7>yJdPFO-8B}b7{h5|>(!(^rr$S(l4lY2?K z3Fu!4cunwNI~&oRfF4D_Yve|?e$}50ffILmwsEP6_;OFGg=h!e)6ge*f z%gAlybu#(KzyfN+M+V5!mncYT;}bHDnkZXH9gs&!GquonQPXEjf9+{}mG|1f(+`-0 z1Hj`y0QXJ}Uu)Z#M<4u9LQ7~wm zpme)n!iR#Tdj-EZBshCY(EXf1yU1%-1>LR-TsORz?}**I)u63xKDA6n>^^ouQtnY; z_m#+Kj{|`KXNkl(;*z{k}onv-W87tDJao&EDla7^m7u?0W*4{_0Opf z;RMs!&A@JRld9KWnY`W)H7pPddtKbl^2^KDl=O^3&leEt+>aNH?7a6(x&8gGQiGih zR7(5K?ih%_LiK-)C^$3?4(#Id_!CW?={!@1u330y;MtQKhdf4loFyW8bpKNMd`Zj2tjd^_>EGR>Q9BWn@yG9ZG!H18a+=I)rm1QWN@YdK7NeJMYV}ejZDnwFg_SFQ`DlA z3eW3Gh41qDR4O~)A)z5p`>cgLDh+*F^WX@%+ONc@MKF+>SB7}=>twQ|d3W`a1bv#! z_U)*X`Un=Uqc&m<-+v>-h4ER#_-tW(J;L}Bzw>eDXnhsgmD9I>jg%=xnmP}7H zGhn8*aKnlxd(*nmy3%54+-A{@W~JF_HX65Gbf@*8CDOPBqbH5qFog~DqNUJO%v3Us z)`!OJ8GUK#w0^V!!pAI=jsCPO-;S?kxHL5`EB3AYM()R$(gT8P;JZIgyP}OOb(NMmU8SY2JZGsZzrFP~N4dv1i+a1V zT?5_O?p$|H$mlP374>%Kxu13A4IAikWe;|_l?}`HWlYrK#aBE@b4ny8uL}Nqq&JOS MKG^4y3ZbQ<>Q;)FR{B6DiqpJ2DSQ|3 zGRkWZN;KBDOy@8E%4s}<6hqR2&=mWUA0JrH<+PN=qkS?G;8elISM!WR`YG^r) zbOp5ifzN3v4Rr&aQPm9=6vlD@t$^QYDV-VzG|@A37N6V{4_u{(X_h+>lK|9F8y(>R zbTR-E5FBS+~4+@KaZ zE}64JPtm+KK#~c#MEBG5wm@tOaE{vOh<1F+fxuC^f%fzU0taz6s7hme0KdUN6)mTc z?K!JMfG;dOvG63oms3p3XkIGd;s^Xjm(cv7fW{yAg%;BZ!+?M2Ia&|^WTXLi=`ore z2*eEs8t7g+EQm8Sf-^+d(db|fWF!YdKcSYcA)Eo8tfz&exD*|LTXZqaNe3hpI8O^{ z+GwsjJw^G@NXg*Z(>j{OtPCFm)Y3Yd#H?hEuiRWE}@TUbG8Nekl`>-W&r7ZI+Nj;F$K6zZ_CST=*Bq-|#c%bAUh)Q6d9Ka1OyuBAF=p>bA)%-d$kp2zPh=gaM!glgdAw_K6a zK=MyO)MZBM1}E@OVDmj-+5>+4Q^rmNH#LGvy`aWN@MVDD>tMl-P=O&_klRHt_D#X1 zC_z>)!Er8iV5(sIXu;&kg4&savju{cW-(xHv0%|hf{aq$xI%Dlm7u6nP_kLDW`|&3 zm7t+o;C(_c?u=l-1zx){G+FQbx;svd2$43@L+unI-qO>7dOA!rE&V<%{r)Y)wp{KQ{`|75 zK@qsv`i9F^@q7jk7!(BtR4Ho0P6@UILyv9<=Amb4l{U;c?}wI&w~xci(K9;fr8wyg zbkZB*q?h`l$8`PoC297i&D2Gr(k-tK;Ec=v2X)p-ufa+0yp!I~PI?z#_P8mYKlv4V z)20-QPW1NKJMUtjy{()bb$y1UA7#>As?^}s65_&}ZLzCm(iG(Y)J^v#N?-5zKP#x`;pwSfxG&$dK6yv*SEHc# zkt6yY);*L+OB3VHeTa@MFIF2?TUI-kH>*7>gyqZfWBIeVXA#H>VsY=H1FI{Gdl;Qq z_RkEX;j9Q&XBPK0-e7TWBa+pP^_Fnu-sXw@4NX