package org.apache.poi.hssf.record.formula.eval;
+import org.apache.poi.hssf.record.formula.functions.Fixed2ArgFunction;
import org.apache.poi.hssf.record.formula.functions.Function;
/**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
*/
-public final class ConcatEval implements Function {
+public final class ConcatEval extends Fixed2ArgFunction {
public static final Function instance = new ConcatEval();
// enforce singleton
}
- public ValueEval evaluate(ValueEval[] args, int srcRow, int srcCol) {
- if(args.length != 2) {
- return ErrorEval.VALUE_INVALID;
- }
- StringBuffer sb = new StringBuffer();
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
+ ValueEval ve0;
+ ValueEval ve1;
try {
- for (int i = 0; i < 2; i++) {
-
- ValueEval ve = OperandResolver.getSingleValue(args[i], srcRow, srcCol);
- if (ve instanceof StringValueEval) {
- StringValueEval sve = (StringValueEval) ve;
- sb.append(sve.getStringValue());
- } else if (ve == BlankEval.INSTANCE) {
- // do nothing
- } else {
- throw new RuntimeException("Unexpected value type ("
- + ve.getClass().getName() + ")");
- }
- }
+ ve0 = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
+ ve1 = OperandResolver.getSingleValue(arg1, srcRowIndex, srcColumnIndex);
} catch (EvaluationException e) {
return e.getErrorEval();
}
-
+ StringBuilder sb = new StringBuilder();
+ sb.append(getText(ve0));
+ sb.append(getText(ve1));
return new StringEval(sb.toString());
}
+
+ private Object getText(ValueEval ve) {
+ if (ve instanceof StringValueEval) {
+ StringValueEval sve = (StringValueEval) ve;
+ return sve.getStringValue();
+ }
+ if (ve == BlankEval.INSTANCE) {
+ return "";
+ }
+ throw new IllegalAccessError("Unexpected value type ("
+ + ve.getClass().getName() + ")");
+ }
}
package org.apache.poi.hssf.record.formula.eval;
+import org.apache.poi.hssf.record.formula.functions.Fixed2ArgFunction;
import org.apache.poi.hssf.record.formula.functions.Function;
/**
* @author Josh Micich
*/
-public final class IntersectionEval implements Function {
+public final class IntersectionEval extends Fixed2ArgFunction {
public static final Function instance = new IntersectionEval();
// enforces singleton
}
- public ValueEval evaluate(ValueEval[] args, int srcRow, int srcCol) {
- if(args.length != 2) {
- return ErrorEval.VALUE_INVALID;
- }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
try {
- AreaEval reA = evaluateRef(args[0]);
- AreaEval reB = evaluateRef(args[1]);
+ AreaEval reA = evaluateRef(arg0);
+ AreaEval reB = evaluateRef(arg1);
AreaEval result = resolveRange(reA, reB);
if (result == null) {
return ErrorEval.NULL_INTERSECTION;
package org.apache.poi.hssf.record.formula.eval;
+import org.apache.poi.hssf.record.formula.functions.Fixed1ArgFunction;
import org.apache.poi.hssf.record.formula.functions.Function;
* Implementation of Excel formula token '%'. <p/>
* @author Josh Micich
*/
-public final class PercentEval implements Function {
+public final class PercentEval extends Fixed1ArgFunction {
public static final Function instance = new PercentEval();
// enforce singleton
}
- public ValueEval evaluate(ValueEval[] args, int srcRow, int srcCol) {
- if (args.length != 1) {
- return ErrorEval.VALUE_INVALID;
- }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
double d;
try {
- ValueEval ve = OperandResolver.getSingleValue(args[0], srcRow, srcCol);
+ ValueEval ve = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
d = OperandResolver.coerceValueToDouble(ve);
} catch (EvaluationException e) {
return e.getErrorEval();
package org.apache.poi.hssf.record.formula.eval;
+import org.apache.poi.hssf.record.formula.functions.Fixed2ArgFunction;
import org.apache.poi.hssf.record.formula.functions.Function;
*
* @author Josh Micich
*/
-public final class RangeEval implements Function {
+public final class RangeEval extends Fixed2ArgFunction {
public static final Function instance = new RangeEval();
// enforces singleton
}
- public ValueEval evaluate(ValueEval[] args, int srcRow, int srcCol) {
- if(args.length != 2) {
- return ErrorEval.VALUE_INVALID;
- }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
try {
- AreaEval reA = evaluateRef(args[0]);
- AreaEval reB = evaluateRef(args[1]);
+ AreaEval reA = evaluateRef(arg0);
+ AreaEval reB = evaluateRef(arg1);
return resolveRange(reA, reB);
} catch (EvaluationException e) {
return e.getErrorEval();
package org.apache.poi.hssf.record.formula.eval;
+import org.apache.poi.hssf.record.formula.functions.Fixed2ArgFunction;
import org.apache.poi.hssf.record.formula.functions.Function;
import org.apache.poi.ss.util.NumberComparer;
*
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
*/
-public abstract class RelationalOperationEval implements Function {
+public abstract class RelationalOperationEval extends Fixed2ArgFunction {
/**
* Converts a standard compare result (-1, 0, 1) to <code>true</code> or <code>false</code>
* Blank < Positive numbers
* </pre>
*/
- public final ValueEval evaluate(ValueEval[] operands, int srcRow, int srcCol) {
- if (operands.length != 2) {
- return ErrorEval.VALUE_INVALID;
- }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
ValueEval vA;
ValueEval vB;
try {
- vA = OperandResolver.getSingleValue(operands[0], srcRow, srcCol);
- vB = OperandResolver.getSingleValue(operands[1], srcRow, srcCol);
+ vA = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
+ vB = OperandResolver.getSingleValue(arg1, srcRowIndex, srcColumnIndex);
} catch (EvaluationException e) {
return e.getErrorEval();
}
package org.apache.poi.hssf.record.formula.eval;
+import org.apache.poi.hssf.record.formula.functions.Fixed2ArgFunction;
import org.apache.poi.hssf.record.formula.functions.Function;
/**
* @author Josh Micich
*/
-public abstract class TwoOperandNumericOperation implements Function {
+public abstract class TwoOperandNumericOperation extends Fixed2ArgFunction {
protected final double singleOperandEvaluate(ValueEval arg, int srcCellRow, int srcCellCol) throws EvaluationException {
ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
return OperandResolver.coerceValueToDouble(ve);
}
-
- public final ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
double result;
try {
- double d0 = singleOperandEvaluate(args[0], srcCellRow, srcCellCol);
- double d1 = singleOperandEvaluate(args[1], srcCellRow, srcCellCol);
+ double d0 = singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
+ double d1 = singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex);
result = evaluate(d0, d1);
if (result == 0.0) { // this '==' matches +0.0 and -0.0
// Excel converts -0.0 to +0.0 for '*', '/', '%', '+' and '^'
}
return new NumberEval(result);
}
+
protected abstract double evaluate(double d0, double d1) throws EvaluationException;
public static final Function AddEval = new TwoOperandNumericOperation() {
package org.apache.poi.hssf.record.formula.eval;
+import org.apache.poi.hssf.record.formula.functions.Fixed1ArgFunction;
import org.apache.poi.hssf.record.formula.functions.Function;
-
/**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
- *
*/
-public final class UnaryMinusEval implements Function {
+public final class UnaryMinusEval extends Fixed1ArgFunction {
public static final Function instance = new UnaryMinusEval();
// enforce singleton
}
- public ValueEval evaluate(ValueEval[] args, int srcRow, int srcCol) {
- if (args.length != 1) {
- return ErrorEval.VALUE_INVALID;
- }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
double d;
try {
- ValueEval ve = OperandResolver.getSingleValue(args[0], srcRow, srcCol);
+ ValueEval ve = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
d = OperandResolver.coerceValueToDouble(ve);
} catch (EvaluationException e) {
return e.getErrorEval();
package org.apache.poi.hssf.record.formula.eval;
+import org.apache.poi.hssf.record.formula.functions.Fixed1ArgFunction;
import org.apache.poi.hssf.record.formula.functions.Function;
/**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
- *
*/
-public final class UnaryPlusEval implements Function {
+public final class UnaryPlusEval extends Fixed1ArgFunction {
public static final Function instance = new UnaryPlusEval();
// enforce singleton
}
- public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
- if(args.length != 1) {
- return ErrorEval.VALUE_INVALID;
- }
+ public ValueEval evaluate(int srcCellRow, int srcCellCol, ValueEval arg0) {
double d;
try {
- ValueEval ve = OperandResolver.getSingleValue(args[0], srcCellRow, srcCellCol);
+ ValueEval ve = OperandResolver.getSingleValue(arg0, srcCellRow, srcCellCol);
if(ve instanceof StringEval) {
// Note - asymmetric with UnaryMinus
// -"hello" evaluates to #VALUE!
*
* @author Guenter Kickinger g.kickinger@gmx.net
*/
-public final class CalendarFieldFunction implements Function {
+public final class CalendarFieldFunction extends Fixed1ArgFunction {
public static final Function YEAR = new CalendarFieldFunction(Calendar.YEAR, false);
public static final Function MONTH = new CalendarFieldFunction(Calendar.MONTH, true);
_needsOneBaseAdjustment = needsOneBaseAdjustment;
}
- public ValueEval evaluate(ValueEval[] operands, int srcCellRow, int srcCellCol) {
- if (operands.length != 1) {
- return ErrorEval.VALUE_INVALID;
- }
-
+ public final ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
int val;
try {
- ValueEval ve = OperandResolver.getSingleValue(operands[0], srcCellRow, srcCellCol);
+ ValueEval ve = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
val = OperandResolver.coerceValueToInt(ve);
} catch (EvaluationException e) {
return e.getErrorEval();
import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
-public final class Column implements Function {
- public ValueEval evaluate(ValueEval[] evals, int srcCellRow, int srcCellCol) {
- ValueEval retval = null;
- int cnum = -1;
-
- switch (evals.length) {
- default:
- retval = ErrorEval.VALUE_INVALID;
- case 1:
- if (evals[0] instanceof AreaEval) {
- AreaEval ae = (AreaEval) evals[0];
- cnum = ae.getFirstColumn();
- }
- else if (evals[0] instanceof RefEval) {
- RefEval re = (RefEval) evals[0];
- cnum = re.getColumn();
- }
- else { // anything else is not valid argument
- retval = ErrorEval.VALUE_INVALID;
- }
- break;
- case 0:
- cnum = srcCellCol;
- }
+public final class Column implements Function0Arg, Function1Arg {
- if (retval == null) {
- retval = (cnum >= 0)
- ? new NumberEval(cnum + 1) // +1 since excel colnums are 1 based
- : (ValueEval) ErrorEval.VALUE_INVALID;
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) {
+ return new NumberEval(srcColumnIndex+1);
+ }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
+ int rnum;
+
+ if (arg0 instanceof AreaEval) {
+ rnum = ((AreaEval) arg0).getFirstColumn();
+ } else if (arg0 instanceof RefEval) {
+ rnum = ((RefEval) arg0).getColumn();
+ } else {
+ // anything else is not valid argument
+ return ErrorEval.VALUE_INVALID;
}
- return retval;
+ return new NumberEval(rnum + 1);
+ }
+ public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+ switch (args.length) {
+ case 1:
+ return evaluate(srcRowIndex, srcColumnIndex, args[0]);
+ case 0:
+ return new NumberEval(srcColumnIndex+1);
+ }
+ return ErrorEval.VALUE_INVALID;
}
-
-
}
*
* @author Josh Micich
*/
-public final class Columns implements Function {
+public final class Columns extends Fixed1ArgFunction {
- public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
- switch(args.length) {
- case 1:
- // expected
- break;
- case 0:
- // too few arguments
- return ErrorEval.VALUE_INVALID;
- default:
- // too many arguments
- return ErrorEval.VALUE_INVALID;
- }
- ValueEval firstArg = args[0];
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
int result;
- if (firstArg instanceof AreaEval) {
- AreaEval ae = (AreaEval) firstArg;
- result = ae.getLastColumn() - ae.getFirstColumn() + 1;
- } else if (firstArg instanceof RefEval) {
+ if (arg0 instanceof AreaEval) {
+ result = ((AreaEval) arg0).getWidth();
+ } else if (arg0 instanceof RefEval) {
result = 1;
} else { // anything else is not valid argument
return ErrorEval.VALUE_INVALID;
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.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
*
* @author Mads Mohr Christensen
*/
-public final class Countblank implements Function {
+public final class Countblank extends Fixed1ArgFunction {
- public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
- if (args.length != 1) {
- // TODO - it doesn't seem to be possible to enter COUNTBLANK() into Excel with the wrong arg count
- // perhaps this should be an exception
- return ErrorEval.VALUE_INVALID;
- }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
double result;
- ValueEval arg0 = args[0];
if (arg0 instanceof RefEval) {
result = CountUtils.countMatchingCell((RefEval) arg0, predicate);
} else if (arg0 instanceof AreaEval) {
*
* @author Josh Micich
*/
-public final class Countif implements Function {
+public final class Countif extends Fixed2ArgFunction {
private static final class CmpOp {
public static final int NONE = 0;
}
}
- public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
- switch(args.length) {
- case 2:
- // expected
- break;
- default:
- // TODO - it doesn't seem to be possible to enter COUNTIF() into Excel with the wrong arg count
- // perhaps this should be an exception
- return ErrorEval.VALUE_INVALID;
- }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
- I_MatchPredicate mp = createCriteriaPredicate(args[1], srcRowIndex, srcColumnIndex);
+ I_MatchPredicate mp = createCriteriaPredicate(arg1, srcRowIndex, srcColumnIndex);
if(mp == null) {
// If the criteria arg is a reference to a blank cell, countif always returns zero.
return NumberEval.ZERO;
}
- double result = countMatchingCellsInArea(args[0], mp);
+ double result = countMatchingCellsInArea(arg0, mp);
return new NumberEval(result);
}
/**
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;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
+
/**
* @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
*/
-public final class DateFunc extends NumericFunction.MultiArg {
+public final class DateFunc extends Fixed3ArgFunction {
public static final Function instance = new DateFunc();
private DateFunc() {
- super(3,3);
+ // no fields to initialise
+ }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+ ValueEval arg2) {
+ double result;
+ try {
+ double d0 = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
+ double d1 = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex);
+ double d2 = NumericFunction.singleOperandEvaluate(arg2, srcRowIndex, srcColumnIndex);
+ result = evaluate(getYear(d0), (int) (d1 - 1), (int) d2);
+ NumericFunction.checkValue(result);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+ return new NumberEval(result);
}
- protected double evaluate(double[] ds) throws EvaluationException {
- int year = getYear(ds[0]);
- int month = (int) ds[1] - 1;
- int day = (int) ds[2];
+ private static double evaluate(int year, int month, int day) throws EvaluationException {
if (year < 0 || month < 0 || day < 0) {
throw new EvaluationException(ErrorEval.VALUE_INVALID);
*
* @author Josh Micich
*/
-public final class Errortype implements Function {
+public final class Errortype extends Fixed1ArgFunction {
- public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
try {
- OperandResolver.getSingleValue(args[0], srcCellRow, srcCellCol);
+ OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
return ErrorEval.NA;
} catch (EvaluationException e) {
int result = translateErrorCodeToErrorTypeValue(e.getErrorEval().getErrorCode());
--- /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 functions that only take zero arguments.
+ *
+ * @author Josh Micich
+ */
+public abstract class Fixed0ArgFunction implements Function0Arg {
+ public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+ if (args.length != 0) {
+ return ErrorEval.VALUE_INVALID;
+ }
+ return evaluate(srcRowIndex, srcColumnIndex);
+ }
+}
--- /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 functions that must take exactly one argument.
+ *
+ * @author Josh Micich
+ */
+public abstract class Fixed1ArgFunction implements Function1Arg {
+ public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+ if (args.length != 1) {
+ return ErrorEval.VALUE_INVALID;
+ }
+ return evaluate(srcRowIndex, srcColumnIndex, args[0]);
+ }
+}
--- /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 functions that must take exactly two arguments.
+ *
+ * @author Josh Micich
+ */
+public abstract class Fixed2ArgFunction implements Function2Arg {
+ public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+ if (args.length != 2) {
+ return ErrorEval.VALUE_INVALID;
+ }
+ return evaluate(srcRowIndex, srcColumnIndex, args[0], args[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;
+
+import org.apache.poi.hssf.record.formula.eval.ErrorEval;
+import org.apache.poi.hssf.record.formula.eval.ValueEval;
+
+/**
+ * Convenience base class for functions that must take exactly three arguments.
+ *
+ * @author Josh Micich
+ */
+public abstract class Fixed3ArgFunction implements Function3Arg {
+ public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+ if (args.length != 3) {
+ return ErrorEval.VALUE_INVALID;
+ }
+ return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2]);
+ }
+}
--- /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 functions that must take exactly four arguments.
+ *
+ * @author Josh Micich
+ */
+public abstract class Fixed4ArgFunction implements Function4Arg {
+ public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+ if (args.length != 4) {
+ return ErrorEval.VALUE_INVALID;
+ }
+ return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2], args[3]);
+ }
+}
--- /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.ValueEval;
+
+/**
+ * Implemented by all functions that can be called with zero arguments
+ *
+ * @author Josh Micich
+ */
+public interface Function0Arg extends Function {
+ /**
+ * see {@link Function#evaluate(ValueEval[], int, int)}
+ */
+ ValueEval evaluate(int srcRowIndex, int srcColumnIndex);
+}
--- /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.ValueEval;
+
+/**
+ * Implemented by all functions that can be called with one argument
+ *
+ * @author Josh Micich
+ */
+public interface Function1Arg extends Function {
+ /**
+ * see {@link Function#evaluate(ValueEval[], int, int)}
+ */
+ ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0);
+}
--- /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.ValueEval;
+
+/**
+ * Implemented by all functions that can be called with two arguments
+ *
+ * @author Josh Micich
+ */
+public interface Function2Arg extends Function {
+ /**
+ * see {@link Function#evaluate(ValueEval[], int, int)}
+ */
+ ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1);
+}
--- /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.ValueEval;
+
+/**
+ * Implemented by all functions that can be called with three arguments
+ *
+ * @author Josh Micich
+ */
+public interface Function3Arg extends Function {
+ /**
+ * see {@link Function#evaluate(ValueEval[], int, int)}
+ */
+ ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, ValueEval arg2);
+}
--- /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.ValueEval;
+
+/**
+ * Implemented by all functions that can be called with four arguments
+ *
+ * @author Josh Micich
+ */
+public interface Function4Arg extends Function {
+ /**
+ * see {@link Function#evaluate(ValueEval[], int, int)}
+ */
+ ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, ValueEval arg2, ValueEval arg3);
+}
*
* @author Josh Micich
*/
-public final class Na implements Function {
+public final class Na extends Fixed0ArgFunction {
- public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
+ public ValueEval evaluate(int srcCellRow, int srcCellCol) {
return ErrorEval.NA;
}
-
}
import java.util.Date;
-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;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
*
* @author Frank Taffelt
*/
-public final class Now implements Function {
-
- public ValueEval evaluate(ValueEval[] evals, int srcCellRow, int srcCellCol) {
- if (evals.length > 0) {
- return ErrorEval.VALUE_INVALID;
- }
+public final class Now extends Fixed0ArgFunction {
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) {
Date now = new Date(System.currentTimeMillis());
return new NumberEval(HSSFDateUtil.getExcelDate(now));
}
return result;
}
- private static final void checkValue(double result) throws EvaluationException {
+ /**
+ * @throws EvaluationException (#NUM!) if <tt>result</tt> is <tt>NaN</> or <tt>Infinity</tt>
+ */
+ static final void checkValue(double result) throws EvaluationException {
if (Double.isNaN(result) || Double.isInfinite(result)) {
throw new EvaluationException(ErrorEval.NUM_ERROR);
}
*
* @author Manda Wilson < wilson at c bio dot msk cc dot org >
*/
-public final class Replace extends TextFunction {
+public final class Replace extends Fixed4ArgFunction {
- protected ValueEval evaluateFunc(ValueEval[] args, int srcCellRow, int srcCellCol)
- throws EvaluationException {
- if (args.length != 4) {
- return ErrorEval.VALUE_INVALID;
- }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+ ValueEval arg2, ValueEval arg3) {
- String oldStr = evaluateStringArg(args[0], srcCellRow, srcCellCol);
- int startNum = evaluateIntArg(args[1], srcCellRow, srcCellCol);
- int numChars = evaluateIntArg(args[2], srcCellRow, srcCellCol);
- String newStr = evaluateStringArg(args[3], srcCellRow, srcCellCol);
+ String oldStr;
+ int startNum;
+ int numChars;
+ String newStr;
+ try {
+ oldStr = TextFunction.evaluateStringArg(arg0, srcRowIndex, srcColumnIndex);
+ startNum = TextFunction.evaluateIntArg(arg1, srcRowIndex, srcColumnIndex);
+ numChars = TextFunction.evaluateIntArg(arg2, srcRowIndex, srcColumnIndex);
+ newStr = TextFunction.evaluateStringArg(arg3, srcRowIndex, srcColumnIndex);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
if (startNum < 1 || numChars < 0) {
return ErrorEval.VALUE_INVALID;
import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
-public final class Row implements Function {
-
- public ValueEval evaluate(ValueEval[] evals, int srcCellRow, int srcCellCol) {
- ValueEval retval = null;
- int rnum = -1;
-
- switch (evals.length) {
- default:
- retval = ErrorEval.VALUE_INVALID;
- case 1:
- if (evals[0] instanceof AreaEval) {
- AreaEval ae = (AreaEval) evals[0];
- rnum = ae.getFirstRow();
- }
- else if (evals[0] instanceof RefEval) {
- RefEval re = (RefEval) evals[0];
- rnum = re.getRow();
- }
- else { // anything else is not valid argument
- retval = ErrorEval.VALUE_INVALID;
- }
- break;
- case 0:
- rnum = srcCellRow;
- }
+public final class Row implements Function0Arg, Function1Arg {
- if (retval == null) {
- retval = (rnum >= 0)
- ? new NumberEval(rnum + 1) // +1 since excel rownums are 1 based
- : (ValueEval) ErrorEval.VALUE_INVALID;
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) {
+ return new NumberEval(srcRowIndex+1);
+ }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
+ int rnum;
+
+ if (arg0 instanceof AreaEval) {
+ rnum = ((AreaEval) arg0).getFirstRow();
+ } else if (arg0 instanceof RefEval) {
+ rnum = ((RefEval) arg0).getRow();
+ } else {
+ // anything else is not valid argument
+ return ErrorEval.VALUE_INVALID;
}
- return retval;
+ return new NumberEval(rnum + 1);
+ }
+ public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+ switch (args.length) {
+ case 1:
+ return evaluate(srcRowIndex, srcColumnIndex, args[0]);
+ case 0:
+ return new NumberEval(srcRowIndex+1);
+ }
+ return ErrorEval.VALUE_INVALID;
}
}
*
* @author Josh Micich
*/
-public final class Rows implements Function {
+public final class Rows extends Fixed1ArgFunction {
- public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
- switch(args.length) {
- case 1:
- // expected
- break;
- case 0:
- // too few arguments
- return ErrorEval.VALUE_INVALID;
- default:
- // too many arguments
- return ErrorEval.VALUE_INVALID;
- }
- ValueEval firstArg = args[0];
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
int result;
- if (firstArg instanceof AreaEval) {
- AreaEval ae = (AreaEval) firstArg;
- result = ae.getLastRow() - ae.getFirstRow() + 1;
- } else if (firstArg instanceof RefEval) {
+ if (arg0 instanceof AreaEval) {
+ result = ((AreaEval) arg0).getHeight();
+ } else if (arg0 instanceof RefEval) {
result = 1;
} else { // anything else is not valid argument
return ErrorEval.VALUE_INVALID;
* cause an empty string result. If the argument is an area, the first (top-left) cell is used
* (regardless of the coordinates of the evaluating formula cell).
*/
-public final class T implements Function {
-
- public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
- switch (args.length) {
- default:
- return ErrorEval.VALUE_INVALID;
- case 1:
- break;
- }
- ValueEval arg = args[0];
+public final class T extends Fixed1ArgFunction {
+
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
+ ValueEval arg = arg0;
if (arg instanceof RefEval) {
arg = ((RefEval) arg).getInnerValueEval();
} else if (arg instanceof AreaEval) {
*
* Based on POI org.apache.hssf.record.formula.DateFunc.java
*/
-public final class Time implements Function {
+public final class Time extends Fixed3ArgFunction {
private static final int SECONDS_PER_MINUTE = 60;
private static final int SECONDS_PER_HOUR = 3600;
private static final int SECONDS_PER_DAY = HOURS_PER_DAY * SECONDS_PER_HOUR;
- public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
- if (args.length != 3) {
- return ErrorEval.VALUE_INVALID;
- }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+ ValueEval arg2) {
double result;
-
try {
- result = evaluate(evalArg(args[0]), evalArg(args[1]), evalArg(args[2]));
+ result = evaluate(evalArg(arg0, srcRowIndex, srcColumnIndex), evalArg(arg1, srcRowIndex, srcColumnIndex), evalArg(arg2, srcRowIndex, srcColumnIndex));
} catch (EvaluationException e) {
return e.getErrorEval();
}
return new NumberEval(result);
}
- private static int evalArg(ValueEval arg) throws EvaluationException {
+ private static int evalArg(ValueEval arg, int srcRowIndex, int srcColumnIndex) throws EvaluationException {
if (arg == MissingArgEval.instance) {
return 0;
}
+ ValueEval ev = OperandResolver.getSingleValue(arg, srcRowIndex, srcColumnIndex);
// Excel silently truncates double values to integers
- return OperandResolver.coerceValueToInt(arg);
+ return OperandResolver.coerceValueToInt(ev);
}
/**
* Converts the supplied hours, minutes and seconds to an Excel time value.
import java.util.Calendar;
import java.util.GregorianCalendar;
-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;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
*
* @author Frank Taffelt
*/
-public final class Today implements Function {
+public final class Today extends Fixed0ArgFunction {
- public ValueEval evaluate(ValueEval[] evals, int srcCellRow, int srcCellCol) {
- if (evals.length > 0) {
- return ErrorEval.VALUE_INVALID;
- }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) {
Calendar now = new GregorianCalendar();
now.set(now.get(Calendar.YEAR), now.get(Calendar.MONTH), now.get(Calendar.DATE),0,0,0);
return new NumberEval(HSSFDateUtil.getExcelDate(now.getTime()));
}
}
-
*
* @author Josh Micich
*/
-public final class Value implements Function {
+public final class Value extends Fixed1ArgFunction {
/** "1,0000" is valid, "1,00" is not */
private static final int MIN_DISTANCE_BETWEEN_THOUSANDS_SEPARATOR = 4;
private static final Double ZERO = new Double(0.0);
- public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
- if (args.length != 1) {
- return ErrorEval.VALUE_INVALID;
- }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
ValueEval veText;
try {
- veText = OperandResolver.getSingleValue(args[0], srcCellRow, srcCellCol);
+ veText = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
} catch (EvaluationException e) {
return e.getErrorEval();
}
*
* @author Josh Micich
*/
-abstract class Var2or3ArgFunction implements Function {
+abstract class Var2or3ArgFunction implements Function2Arg, Function3Arg {
public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
switch (args.length) {
}
return ErrorEval.VALUE_INVALID;
}
-
- public abstract ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0,
- ValueEval arg1, ValueEval arg2);
-
- public abstract ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0,
- ValueEval arg1);
}
/**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
- *
*/
-public abstract class XYNumericFunction implements Function {
+public abstract class XYNumericFunction extends Fixed2ArgFunction {
private static abstract class ValueArray implements ValueVector {
private final int _size;
*/
protected abstract Accumulator createAccumulator();
- public final ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
- if (args.length != 2) {
- return ErrorEval.VALUE_INVALID;
- }
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
double result;
try {
- ValueVector vvX = createValueVector(args[0]);
- ValueVector vvY = createValueVector(args[1]);
+ ValueVector vvX = createValueVector(arg0);
+ ValueVector vvY = createValueVector(arg1);
int size = vvX.getSize();
if (size == 0 || vvY.getSize() != size) {
return ErrorEval.NA;