retval[0] = new Count();
retval[1] = new If();
- retval[2] = new IsNa();
- retval[3] = new IsError();
+ retval[2] = LogicalFunction.ISNA;
+ retval[3] = LogicalFunction.ISERROR;
retval[ID.SUM] = AggregateFunction.SUM;
retval[5] = AggregateFunction.AVERAGE;
retval[6] = AggregateFunction.MIN;
retval[16] = NumericFunction.COS;
retval[17] = NumericFunction.TAN;
retval[18] = NumericFunction.ATAN;
- retval[19] = new Pi();
+ retval[19] = NumericFunction.PI;
retval[20] = NumericFunction.SQRT;
retval[21] = NumericFunction.EXP;
retval[22] = NumericFunction.LN;
retval[31] = TextFunction.MID;
retval[32] = TextFunction.LEN;
retval[33] = new Value();
- retval[34] = new True();
- retval[35] = new False();
- retval[36] = new And();
- retval[37] = new Or();
- retval[38] = new Not();
+ retval[34] = BooleanFunction.TRUE;
+ retval[35] = BooleanFunction.FALSE;
+ retval[36] = BooleanFunction.AND;
+ retval[37] = BooleanFunction.OR;
+ retval[38] = BooleanFunction.NOT;
retval[39] = NumericFunction.MOD;
retval[56] = FinanceFunction.PV;
retval[58] = FinanceFunction.NPER;
retval[59] = FinanceFunction.PMT;
- retval[63] = new Rand();
+ retval[63] = NumericFunction.RAND;
retval[64] = new Match();
retval[65] = DateFunc.instance;
retval[66] = new Time();
retval[76] = new Rows();
retval[77] = new Columns();
+ retval[82] = TextFunction.SEARCH;
retval[ID.OFFSET] = new Offset();
retval[82] = TextFunction.SEARCH;
retval[101] = new Hlookup();
retval[102] = new Vlookup();
- retval[105] = new Isref();
+ retval[105] = LogicalFunction.ISREF;
retval[109] = NumericFunction.LOG;
retval[124] = TextFunction.FIND;
- retval[127] = LogicalFunction.IsText;
- retval[128] = LogicalFunction.IsNumber;
- retval[129] = new Isblank();
+ retval[127] = LogicalFunction.ISTEXT;
+ retval[128] = LogicalFunction.ISNUMBER;
+ retval[129] = LogicalFunction.ISBLANK;
retval[130] = new T();
retval[ID.INDIRECT] = null; // Indirect.evaluate has different signature
retval[183] = AggregateFunction.PRODUCT;
retval[184] = NumericFunction.FACT;
- retval[190] = LogicalFunction.IsNonText;
+ retval[190] = LogicalFunction.ISNONTEXT;
- retval[198] = LogicalFunction.IsLogical;
+ retval[198] = LogicalFunction.ISLOGICAL;
retval[212] = NumericFunction.ROUNDUP;
retval[213] = NumericFunction.ROUNDDOWN;
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.NumberEval;
+import org.apache.poi.hssf.record.formula.eval.OperandResolver;
+import org.apache.poi.hssf.record.formula.eval.ValueEval;
/**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
- *
*/
public abstract class AggregateFunction extends MultiOperandNumericFunction {
+ private static final class LargeSmall extends Fixed2ArgFunction {
+ private final boolean _isLarge;
+ protected LargeSmall(boolean isLarge) {
+ _isLarge = isLarge;
+ }
+
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0,
+ ValueEval arg1) {
+ double dn;
+ try {
+ ValueEval ve1 = OperandResolver.getSingleValue(arg1, srcRowIndex, srcColumnIndex);
+ dn = OperandResolver.coerceValueToDouble(ve1);
+ } catch (EvaluationException e1) {
+ // all errors in the second arg translate to #VALUE!
+ return ErrorEval.VALUE_INVALID;
+ }
+ // weird Excel behaviour on second arg
+ if (dn < 1.0) {
+ // values between 0.0 and 1.0 result in #NUM!
+ return ErrorEval.NUM_ERROR;
+ }
+ // all other values are rounded up to the next integer
+ int k = (int) Math.ceil(dn);
+
+ double result;
+ try {
+ double[] ds = ValueCollector.collectValues(arg0);
+ if (k > ds.length) {
+ return ErrorEval.NUM_ERROR;
+ }
+ result = _isLarge ? StatsLib.kthLargest(ds, k) : StatsLib.kthSmallest(ds, k);
+ NumericFunction.checkValue(result);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+
+ return new NumberEval(result);
+ }
+ }
+ private static final class ValueCollector extends MultiOperandNumericFunction {
+ private static final ValueCollector instance = new ValueCollector();
+ public ValueCollector() {
+ super(false, false);
+ }
+ public static double[] collectValues(ValueEval...operands) throws EvaluationException {
+ return instance.getNumberArray(operands);
+ }
+ protected double evaluate(double[] values) {
+ throw new IllegalStateException("should not be called");
+ }
+ }
+
protected AggregateFunction() {
super(false, false);
}
return StatsLib.devsq(values);
}
};
- public static final Function LARGE = new AggregateFunction() {
- protected double evaluate(double[] ops) throws EvaluationException {
- if (ops.length < 2) {
- throw new EvaluationException(ErrorEval.NUM_ERROR);
- }
- double[] values = new double[ops.length-1];
- int k = (int) ops[ops.length-1];
- System.arraycopy(ops, 0, values, 0, values.length);
- return StatsLib.kthLargest(values, k);
- }
- };
+ public static final Function LARGE = new LargeSmall(true);
public static final Function MAX = new AggregateFunction() {
protected double evaluate(double[] values) {
return values.length > 0 ? MathX.max(values) : 0;
return MathX.product(values);
}
};
- public static final Function SMALL = new AggregateFunction() {
- protected double evaluate(double[] ops) throws EvaluationException {
- if (ops.length < 2) {
- throw new EvaluationException(ErrorEval.NUM_ERROR);
- }
- double[] values = new double[ops.length-1];
- int k = (int) ops[ops.length-1];
- System.arraycopy(ops, 0, values, 0, values.length);
- return StatsLib.kthSmallest(values, k);
- }
- };
+ public static final Function SMALL = new LargeSmall(false);
public static final Function STDEV = new AggregateFunction() {
protected double evaluate(double[] values) throws EvaluationException {
if (values.length < 1) {
+++ /dev/null
-/* ====================================================================
- 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;
-
-/**
- *
- */
-public final class And extends BooleanFunction {
-
- protected boolean getInitialResultValue() {
- return true;
- }
-
- protected boolean partialEvaluate(boolean cumulativeResult, boolean currentValue) {
- return cumulativeResult && currentValue;
- }
-}
protected abstract boolean getInitialResultValue();
protected abstract boolean partialEvaluate(boolean cumulativeResult, boolean currentValue);
+
+
+ public static final Function AND = new BooleanFunction() {
+ protected boolean getInitialResultValue() {
+ return true;
+ }
+ protected boolean partialEvaluate(boolean cumulativeResult, boolean currentValue) {
+ return cumulativeResult && currentValue;
+ }
+ };
+ public static final Function OR = new BooleanFunction() {
+ protected boolean getInitialResultValue() {
+ return false;
+ }
+ protected boolean partialEvaluate(boolean cumulativeResult, boolean currentValue) {
+ return cumulativeResult || currentValue;
+ }
+ };
+ public static final Function FALSE = new Fixed0ArgFunction() {
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) {
+ return BoolEval.FALSE;
+ }
+ };
+ public static final Function TRUE = new Fixed0ArgFunction() {
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) {
+ return BoolEval.TRUE;
+ }
+ };
+ public static final Function NOT = new Fixed1ArgFunction() {
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
+ boolean boolArgVal;
+ try {
+ ValueEval ve = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
+ Boolean b = OperandResolver.coerceValueToBoolean(ve, false);
+ boolArgVal = b == null ? false : b.booleanValue();
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+
+ return BoolEval.valueOf(!boolArgVal);
+ }
+ };
}
+++ /dev/null
-/* ====================================================================
- 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.ValueEval;
-
-/**
- * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
- *
- */
-public final class False implements Function {
-
- public ValueEval evaluate(ValueEval[] operands, int srcRow, int srcCol) {
- ValueEval retval;
- switch (operands.length) {
- default:
- retval = ErrorEval.VALUE_INVALID;
- break;
- case 0:
- retval = BoolEval.FALSE;
- }
- return retval;
- }
-
-}
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.EvaluationException;
+import org.apache.poi.hssf.record.formula.eval.NumberEval;
+import org.apache.poi.hssf.record.formula.eval.ValueEval;
/**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
- * Super class for all Evals for financial function evaluation.
- *
*/
-public abstract class FinanceFunction extends NumericFunction.MultiArg {
+public abstract class FinanceFunction implements Function3Arg, Function4Arg {
+ private static final ValueEval DEFAULT_ARG3 = NumberEval.ZERO;
+ private static final ValueEval DEFAULT_ARG4 = BoolEval.FALSE;
+
protected FinanceFunction() {
- super (3, 5);
+ // no instance fields
+ }
+
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+ ValueEval arg2) {
+ return evaluate(srcRowIndex, srcColumnIndex, arg0, arg1, arg2, DEFAULT_ARG3);
+ }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+ ValueEval arg2, ValueEval arg3) {
+ return evaluate(srcRowIndex, srcColumnIndex, arg0, arg1, arg2, arg3, DEFAULT_ARG4);
+ }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+ ValueEval arg2, ValueEval arg3, ValueEval arg4) {
+ double result;
+ try {
+ double d0 = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
+ double d1 = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex);
+ double d2 = NumericFunction.singleOperandEvaluate(arg2, srcRowIndex, srcColumnIndex);
+ double d3 = NumericFunction.singleOperandEvaluate(arg3, srcRowIndex, srcColumnIndex);
+ double d4 = NumericFunction.singleOperandEvaluate(arg4, srcRowIndex, srcColumnIndex);
+ result = evaluate(d0, d1, d2, d3, d4 != 0.0);
+ NumericFunction.checkValue(result);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+ return new NumberEval(result);
+ }
+ public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+ switch (args.length) {
+ case 3:
+ return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2], DEFAULT_ARG3, DEFAULT_ARG4);
+ case 4:
+ return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2], args[3], DEFAULT_ARG4);
+ case 5:
+ return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2], args[3], args[4]);
+ }
+ return ErrorEval.VALUE_INVALID;
}
protected double evaluate(double[] ds) throws EvaluationException {
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.ErrorEval;
+import org.apache.poi.hssf.record.formula.eval.BoolEval;
import org.apache.poi.hssf.record.formula.eval.EvaluationException;
import org.apache.poi.hssf.record.formula.eval.OperandResolver;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
*
* @author Josh Micich
*/
-public final class Hlookup implements Function {
+public final class Hlookup extends Var3or4ArgFunction {
+ private static final ValueEval DEFAULT_ARG3 = BoolEval.TRUE;
- public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
- ValueEval arg3 = null;
- switch(args.length) {
- case 4:
- arg3 = args[3]; // important: assumed array element is never null
- case 3:
- break;
- default:
- // wrong number of arguments
- return ErrorEval.VALUE_INVALID;
- }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+ ValueEval arg2) {
+ return evaluate(srcRowIndex, srcColumnIndex, arg0, arg1, arg2, DEFAULT_ARG3);
+ }
+
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+ ValueEval arg2, ValueEval arg3) {
try {
// Evaluation order:
// arg0 lookup_value, arg1 table_array, arg3 range_lookup, find lookup value, arg2 row_index, fetch result
- ValueEval lookupValue = OperandResolver.getSingleValue(args[0], srcCellRow, srcCellCol);
- AreaEval tableArray = LookupUtils.resolveTableArrayArg(args[1]);
- boolean isRangeLookup = LookupUtils.resolveRangeLookupArg(arg3, srcCellRow, srcCellCol);
+ ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
+ AreaEval tableArray = LookupUtils.resolveTableArrayArg(arg1);
+ boolean isRangeLookup = LookupUtils.resolveRangeLookupArg(arg3, srcRowIndex, srcColumnIndex);
int colIndex = LookupUtils.lookupIndexOfValue(lookupValue, LookupUtils.createRowVector(tableArray, 0), isRangeLookup);
- int rowIndex = LookupUtils.resolveRowOrColIndexArg(args[2], srcCellRow, srcCellCol);
+ int rowIndex = LookupUtils.resolveRowOrColIndexArg(arg2, srcRowIndex, srcColumnIndex);
ValueVector resultCol = createResultColumnVector(tableArray, rowIndex);
return resultCol.getItem(colIndex);
} catch (EvaluationException e) {
}
}
-
/**
* Returns one column from an <tt>AreaEval</tt>
*
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.OperandResolver;
import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
* <b>friendly_name</b> (optional) the value to display<p/>
*
* Returns last argument. Leaves type unchanged (does not convert to {@link StringEval}).
-
+ *
* @author Wayne Clingingsmith
*/
-public final class Hyperlink implements Function {
+public final class Hyperlink extends Var1or2ArgFunction {
- public ValueEval evaluate(ValueEval[] operands, int srcRow, int srcCol) {
- int lastArgIx = operands.length - 1;
- if (lastArgIx < 0 || lastArgIx > 1) {
- return ErrorEval.VALUE_INVALID;
- }
-
- try {
- return OperandResolver.getSingleValue(operands[lastArgIx], srcRow, srcCol);
- } catch (EvaluationException e) {
- return e.getErrorEval();
- }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
+ return arg0;
+ }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
+ // note - if last arg is MissingArgEval, result will be NumberEval.ZERO,
+ // but WorkbookEvaluator does that translation
+ return arg1;
}
}
*
* @author Josh Micich
*/
-public final class Index implements Function {
+public final class Index implements Function2Arg, Function3Arg, Function4Arg {
- public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
- int nArgs = args.length;
- if(nArgs < 2) {
- // too few arguments
- return ErrorEval.VALUE_INVALID;
- }
- ValueEval firstArg = args[0];
- if (firstArg instanceof RefEval) {
- // convert to area ref for simpler code in getValueFromArea()
- firstArg = ((RefEval)firstArg).offset(0, 0, 0, 0);
- }
- if(!(firstArg instanceof AreaEval)) {
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
+ AreaEval reference = convertFirstArg(arg0);
- // else the other variation of this function takes an array as the first argument
- // it seems like interface 'ArrayEval' does not even exist yet
- throw new RuntimeException("Incomplete code - cannot handle first arg of type ("
- + firstArg.getClass().getName() + ")");
+ boolean colArgWasPassed = false;
+ int columnIx = 0;
+ try {
+ int rowIx = resolveIndexArg(arg1, srcRowIndex, srcColumnIndex);
+ return getValueFromArea(reference, rowIx, columnIx, colArgWasPassed, srcRowIndex, srcColumnIndex);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
}
- AreaEval reference = (AreaEval) firstArg;
+ }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+ ValueEval arg2) {
+ AreaEval reference = convertFirstArg(arg0);
- int rowIx = 0;
- int columnIx = 0;
- boolean colArgWasPassed = false;
+ boolean colArgWasPassed = true;
try {
- switch(nArgs) {
- case 4:
- throw new RuntimeException("Incomplete code" +
- " - don't know how to support the 'area_num' parameter yet)");
- // Excel expression might look like this "INDEX( (A1:B4, C3:D6, D2:E5 ), 1, 2, 3)
- // In this example, the 3rd area would be used i.e. D2:E5, and the overall result would be E2
- // Token array might be encoded like this: MemAreaPtg, AreaPtg, AreaPtg, UnionPtg, UnionPtg, ParenthesesPtg
- // The formula parser doesn't seem to support this yet. Not sure if the evaluator does either
-
- case 3:
- columnIx = resolveIndexArg(args[2], srcCellRow, srcCellCol);
- colArgWasPassed = true;
- case 2:
- rowIx = resolveIndexArg(args[1], srcCellRow, srcCellCol);
- break;
- default:
- // too many arguments
- return ErrorEval.VALUE_INVALID;
- }
- return getValueFromArea(reference, rowIx, columnIx, colArgWasPassed, srcCellRow, srcCellCol);
+ int columnIx = resolveIndexArg(arg2, srcRowIndex, srcColumnIndex);
+ int rowIx = resolveIndexArg(arg1, srcRowIndex, srcColumnIndex);
+ return getValueFromArea(reference, rowIx, columnIx, colArgWasPassed, srcRowIndex, srcColumnIndex);
} catch (EvaluationException e) {
return e.getErrorEval();
}
}
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+ ValueEval arg2, ValueEval arg3) {
+ throw new RuntimeException("Incomplete code"
+ + " - don't know how to support the 'area_num' parameter yet)");
+ // Excel expression might look like this "INDEX( (A1:B4, C3:D6, D2:E5 ), 1, 2, 3)
+ // In this example, the 3rd area would be used i.e. D2:E5, and the overall result would be E2
+ // Token array might be encoded like this: MemAreaPtg, AreaPtg, AreaPtg, UnionPtg, UnionPtg, ParenthesesPtg
+ // The formula parser doesn't seem to support this yet. Not sure if the evaluator does either
+ }
+
+ private static AreaEval convertFirstArg(ValueEval arg0) {
+ ValueEval firstArg = arg0;
+ if (firstArg instanceof RefEval) {
+ // convert to area ref for simpler code in getValueFromArea()
+ return ((RefEval)firstArg).offset(0, 0, 0, 0);
+ }
+ if((firstArg instanceof AreaEval)) {
+ return (AreaEval) firstArg;
+ }
+ // else the other variation of this function takes an array as the first argument
+ // it seems like interface 'ArrayEval' does not even exist yet
+ throw new RuntimeException("Incomplete code - cannot handle first arg of type ("
+ + firstArg.getClass().getName() + ")");
+
+ }
+
+ public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+ switch (args.length) {
+ case 2:
+ return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1]);
+ case 3:
+ return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2]);
+ case 4:
+ return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2], args[3]);
+ }
+ return ErrorEval.VALUE_INVALID;
+ }
+
/**
* @param colArgWasPassed <code>false</code> if the INDEX argument list had just 2 items
+++ /dev/null
-/* ====================================================================
- 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.EvaluationException;
-import org.apache.poi.hssf.record.formula.eval.OperandResolver;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-
-/**
- * @author Josh Micich
- */
-public final class IsError implements Function {
-
- public ValueEval evaluate(ValueEval[] operands, int srcCellRow, int srcCellCol) {
- if (operands.length != 1) {
- return ErrorEval.VALUE_INVALID;
- }
- try {
- OperandResolver.getSingleValue(operands[0], srcCellRow, srcCellCol);
- } catch (EvaluationException e) {
- return BoolEval.TRUE;
- }
- return BoolEval.FALSE;
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.EvaluationException;
-import org.apache.poi.hssf.record.formula.eval.OperandResolver;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-import org.apache.poi.ss.usermodel.ErrorConstants;
-
-/**
- * Implementation for Excel ISNA() function.<p/>
- *
- * <b>Syntax</b>:<br/>
- * <b>ISNA</b>(<b>value</b>)<p/>
- *
- * <b>value</b> The value to be tested<br/>
- * <br/>
- * Returns <tt>TRUE</tt> if the specified value is '#N/A', <tt>FALSE</tt> otherwise.
- *
- * @author Josh Micich
- */
-public final class IsNa implements Function {
-
- public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
- if(args.length != 1) {
- return ErrorEval.VALUE_INVALID;
- }
- ValueEval arg = args[0];
-
- try {
- OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
- } catch (EvaluationException e) {
- if (e.getErrorEval().getErrorCode() == ErrorConstants.ERROR_NA) {
- return BoolEval.TRUE;
- }
- }
- return BoolEval.FALSE;
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.BlankEval;
-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.EvaluationException;
-import org.apache.poi.hssf.record.formula.eval.OperandResolver;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-
-/**
- * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
- *
- */
-public final class Isblank implements Function {
-
- public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
- if(args.length != 1) {
- return ErrorEval.VALUE_INVALID;
- }
- ValueEval arg = args[0];
-
- ValueEval singleCellValue;
- try {
- singleCellValue = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
- } catch (EvaluationException e) {
- return BoolEval.FALSE;
- }
- return BoolEval.valueOf(singleCellValue instanceof BlankEval);
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.RefEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-
-/**
- * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
- */
-public final class Isref implements Function {
- public ValueEval evaluate(ValueEval[] operands, int srcCellRow, int srcCellCol) {
- if (operands.length != 1) {
- return ErrorEval.VALUE_INVALID;
- }
-
- ValueEval eval = operands[0];
- if (eval instanceof RefEval || eval instanceof AreaEval) {
- return BoolEval.TRUE;
- }
-
- return BoolEval.FALSE;
- }
-}
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.BlankEval;
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.EvaluationException;
/**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
+ * @author Josh Micich
*/
-public abstract class LogicalFunction implements Function {
+public abstract class LogicalFunction extends Fixed1ArgFunction {
- /**
- * recursively evaluate any RefEvals TODO - use {@link OperandResolver}
- */
- private static ValueEval xlateRefEval(RefEval reval) {
- ValueEval retval = reval.getInnerValueEval();
-
- if (retval instanceof RefEval) {
- RefEval re = (RefEval) retval;
- retval = xlateRefEval(re);
- }
-
- return retval;
- }
-
- public final ValueEval evaluate(ValueEval[] operands, int srcCellRow, int srcCellCol) {
- if (operands.length != 1) {
- return ErrorEval.VALUE_INVALID;
- }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
ValueEval ve;
try {
- ve = OperandResolver.getSingleValue(operands[0], srcCellRow, srcCellCol);
+ ve = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
} catch (EvaluationException e) {
if (false) {
// Note - it is more usual to propagate error codes straight to the result like this:
// this will usually cause a 'FALSE' result except for ISNONTEXT()
ve = e.getErrorEval();
}
- if (ve instanceof RefEval) {
- ve = xlateRefEval((RefEval) ve);
- }
return BoolEval.valueOf(evaluate(ve));
}
+ /**
+ * @param arg any {@link ValueEval}, potentially {@link BlankEval} or {@link ErrorEval}.
+ */
protected abstract boolean evaluate(ValueEval arg);
- public static final Function IsLogical = new LogicalFunction() {
+ public static final Function ISLOGICAL = new LogicalFunction() {
protected boolean evaluate(ValueEval arg) {
return arg instanceof BoolEval;
}
};
- public static final Function IsNonText = new LogicalFunction() {
+ public static final Function ISNONTEXT = new LogicalFunction() {
protected boolean evaluate(ValueEval arg) {
return !(arg instanceof StringEval);
}
};
- public static final Function IsNumber = new LogicalFunction() {
+ public static final Function ISNUMBER = new LogicalFunction() {
protected boolean evaluate(ValueEval arg) {
return arg instanceof NumberEval;
}
};
- public static final Function IsText = new LogicalFunction() {
+ public static final Function ISTEXT = new LogicalFunction() {
protected boolean evaluate(ValueEval arg) {
return arg instanceof StringEval;
}
};
+
+ public static final Function ISBLANK = new LogicalFunction() {
+
+ protected boolean evaluate(ValueEval arg) {
+ return arg instanceof BlankEval;
+ }
+ };
+
+ public static final Function ISERROR = new LogicalFunction() {
+
+ protected boolean evaluate(ValueEval arg) {
+ return arg instanceof ErrorEval;
+ }
+ };
+
+ /**
+ * Implementation for Excel ISNA() function.<p/>
+ *
+ * <b>Syntax</b>:<br/>
+ * <b>ISNA</b>(<b>value</b>)<p/>
+ *
+ * <b>value</b> The value to be tested<br/>
+ * <br/>
+ * Returns <tt>TRUE</tt> if the specified value is '#N/A', <tt>FALSE</tt> otherwise.
+ */
+ public static final Function ISNA = new LogicalFunction() {
+
+ protected boolean evaluate(ValueEval arg) {
+ return arg == ErrorEval.NA;
+ }
+ };
+
+ public static final Function ISREF = new Fixed1ArgFunction() {
+
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
+ if (arg0 instanceof RefEval || arg0 instanceof AreaEval) {
+ return BoolEval.TRUE;
+ }
+ return BoolEval.FALSE;
+ }
+ };
}
/**
* Resolves the last (optional) parameter (<b>range_lookup</b>) to the VLOOKUP and HLOOKUP functions.
- * @param rangeLookupArg
- * @param srcCellRow
- * @param srcCellCol
- * @return
- * @throws EvaluationException
+ * @param rangeLookupArg must not be <code>null</code>
*/
public static boolean resolveRangeLookupArg(ValueEval rangeLookupArg, int srcCellRow, int srcCellCol) throws EvaluationException {
- if(rangeLookupArg == null) {
- // range_lookup arg not provided
- return true; // default is TRUE
- }
+
ValueEval valEval = OperandResolver.getSingleValue(rangeLookupArg, srcCellRow, srcCellCol);
if(valEval instanceof BlankEval) {
// Tricky:
+++ /dev/null
-/* ====================================================================
- 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.EvaluationException;
-import org.apache.poi.hssf.record.formula.eval.OperandResolver;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-
-
-/**
- * @author Amol S. Deshmukh < amol at apache dot org >
- * The NOT boolean function. Returns negation of specified value
- * (treated as a boolean). If the specified arg is a number,
- * then it is true <=> 'number is non-zero'
- */
-public final class Not implements Function {
-
- public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
- if (args.length != 1) {
- return ErrorEval.VALUE_INVALID;
- }
- boolean boolArgVal;
- try {
- ValueEval ve = OperandResolver.getSingleValue(args[0], srcCellRow, srcCellCol);
- Boolean b = OperandResolver.coerceValueToBoolean(ve, false);
- boolArgVal = b == null ? false : b.booleanValue();
- } catch (EvaluationException e) {
- return e.getErrorEval();
- }
-
- return BoolEval.valueOf(!boolArgVal);
- }
-}
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.NumberEval;
+import org.apache.poi.hssf.record.formula.eval.ValueEval;
/**
* Calculates the net present value of an investment by using a discount rate
* values). Minimum 2 arguments, first arg is the rate of discount over the
* length of one period others up to 254 arguments representing the payments and
* income.
- *
+ *
* @author SPetrakovsky
*/
-public class Npv extends NumericFunction.MultiArg {
+public final class Npv implements Function2Arg, Function3Arg, Function4Arg {
- public Npv() {
- super(2, 255);
+
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
+ double result;
+ try {
+ double rate = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
+ double d1 = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex);
+ result = evaluate(rate, d1);
+ NumericFunction.checkValue(result);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+ return new NumberEval(result);
+ }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+ ValueEval arg2) {
+ double result;
+ try {
+ double rate = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
+ double d1 = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex);
+ double d2 = NumericFunction.singleOperandEvaluate(arg2, srcRowIndex, srcColumnIndex);
+ result = evaluate(rate, d1, d2);
+ NumericFunction.checkValue(result);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+ return new NumberEval(result);
+ }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+ ValueEval arg2, ValueEval arg3) {
+ double result;
+ try {
+ double rate = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
+ double d1 = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex);
+ double d2 = NumericFunction.singleOperandEvaluate(arg2, srcRowIndex, srcColumnIndex);
+ double d3 = NumericFunction.singleOperandEvaluate(arg3, srcRowIndex, srcColumnIndex);
+ result = evaluate(rate, d1, d2, d3);
+ NumericFunction.checkValue(result);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+ return new NumberEval(result);
}
- @Override
- protected double evaluate(double[] ds) throws EvaluationException {
- double rate = ds[0];
+ public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+ int nArgs = args.length;
+ if (nArgs<2) {
+ return ErrorEval.VALUE_INVALID;
+ }
+ int np = nArgs-1;
+ double[] ds = new double[np];
+ double result;
+ try {
+ double rate = NumericFunction.singleOperandEvaluate(args[0], srcRowIndex, srcColumnIndex);
+ for (int i = 0; i < ds.length; i++) {
+ ds[i] = NumericFunction.singleOperandEvaluate(args[i+1], srcRowIndex, srcColumnIndex);
+ }
+ result = evaluate(rate, ds);
+ NumericFunction.checkValue(result);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+ return new NumberEval(result);
+ }
+
+ private static double evaluate(double rate, double...ds) {
double sum = 0;
- for (int i = 1; i < ds.length; i++) {
+ for (int i = 0; i < ds.length; i++) {
sum += ds[i] / Math.pow(rate + 1, i);
}
return sum;
}
-
}
/**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
+ * @author Josh Micich
*/
public abstract class NumericFunction implements Function {
static final double TEN = 10.0;
static final double LOG_10_TO_BASE_e = Math.log(TEN);
- protected static final double singleOperandEvaluate(ValueEval arg, int srcCellRow, int srcCellCol) throws EvaluationException {
- ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
+ protected static final double singleOperandEvaluate(ValueEval arg, int srcRowIndex, int srcColumnIndex) throws EvaluationException {
+ ValueEval ve = OperandResolver.getSingleValue(arg, srcRowIndex, srcColumnIndex);
double result = OperandResolver.coerceValueToDouble(ve);
checkValue(result);
return result;
/* -------------------------------------------------------------------------- */
// intermediate sub-classes (one-arg, two-arg and multi-arg)
- public static abstract class OneArg extends NumericFunction {
+ public static abstract class OneArg extends Fixed1ArgFunction {
protected OneArg() {
// no fields to initialise
}
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
+ double result;
+ try {
+ double d = singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
+ result = evaluate(d);
+ checkValue(result);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+ return new NumberEval(result);
+ }
protected final double eval(ValueEval[] args, int srcCellRow, int srcCellCol) throws EvaluationException {
if (args.length != 1) {
throw new EvaluationException(ErrorEval.VALUE_INVALID);
protected abstract double evaluate(double d) throws EvaluationException;
}
- public static abstract class TwoArg extends NumericFunction {
+ public static abstract class TwoArg extends Fixed2ArgFunction {
protected TwoArg() {
// no fields to initialise
}
- protected final double eval(ValueEval[] args, int srcCellRow, int srcCellCol) throws EvaluationException {
- if (args.length != 2) {
- throw new EvaluationException(ErrorEval.VALUE_INVALID);
- }
- double d0 = singleOperandEvaluate(args[0], srcCellRow, srcCellCol);
- double d1 = singleOperandEvaluate(args[1], srcCellRow, srcCellCol);
- return evaluate(d0, d1);
- }
- protected abstract double evaluate(double d0, double d1) throws EvaluationException;
- }
- public static abstract class MultiArg extends NumericFunction {
- private final int _minArgs;
- private final int _maxArgs;
- protected MultiArg(int minArgs, int maxArgs) {
- _minArgs = minArgs;
- _maxArgs = maxArgs;
- }
- protected final double eval(ValueEval[] args, int srcCellRow, int srcCellCol) throws EvaluationException {
- int nArgs = args.length;
- if (nArgs < _minArgs || nArgs > _maxArgs) {
- throw new EvaluationException(ErrorEval.VALUE_INVALID);
- }
- double[] ds = new double[nArgs];
- for(int i=0; i<nArgs; i++) {
- ds[i] = singleOperandEvaluate(args[i], srcCellRow, srcCellCol);
+
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
+ double result;
+ try {
+ double d0 = singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
+ double d1 = singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex);
+ result = evaluate(d0, d1);
+ checkValue(result);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
}
- return evaluate(ds);
+ return new NumberEval(result);
}
- protected abstract double evaluate(double[] ds) throws EvaluationException;
+
+ protected abstract double evaluate(double d0, double d1) throws EvaluationException;
}
/* -------------------------------------------------------------------------- */
return Math.toDegrees(d);
}
};
- public static final Function DOLLAR = new OneArg() {
- protected double evaluate(double d) {
- return d;
+ static final NumberEval DOLLAR_ARG2_DEFAULT = new NumberEval(2.0);
+ public static final Function DOLLAR = new Var1or2ArgFunction() {
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
+ return evaluate(srcRowIndex, srcColumnIndex, arg0, DOLLAR_ARG2_DEFAULT);
+ }
+
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0,
+ ValueEval arg1) {
+ double val;
+ double d1;
+ try {
+ val = singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
+ d1 = singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+ // second arg converts to int by truncating toward zero
+ int nPlaces = (int)d1;
+
+ if (nPlaces > 127) {
+ return ErrorEval.VALUE_INVALID;
+ }
+
+
+ // TODO - DOLLAR() function impl is NQR
+ // result should be StringEval, with leading '$' and thousands separators
+ // current junits are asserting incorrect behaviour
+ return new NumberEval(val);
}
};
public static final Function EXP = new OneArg() {
/* -------------------------------------------------------------------------- */
- public static final Function LOG = new MultiArg(1,2) {
- protected double evaluate(double[] ds) {
-
- double logE = Math.log(ds[0]);
- if (ds.length == 1) {
- return logE / LOG_10_TO_BASE_e;
+ private static final class Log extends Var1or2ArgFunction {
+ public Log() {
+ // no instance fields
+ }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
+ double result;
+ try {
+ double d0 = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
+ result = Math.log(d0) / LOG_10_TO_BASE_e;
+ NumericFunction.checkValue(result);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
}
- double base = ds[1];
- if (base == Math.E) {
- return logE;
+ return new NumberEval(result);
+ }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0,
+ ValueEval arg1) {
+ double result;
+ try {
+ double d0 = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
+ double d1 = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex);
+ double logE = Math.log(d0);
+ double base = d1;
+ if (base == Math.E) {
+ result = logE;
+ } else {
+ result = logE / Math.log(base);
+ }
+ NumericFunction.checkValue(result);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
}
- return logE / Math.log(base);
+ return new NumberEval(result);
+ }
+ }
+
+ public static final Function LOG = new Log();
+
+ static final NumberEval PI_EVAL = new NumberEval(Math.PI);
+ public static final Function PI = new Fixed0ArgFunction() {
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) {
+ return PI_EVAL;
+ }
+ };
+ public static final Function RAND = new Fixed0ArgFunction() {
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) {
+ return new NumberEval(Math.random());
}
};
}
+++ /dev/null
-/* ====================================================================
- 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;
-
-/**
- *
- */
-public final class Or extends BooleanFunction {
-
- protected boolean getInitialResultValue() {
- return false;
- }
-
- protected boolean partialEvaluate(boolean cumulativeResult, boolean currentValue) {
- return cumulativeResult || currentValue;
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-
-/**
- * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
- *
- */
-public final class Pi implements Function {
-
- private static final NumberEval PI_EVAL = new NumberEval(Math.PI);
-
- public ValueEval evaluate(ValueEval[] operands, int srcRow, int srcCol) {
- ValueEval retval;
- switch (operands.length) {
- default:
- retval = ErrorEval.VALUE_INVALID;
- break;
- case 0:
- retval = PI_EVAL;
- }
- return retval;
- }
-
-}
+++ /dev/null
-/* ====================================================================
- 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.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-
-/**
- * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
- *
- */
-public final class Rand implements Function {
-
- public ValueEval evaluate(ValueEval[] operands, int srcRow, int srcCol) {
- ValueEval retval;
- switch (operands.length) {
- default:
- retval = ErrorEval.VALUE_INVALID;
- break;
- case 0:
- retval = new NumberEval(Math.random());
- }
- return retval;
- }
-
-}
* Substitutes text in a text string with new text, some number of times.
* @author Manda Wilson < wilson at c bio dot msk cc dot org >
*/
-public final class Substitute extends TextFunction {
+public final class Substitute extends Var3or4ArgFunction {
- protected ValueEval evaluateFunc(ValueEval[] args, int srcCellRow, int srcCellCol)
- throws EvaluationException {
- if (args.length < 3 || args.length > 4) {
- return ErrorEval.VALUE_INVALID;
- }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+ ValueEval arg2) {
+ String result;
+ try {
+ String oldStr = TextFunction.evaluateStringArg(arg0, srcRowIndex, srcColumnIndex);
+ String searchStr = TextFunction.evaluateStringArg(arg1, srcRowIndex, srcColumnIndex);
+ String newStr = TextFunction.evaluateStringArg(arg2, srcRowIndex, srcColumnIndex);
- String oldStr = evaluateStringArg(args[0], srcCellRow, srcCellCol);
- String searchStr = evaluateStringArg(args[1], srcCellRow, srcCellCol);
- String newStr = evaluateStringArg(args[2], srcCellRow, srcCellCol);
+ result = replaceAllOccurrences(oldStr, searchStr, newStr);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+ return new StringEval(result);
+ }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+ ValueEval arg2, ValueEval arg3) {
String result;
- switch (args.length) {
- default:
- throw new IllegalStateException("Cannot happen");
- case 4:
- int instanceNumber = evaluateIntArg(args[3], srcCellRow, srcCellCol);
- if (instanceNumber < 1) {
- return ErrorEval.VALUE_INVALID;
- }
- result = replaceOneOccurrence(oldStr, searchStr, newStr, instanceNumber);
- break;
- case 3:
- result = replaceAllOccurrences(oldStr, searchStr, newStr);
+ try {
+ String oldStr = TextFunction.evaluateStringArg(arg0, srcRowIndex, srcColumnIndex);
+ String searchStr = TextFunction.evaluateStringArg(arg1, srcRowIndex, srcColumnIndex);
+ String newStr = TextFunction.evaluateStringArg(arg2, srcRowIndex, srcColumnIndex);
+
+ int instanceNumber = TextFunction.evaluateIntArg(arg3, srcRowIndex, srcColumnIndex);
+ if (instanceNumber < 1) {
+ return ErrorEval.VALUE_INVALID;
+ }
+ result = replaceOneOccurrence(oldStr, searchStr, newStr, instanceNumber);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
}
return new StringEval(result);
}
/**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
- *
+ * @author Josh Micich
*/
public abstract class TextFunction implements Function {
/* ---------------------------------------------------------------------- */
- private static abstract class SingleArgTextFunc extends TextFunction {
+ private static abstract class SingleArgTextFunc extends Fixed1ArgFunction {
protected SingleArgTextFunc() {
// no fields to initialise
}
- protected ValueEval evaluateFunc(ValueEval[] args, int srcCellRow, int srcCellCol)
- throws EvaluationException {
- if (args.length != 1) {
- return ErrorEval.VALUE_INVALID;
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
+ String arg;
+ try {
+ arg = evaluateStringArg(arg0, srcRowIndex, srcColumnIndex);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
}
- String arg = evaluateStringArg(args[0], srcCellRow, srcCellCol);
return evaluate(arg);
}
protected abstract ValueEval evaluate(String arg);
*
* Author: Manda Wilson < wilson at c bio dot msk cc dot org >
*/
- public static final Function MID = new TextFunction() {
+ public static final Function MID = new Fixed3ArgFunction() {
- protected ValueEval evaluateFunc(ValueEval[] args, int srcCellRow, int srcCellCol)
- throws EvaluationException {
- if (args.length != 3) {
- return ErrorEval.VALUE_INVALID;
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0,
+ ValueEval arg1, ValueEval arg2) {
+ String text;
+ int startCharNum;
+ int numChars;
+ try {
+ text = evaluateStringArg(arg0, srcRowIndex, srcColumnIndex);
+ startCharNum = evaluateIntArg(arg1, srcRowIndex, srcColumnIndex);
+ numChars = evaluateIntArg(arg2, srcRowIndex, srcColumnIndex);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
}
-
- String text = evaluateStringArg(args[0], srcCellRow, srcCellCol);
- int startCharNum = evaluateIntArg(args[1], srcCellRow, srcCellCol);
- int numChars = evaluateIntArg(args[2], srcCellRow, srcCellCol);
int startIx = startCharNum - 1; // convert to zero-based
// Note - for start_num arg, blank/zero causes error(#VALUE!),
}
};
- private static final class LeftRight extends TextFunction {
-
+ private static final class LeftRight extends Var1or2ArgFunction {
+ private static final ValueEval DEFAULT_ARG1 = new NumberEval(1.0);
private final boolean _isLeft;
protected LeftRight(boolean isLeft) {
_isLeft = isLeft;
}
- protected ValueEval evaluateFunc(ValueEval[] args, int srcCellRow, int srcCellCol)
- throws EvaluationException {
- if (args.length != 2) {
- return ErrorEval.VALUE_INVALID;
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
+ return evaluate(srcRowIndex, srcColumnIndex, arg0, DEFAULT_ARG1);
+ }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0,
+ ValueEval arg1) {
+ String arg;
+ int index;
+ try {
+ arg = evaluateStringArg(arg0, srcRowIndex, srcColumnIndex);
+ index = evaluateIntArg(arg1, srcRowIndex, srcColumnIndex);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
}
- String arg = evaluateStringArg(args[0], srcCellRow, srcCellCol);
- int index = evaluateIntArg(args[1], srcCellRow, srcCellCol);
String result;
if (_isLeft) {
public static final Function LEFT = new LeftRight(true);
public static final Function RIGHT = new LeftRight(false);
- public static final Function CONCATENATE = new TextFunction() {
+ public static final Function CONCATENATE = new Function() {
- protected ValueEval evaluateFunc(ValueEval[] args, int srcCellRow, int srcCellCol)
- throws EvaluationException {
- StringBuffer sb = new StringBuffer();
+ public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+ StringBuilder sb = new StringBuilder();
for (int i=0, iSize=args.length; i<iSize; i++) {
- sb.append(evaluateStringArg(args[i], srcCellRow, srcCellCol));
+ try {
+ sb.append(evaluateStringArg(args[i], srcRowIndex, srcColumnIndex));
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
}
return new StringEval(sb.toString());
}
};
- public static final Function EXACT = new TextFunction() {
+ public static final Function EXACT = new Fixed2ArgFunction() {
- protected ValueEval evaluateFunc(ValueEval[] args, int srcCellRow, int srcCellCol)
- throws EvaluationException {
- if (args.length != 2) {
- return ErrorEval.VALUE_INVALID;
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0,
+ ValueEval arg1) {
+ String s0;
+ String s1;
+ try {
+ s0 = evaluateStringArg(arg0, srcRowIndex, srcColumnIndex);
+ s1 = evaluateStringArg(arg1, srcRowIndex, srcColumnIndex);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
}
-
- String s0 = evaluateStringArg(args[0], srcCellRow, srcCellCol);
- String s1 = evaluateStringArg(args[1], srcCellRow, srcCellCol);
return BoolEval.valueOf(s0.equals(s1));
}
};
+++ /dev/null
-/* ====================================================================
- 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.ValueEval;
-
-/**
- * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
- *
- */
-public final class True implements Function {
-
- public ValueEval evaluate(ValueEval[] operands, int srcRow, int srcCol) {
- ValueEval retval;
- switch (operands.length) {
- default:
- retval = ErrorEval.VALUE_INVALID;
- break;
- case 0:
- retval = BoolEval.TRUE;
- }
- return retval;
- }
-
-}
--- /dev/null
+/* ====================================================================
+ 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.ValueEval;
+
+/**
+ * Convenience base class for any function which must take two or three
+ * arguments
+ *
+ * @author Josh Micich
+ */
+abstract class Var1or2ArgFunction implements Function1Arg, Function2Arg {
+
+ public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+ switch (args.length) {
+ case 1:
+ return evaluate(srcRowIndex, srcColumnIndex, args[0]);
+ case 2:
+ return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1]);
+ }
+ return ErrorEval.VALUE_INVALID;
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.ValueEval;
+
+/**
+ * Convenience base class for any function which must take three or four
+ * arguments
+ *
+ * @author Josh Micich
+ */
+abstract class Var3or4ArgFunction implements Function3Arg, Function4Arg {
+
+ public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+ switch (args.length) {
+ case 3:
+ return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2]);
+ case 4:
+ return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2], args[3]);
+ }
+ return ErrorEval.VALUE_INVALID;
+ }
+}
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.ErrorEval;
+import org.apache.poi.hssf.record.formula.eval.BoolEval;
import org.apache.poi.hssf.record.formula.eval.EvaluationException;
import org.apache.poi.hssf.record.formula.eval.OperandResolver;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
*
* @author Josh Micich
*/
-public final class Vlookup implements Function {
+public final class Vlookup extends Var3or4ArgFunction {
+ private static final ValueEval DEFAULT_ARG3 = BoolEval.TRUE;
- public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
- ValueEval arg3 = null;
- switch(args.length) {
- case 4:
- arg3 = args[3]; // important: assumed array element is never null
- case 3:
- break;
- default:
- // wrong number of arguments
- return ErrorEval.VALUE_INVALID;
- }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+ ValueEval arg2) {
+ return evaluate(srcRowIndex, srcColumnIndex, arg0, arg1, arg2, DEFAULT_ARG3);
+ }
+
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+ ValueEval arg2, ValueEval arg3) {
try {
// Evaluation order:
// arg0 lookup_value, arg1 table_array, arg3 range_lookup, find lookup value, arg2 col_index, fetch result
- ValueEval lookupValue = OperandResolver.getSingleValue(args[0], srcCellRow, srcCellCol);
- AreaEval tableArray = LookupUtils.resolveTableArrayArg(args[1]);
- boolean isRangeLookup = LookupUtils.resolveRangeLookupArg(arg3, srcCellRow, srcCellCol);
+ ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
+ AreaEval tableArray = LookupUtils.resolveTableArrayArg(arg1);
+ boolean isRangeLookup = LookupUtils.resolveRangeLookupArg(arg3, srcRowIndex, srcColumnIndex);
int rowIndex = LookupUtils.lookupIndexOfValue(lookupValue, LookupUtils.createColumnVector(tableArray, 0), isRangeLookup);
- int colIndex = LookupUtils.resolveRowOrColIndexArg(args[2], srcCellRow, srcCellCol);
+ int colIndex = LookupUtils.resolveRowOrColIndexArg(arg2, srcRowIndex, srcColumnIndex);
ValueVector resultCol = createResultColumnVector(tableArray, colIndex);
return resultCol.getItem(rowIndex);
} catch (EvaluationException e) {
* @author Josh Micich
*/
public final class OperationEvaluationContext {
-
+ public static final FreeRefFunction UDF = UserDefinedFunction.instance;
private final EvaluationWorkbook _workbook;
private final int _sheetIndex;
private final int _rowIndex;