updated remaining evaluator functions to implement fixed args interfaces
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@883197 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
24717007c8
commit
1f22e9c945
@ -52,8 +52,8 @@ public final class FunctionEval {
|
||||
|
||||
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;
|
||||
@ -69,7 +69,7 @@ public final class FunctionEval {
|
||||
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;
|
||||
@ -84,11 +84,11 @@ public final class FunctionEval {
|
||||
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;
|
||||
@ -96,7 +96,7 @@ public final class FunctionEval {
|
||||
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();
|
||||
@ -108,6 +108,7 @@ public final class FunctionEval {
|
||||
|
||||
retval[76] = new Rows();
|
||||
retval[77] = new Columns();
|
||||
retval[82] = TextFunction.SEARCH;
|
||||
retval[ID.OFFSET] = new Offset();
|
||||
retval[82] = TextFunction.SEARCH;
|
||||
|
||||
@ -118,7 +119,7 @@ public final class FunctionEval {
|
||||
retval[101] = new Hlookup();
|
||||
retval[102] = new Vlookup();
|
||||
|
||||
retval[105] = new Isref();
|
||||
retval[105] = LogicalFunction.ISREF;
|
||||
|
||||
retval[109] = NumericFunction.LOG;
|
||||
|
||||
@ -134,9 +135,9 @@ public final class FunctionEval {
|
||||
|
||||
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
|
||||
@ -146,9 +147,9 @@ public final class FunctionEval {
|
||||
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;
|
||||
|
@ -19,13 +19,67 @@ 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.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);
|
||||
}
|
||||
@ -48,17 +102,7 @@ public abstract class AggregateFunction extends MultiOperandNumericFunction {
|
||||
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;
|
||||
@ -79,17 +123,7 @@ public abstract class AggregateFunction extends MultiOperandNumericFunction {
|
||||
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) {
|
||||
|
@ -1,32 +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;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public final class And extends BooleanFunction {
|
||||
|
||||
protected boolean getInitialResultValue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean partialEvaluate(boolean cumulativeResult, boolean currentValue) {
|
||||
return cumulativeResult && currentValue;
|
||||
}
|
||||
}
|
@ -101,4 +101,46 @@ public abstract class BooleanFunction implements Function {
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -17,17 +17,58 @@
|
||||
|
||||
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 {
|
||||
|
@ -18,7 +18,7 @@
|
||||
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;
|
||||
@ -39,27 +39,24 @@ import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector;
|
||||
*
|
||||
* @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) {
|
||||
@ -67,7 +64,6 @@ public final class Hlookup implements Function {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns one column from an <tt>AreaEval</tt>
|
||||
*
|
||||
|
@ -17,9 +17,6 @@
|
||||
|
||||
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;
|
||||
|
||||
@ -36,21 +33,17 @@ 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;
|
||||
}
|
||||
}
|
||||
|
@ -44,56 +44,71 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
*
|
||||
* @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() + ")");
|
||||
}
|
||||
AreaEval reference = (AreaEval) firstArg;
|
||||
|
||||
int rowIx = 0;
|
||||
int columnIx = 0;
|
||||
boolean colArgWasPassed = false;
|
||||
int columnIx = 0;
|
||||
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 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) {
|
||||
AreaEval reference = convertFirstArg(arg0);
|
||||
|
||||
boolean colArgWasPassed = true;
|
||||
try {
|
||||
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
|
||||
|
@ -1,42 +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.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;
|
||||
}
|
||||
}
|
@ -1,56 +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.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;
|
||||
}
|
||||
}
|
@ -1,47 +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.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);
|
||||
}
|
||||
}
|
@ -1,42 +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.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;
|
||||
}
|
||||
}
|
@ -17,6 +17,8 @@
|
||||
|
||||
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;
|
||||
@ -28,30 +30,14 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* @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:
|
||||
@ -61,32 +47,73 @@ public abstract class LogicalFunction implements Function {
|
||||
// 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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -379,17 +379,10 @@ final class LookupUtils {
|
||||
|
||||
/**
|
||||
* 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:
|
||||
|
@ -1,50 +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.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);
|
||||
}
|
||||
}
|
@ -17,7 +17,10 @@
|
||||
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.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
|
||||
@ -25,23 +28,80 @@ import org.apache.poi.hssf.record.formula.eval.EvaluationException;
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public abstract class NumericFunction implements Function {
|
||||
|
||||
@ -32,8 +33,8 @@ 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;
|
||||
@ -64,10 +65,21 @@ public abstract class NumericFunction implements Function {
|
||||
/* -------------------------------------------------------------------------- */
|
||||
// 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);
|
||||
@ -78,40 +90,26 @@ public abstract class NumericFunction implements Function {
|
||||
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);
|
||||
|
||||
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();
|
||||
}
|
||||
double[] ds = new double[nArgs];
|
||||
for(int i=0; i<nArgs; i++) {
|
||||
ds[i] = singleOperandEvaluate(args[i], srcCellRow, srcCellCol);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -166,9 +164,34 @@ public abstract class NumericFunction implements Function {
|
||||
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() {
|
||||
@ -298,18 +321,53 @@ public abstract class NumericFunction implements Function {
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
public static final Function LOG = new MultiArg(1,2) {
|
||||
protected double evaluate(double[] ds) {
|
||||
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();
|
||||
}
|
||||
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 new NumberEval(result);
|
||||
}
|
||||
}
|
||||
|
||||
double logE = Math.log(ds[0]);
|
||||
if (ds.length == 1) {
|
||||
return logE / LOG_10_TO_BASE_e;
|
||||
}
|
||||
double base = ds[1];
|
||||
if (base == Math.E) {
|
||||
return logE;
|
||||
}
|
||||
return logE / Math.log(base);
|
||||
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());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,32 +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;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public final class Or extends BooleanFunction {
|
||||
|
||||
protected boolean getInitialResultValue() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean partialEvaluate(boolean cumulativeResult, boolean currentValue) {
|
||||
return cumulativeResult || currentValue;
|
||||
}
|
||||
}
|
@ -1,44 +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.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;
|
||||
}
|
||||
|
||||
}
|
@ -1,42 +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.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;
|
||||
}
|
||||
|
||||
}
|
@ -27,31 +27,38 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
* 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 {
|
||||
|
||||
protected ValueEval evaluateFunc(ValueEval[] args, int srcCellRow, int srcCellCol)
|
||||
throws EvaluationException {
|
||||
if (args.length < 3 || args.length > 4) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
|
||||
String oldStr = evaluateStringArg(args[0], srcCellRow, srcCellCol);
|
||||
String searchStr = evaluateStringArg(args[1], srcCellRow, srcCellCol);
|
||||
String newStr = evaluateStringArg(args[2], srcCellRow, srcCellCol);
|
||||
public final class Substitute extends Var3or4ArgFunction {
|
||||
|
||||
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
|
||||
ValueEval arg2) {
|
||||
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);
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
|
||||
/**
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public abstract class TextFunction implements Function {
|
||||
|
||||
@ -54,17 +54,18 @@ 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);
|
||||
@ -107,17 +108,20 @@ public abstract class TextFunction implements Function {
|
||||
*
|
||||
* 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!),
|
||||
@ -138,19 +142,25 @@ public abstract class TextFunction implements Function {
|
||||
}
|
||||
};
|
||||
|
||||
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) {
|
||||
@ -165,28 +175,33 @@ public abstract class TextFunction implements Function {
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
@ -17,26 +17,24 @@
|
||||
|
||||
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 >
|
||||
* Convenience base class for any function which must take two or three
|
||||
* arguments
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
@ -17,26 +17,24 @@
|
||||
|
||||
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 >
|
||||
* Convenience base class for any function which must take three or four
|
||||
* arguments
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
@ -18,7 +18,7 @@
|
||||
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;
|
||||
@ -39,27 +39,24 @@ import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector;
|
||||
*
|
||||
* @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) {
|
||||
|
@ -37,7 +37,7 @@ import org.apache.poi.ss.util.CellReference.NameType;
|
||||
* @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;
|
||||
|
Loading…
Reference in New Issue
Block a user