replace over engineered inner classes with lambdas/method references

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1888743 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2021-04-13 19:44:38 +00:00
parent 3c03974499
commit 240b02daec
16 changed files with 437 additions and 605 deletions

View File

@ -73,9 +73,9 @@ public final class FunctionEval {
retval[5] = AggregateFunction.AVERAGE; retval[5] = AggregateFunction.AVERAGE;
retval[6] = AggregateFunction.MIN; retval[6] = AggregateFunction.MIN;
retval[7] = AggregateFunction.MAX; retval[7] = AggregateFunction.MAX;
retval[8] = new RowFunc(); // ROW retval[8] = RowFunc::evaluate; // ROW
retval[9] = new Column(); retval[9] = Column::evaluate;
retval[10] = new Na(); retval[10] = Na::evaluate;
retval[11] = new Npv(); retval[11] = new Npv();
retval[12] = AggregateFunction.STDEV; retval[12] = AggregateFunction.STDEV;
retval[13] = NumericFunction.DOLLAR; retval[13] = NumericFunction.DOLLAR;
@ -137,7 +137,7 @@ public final class FunctionEval {
retval[71] = CalendarFieldFunction.HOUR; retval[71] = CalendarFieldFunction.HOUR;
retval[72] = CalendarFieldFunction.MINUTE; retval[72] = CalendarFieldFunction.MINUTE;
retval[73] = CalendarFieldFunction.SECOND; retval[73] = CalendarFieldFunction.SECOND;
retval[74] = new Now(); retval[74] = Now::evaluate;
retval[75] = new Areas(); retval[75] = new Areas();
retval[76] = new Rows(); retval[76] = new Rows();
retval[77] = new Columns(); retval[77] = new Columns();
@ -226,7 +226,7 @@ public final class FunctionEval {
retval[216] = new Rank(); retval[216] = new Rank();
retval[219] = new Address(); retval[219] = new Address();
retval[220] = new Days360(); retval[220] = new Days360();
retval[221] = new Today(); retval[221] = Today::evaluate;
//222: VBD //222: VBD
retval[227] = AggregateFunction.MEDIAN; retval[227] = AggregateFunction.MEDIAN;
@ -259,7 +259,7 @@ public final class FunctionEval {
retval[276] = NumericFunction.COMBIN; retval[276] = NumericFunction.COMBIN;
// 277: CONFIDENCE // 277: CONFIDENCE
// 278:CRITBINOM // 278:CRITBINOM
retval[279] = new Even(); retval[279] = NumericFunction.EVEN;
// 280: EXPONDIST // 280: EXPONDIST
// 281: FDIST // 281: FDIST
// 282: FINV // 282: FINV
@ -278,7 +278,7 @@ public final class FunctionEval {
// 295: NORMINV // 295: NORMINV
// 296: NORMSINV // 296: NORMSINV
// 297: STANDARDIZE // 297: STANDARDIZE
retval[298] = new Odd(); retval[298] = NumericFunction.ODD;
// 299: PERMUT // 299: PERMUT
retval[300] = NumericFunction.POISSON; retval[300] = NumericFunction.POISSON;
// 301: TDIST // 301: TDIST

View File

@ -32,10 +32,10 @@ public interface ArrayFunction {
/** /**
* @param args the evaluated function arguments. Empty values are represented with * @param args the evaluated function arguments. Empty values are represented with
* {@link BlankEval} or {@link MissingArgEval}, never <code>null</code>. * {@link BlankEval} or {@link MissingArgEval}, never {@code null}.
* @param srcRowIndex row index of the cell containing the formula under evaluation * @param srcRowIndex row index of the cell containing the formula under evaluation
* @param srcColumnIndex column index of the cell containing the formula under evaluation * @param srcColumnIndex column index of the cell containing the formula under evaluation
* @return The evaluated result, possibly an {@link ErrorEval}, never <code>null</code>. * @return The evaluated result, possibly an {@link ErrorEval}, never {@code null}.
* <b>Note</b> - Excel uses the error code <i>#NUM!</i> instead of IEEE <i>NaN</i>, so when * <b>Note</b> - Excel uses the error code <i>#NUM!</i> instead of IEEE <i>NaN</i>, so when
* numeric functions evaluate to {@link Double#NaN} be sure to translate the result to {@link * numeric functions evaluate to {@link Double#NaN} be sure to translate the result to {@link
* ErrorEval#NUM_ERROR}. * ErrorEval#NUM_ERROR}.
@ -47,19 +47,29 @@ public interface ArrayFunction {
* Evaluate an array function with two arguments. * Evaluate an array function with two arguments.
* *
* @param arg0 the first function argument. Empty values are represented with * @param arg0 the first function argument. Empty values are represented with
* {@link BlankEval} or {@link MissingArgEval}, never <code>null</code> * {@link BlankEval} or {@link MissingArgEval}, never {@code null}
* @param arg1 the first function argument. Empty values are represented with * @param arg1 the first function argument. Empty values are represented with
* @link BlankEval} or {@link MissingArgEval}, never <code>null</code> * @link BlankEval} or {@link MissingArgEval}, never {@code null}
* *
* @param srcRowIndex row index of the cell containing the formula under evaluation * @param srcRowIndex row index of the cell containing the formula under evaluation
* @param srcColumnIndex column index of the cell containing the formula under evaluation * @param srcColumnIndex column index of the cell containing the formula under evaluation
* @return The evaluated result, possibly an {@link ErrorEval}, never <code>null</code>. * @return The evaluated result, possibly an {@link ErrorEval}, never {@code null}.
* <b>Note</b> - Excel uses the error code <i>#NUM!</i> instead of IEEE <i>NaN</i>, so when * <b>Note</b> - Excel uses the error code <i>#NUM!</i> instead of IEEE <i>NaN</i>, so when
* numeric functions evaluate to {@link Double#NaN} be sure to translate the result to {@link * numeric functions evaluate to {@link Double#NaN} be sure to translate the result to {@link
* ErrorEval#NUM_ERROR}. * ErrorEval#NUM_ERROR}.
*/ */
default ValueEval evaluateTwoArrayArgs(ValueEval arg0, ValueEval arg1, int srcRowIndex, int srcColumnIndex, default ValueEval evaluateTwoArrayArgs(ValueEval arg0, ValueEval arg1, int srcRowIndex, int srcColumnIndex,
BiFunction<ValueEval, ValueEval, ValueEval> evalFunc) { BiFunction<ValueEval, ValueEval, ValueEval> evalFunc) {
return _evaluateTwoArrayArgs(arg0, arg1, srcRowIndex, srcColumnIndex, evalFunc);
}
default ValueEval evaluateOneArrayArg(ValueEval arg0, int srcRowIndex, int srcColumnIndex,
java.util.function.Function<ValueEval, ValueEval> evalFunc) {
return _evaluateOneArrayArg(arg0, srcRowIndex, srcColumnIndex, evalFunc);
}
static ValueEval _evaluateTwoArrayArgs(ValueEval arg0, ValueEval arg1, int srcRowIndex, int srcColumnIndex,
BiFunction<ValueEval, ValueEval, ValueEval> evalFunc) {
int w1, w2, h1, h2; int w1, w2, h1, h2;
int a1FirstCol = 0, a1FirstRow = 0; int a1FirstCol = 0, a1FirstRow = 0;
if (arg0 instanceof AreaEval) { if (arg0 instanceof AreaEval) {
@ -150,8 +160,9 @@ public interface ArrayFunction {
return new CacheAreaEval(srcRowIndex, srcColumnIndex, srcRowIndex + height - 1, srcColumnIndex + width - 1, vals); return new CacheAreaEval(srcRowIndex, srcColumnIndex, srcRowIndex + height - 1, srcColumnIndex + width - 1, vals);
} }
default ValueEval evaluateOneArrayArg(ValueEval arg0, int srcRowIndex, int srcColumnIndex,
java.util.function.Function<ValueEval, ValueEval> evalFunc){ static ValueEval _evaluateOneArrayArg(ValueEval arg0, int srcRowIndex, int srcColumnIndex,
java.util.function.Function<ValueEval, ValueEval> evalFunc){
int w1, w2, h1, h2; int w1, w2, h1, h2;
int a1FirstCol = 0, a1FirstRow = 0; int a1FirstCol = 0, a1FirstRow = 0;
if (arg0 instanceof AreaEval) { if (arg0 instanceof AreaEval) {
@ -204,7 +215,6 @@ public interface ArrayFunction {
} }
return new CacheAreaEval(srcRowIndex, srcColumnIndex, srcRowIndex + height - 1, srcColumnIndex + width - 1, vals); return new CacheAreaEval(srcRowIndex, srcColumnIndex, srcRowIndex + height - 1, srcColumnIndex + width - 1, vals);
} }
} }

View File

@ -34,8 +34,6 @@ import org.apache.poi.ss.formula.eval.ValueEval;
* <li> Numbers: 0 is false. Any other number is TRUE </li> * <li> Numbers: 0 is false. Any other number is TRUE </li>
* <li> Areas: *all* cells in area are evaluated according to the above rules</li> * <li> Areas: *all* cells in area are evaluated according to the above rules</li>
* </ol> * </ol>
*
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*/ */
public abstract class BooleanFunction implements Function,ArrayFunction { public abstract class BooleanFunction implements Function,ArrayFunction {
@ -132,43 +130,12 @@ public abstract class BooleanFunction implements Function,ArrayFunction {
return cumulativeResult || 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;
}
};
abstract static class Boolean1ArgFunction extends Fixed1ArgFunction implements ArrayFunction { public static final Function FALSE = BooleanFunction::evaluateFalse;
@Override
public ValueEval evaluateArray(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
if (args.length != 1) {
return ErrorEval.VALUE_INVALID;
}
return evaluateOneArrayArg(args[0], srcRowIndex, srcColumnIndex,
vA -> evaluate(srcRowIndex, srcColumnIndex, vA));
}
} public static final Function TRUE = BooleanFunction::evaluateTrue;
public static final Function NOT = new Boolean1ArgFunction() { public static final Function NOT = BooleanFunction::evaluateNot;
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;
} catch (EvaluationException e) {
return e.getErrorEval();
}
return BoolEval.valueOf(!boolArgVal);
}
};
@Override @Override
public ValueEval evaluateArray(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { public ValueEval evaluateArray(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
@ -178,4 +145,30 @@ public abstract class BooleanFunction implements Function,ArrayFunction {
return evaluateOneArrayArg(args[0], srcRowIndex, srcColumnIndex, return evaluateOneArrayArg(args[0], srcRowIndex, srcColumnIndex,
vA -> evaluate(new ValueEval[]{vA}, srcRowIndex, srcColumnIndex)); vA -> evaluate(new ValueEval[]{vA}, srcRowIndex, srcColumnIndex));
} }
private static ValueEval evaluateFalse(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
return args.length != 0 ? ErrorEval.VALUE_INVALID : BoolEval.FALSE;
}
private static ValueEval evaluateTrue(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
return args.length != 0 ? ErrorEval.VALUE_INVALID : BoolEval.TRUE;
}
private static ValueEval evaluateNot(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
if (args.length != 1) {
return ErrorEval.VALUE_INVALID;
}
java.util.function.Function<ValueEval, ValueEval> notInner = (va) -> {
try {
ValueEval ve = OperandResolver.getSingleValue(va, srcRowIndex, srcColumnIndex);
Boolean b = OperandResolver.coerceValueToBoolean(ve, false);
boolean boolArgVal = b != null && b;
return BoolEval.valueOf(!boolArgVal);
} catch (EvaluationException e) {
return e.getErrorEval();
}
};
return ArrayFunction._evaluateOneArrayArg(args[0], srcRowIndex, srcColumnIndex, notInner);
}
} }

View File

@ -23,18 +23,19 @@ import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.RefEval; import org.apache.poi.ss.formula.eval.RefEval;
import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.formula.eval.ValueEval;
public final class Column implements Function0Arg, Function1Arg { public final class Column {
public static ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
if (args.length > 1) {
return 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; int rnum;
if (args.length == 0) {
if (arg0 instanceof AreaEval) { rnum = srcColumnIndex;
rnum = ((AreaEval) arg0).getFirstColumn(); } else if (args[0] instanceof AreaEval) {
} else if (arg0 instanceof RefEval) { rnum = ((AreaEval) args[0]).getFirstColumn();
rnum = ((RefEval) arg0).getColumn(); } else if (args[0] instanceof RefEval) {
rnum = ((RefEval) args[0]).getColumn();
} else { } else {
// anything else is not valid argument // anything else is not valid argument
return ErrorEval.VALUE_INVALID; return ErrorEval.VALUE_INVALID;
@ -42,13 +43,4 @@ public final class Column implements Function0Arg, Function1Arg {
return new NumberEval(rnum + 1.); 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;
}
} }

View File

@ -1,49 +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.ss.formula.functions;
/**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*
*/
public final class Even extends NumericFunction.OneArg {
private static final long PARITY_MASK = 0xFFFFFFFFFFFFFFFEL;
protected double evaluate(double d) {
if (d==0) {
return 0;
}
long result;
if (d>0) {
result = calcEven(d);
} else {
result = -calcEven(-d);
}
return result;
}
private static long calcEven(double d) {
long x = ((long) d) & PARITY_MASK;
if (x == d) {
return x;
}
return x + 2;
}
}

View File

@ -19,12 +19,15 @@ package org.apache.poi.ss.formula.functions;
import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.util.Removal;
/** /**
* Convenience base class for functions that only take zero arguments. * Convenience base class for functions that only take zero arguments.
* *
* @author Josh Micich * @deprecated replaced by lambda expressions in 5.0.1
*/ */
@Deprecated
@Removal(version = "6.0.0")
public abstract class Fixed0ArgFunction implements Function0Arg { public abstract class Fixed0ArgFunction implements Function0Arg {
public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
if (args.length != 0) { if (args.length != 0) {

View File

@ -0,0 +1,50 @@
/* ====================================================================
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.ss.formula.functions;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval;
public class Log {
private static final double TEN = 10.0;
private static final double LOG_10_TO_BASE_e = Math.log(TEN);
public static ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
if (args.length != 1 && args.length != 2) {
return ErrorEval.VALUE_INVALID;
}
try {
double d0 = NumericFunction.singleOperandEvaluate(args[0], srcRowIndex, srcColumnIndex);
double result;
if (args.length == 1) {
result = Math.log(d0) / LOG_10_TO_BASE_e;
} else {
double d1 = NumericFunction.singleOperandEvaluate(args[1], srcRowIndex, srcColumnIndex);
double logE = Math.log(d0);
result = (Double.compare(d1, Math.E) == 0) ? logE : (logE / Math.log(d1));
}
NumericFunction.checkValue(result);
return new NumberEval(result);
} catch (EvaluationException e) {
return e.getErrorEval();
}
}
}

View File

@ -51,6 +51,12 @@ final class MathX {
return round(n, p, java.math.RoundingMode.HALF_UP); return round(n, p, java.math.RoundingMode.HALF_UP);
} }
public static double round(double n, double p) {
return round(n, (int)p);
}
/** /**
* Returns a value rounded-up to p digits after decimal. * Returns a value rounded-up to p digits after decimal.
* If p is negative, then the number is rounded to * If p is negative, then the number is rounded to
@ -70,6 +76,11 @@ final class MathX {
return round(n, p, java.math.RoundingMode.UP); return round(n, p, java.math.RoundingMode.UP);
} }
public static double roundUp(double n, double p) {
return roundUp(n, (int)p);
}
/** /**
* Returns a value rounded to p digits after decimal. * Returns a value rounded to p digits after decimal.
* If p is negative, then the number is rounded to * If p is negative, then the number is rounded to
@ -89,6 +100,10 @@ final class MathX {
return round(n, p, java.math.RoundingMode.DOWN); return round(n, p, java.math.RoundingMode.DOWN);
} }
public static double roundDown(double n, double p) {
return roundDown(n, (int)p);
}
private static double round(double n, int p, java.math.RoundingMode rounding) { private static double round(double n, int p, java.math.RoundingMode rounding) {
if (Double.isNaN(n) || Double.isInfinite(n)) { if (Double.isNaN(n) || Double.isInfinite(n)) {
return Double.NaN; return Double.NaN;
@ -273,6 +288,10 @@ final class MathX {
return d; return d;
} }
public static double factorial(double d) {
return factorial((int)d);
}
/** /**
* returns the remainder resulting from operation: * returns the remainder resulting from operation:

View File

@ -22,12 +22,9 @@ import org.apache.poi.ss.formula.eval.ValueEval;
/** /**
* Implementation of Excel function NA() * Implementation of Excel function NA()
*
* @author Josh Micich
*/ */
public final class Na extends Fixed0ArgFunction { public final class Na {
public static ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
public ValueEval evaluate(int srcCellRow, int srcCellCol) { return args.length != 0 ? ErrorEval.VALUE_INVALID : ErrorEval.NA;
return ErrorEval.NA;
} }
} }

View File

@ -19,18 +19,19 @@ package org.apache.poi.ss.formula.functions;
import java.util.Date; import java.util.Date;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.NumberEval; import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.DateUtil;
/** /**
* Implementation of Excel NOW() Function * Implementation of Excel NOW() Function
*
* @author Frank Taffelt
*/ */
public final class Now extends Fixed0ArgFunction { public final class Now {
public static ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { if (args.length != 0) {
return ErrorEval.VALUE_INVALID;
}
Date now = new Date(System.currentTimeMillis()); Date now = new Date(System.currentTimeMillis());
return new NumberEval(DateUtil.getExcelDate(now)); return new NumberEval(DateUtil.getExcelDate(now));
} }

View File

@ -17,18 +17,17 @@
package org.apache.poi.ss.formula.functions; package org.apache.poi.ss.formula.functions;
import static org.apache.poi.ss.formula.eval.ErrorEval.VALUE_INVALID;
import org.apache.poi.ss.formula.eval.*; import org.apache.poi.ss.formula.eval.*;
/**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
* @author Josh Micich
* @author Stephen Wolke (smwolke at geistig.com)
*/
public abstract class NumericFunction implements Function { public abstract class NumericFunction implements Function {
static final double ZERO = 0.0; private static final double ZERO = 0.0;
static final double TEN = 10.0; private static final double TEN = 10.0;
static final double LOG_10_TO_BASE_e = Math.log(TEN); private static final double LOG_10_TO_BASE_e = Math.log(TEN);
private static final long PARITY_MASK = 0xFFFFFFFFFFFFFFFEL;
protected static double singleOperandEvaluate(ValueEval arg, int srcRowIndex, int srcColumnIndex) throws EvaluationException { protected static double singleOperandEvaluate(ValueEval arg, int srcRowIndex, int srcColumnIndex) throws EvaluationException {
if (arg == null) { if (arg == null) {
@ -41,7 +40,7 @@ public abstract class NumericFunction implements Function {
} }
/** /**
* @throws EvaluationException (#NUM!) if <tt>result</tt> is <tt>NaN</tt> or <tt>Infinity</tt> * @throws EvaluationException (#NUM!) if <tt>result</tt> is {@code NaN} or {@code Infinity}
*/ */
public static void checkValue(double result) throws EvaluationException { public static void checkValue(double result) throws EvaluationException {
if (Double.isNaN(result) || Double.isInfinite(result)) { if (Double.isNaN(result) || Double.isInfinite(result)) {
@ -62,432 +61,179 @@ public abstract class NumericFunction implements Function {
protected abstract double eval(ValueEval[] args, int srcCellRow, int srcCellCol) throws EvaluationException; protected abstract double eval(ValueEval[] args, int srcCellRow, int srcCellCol) throws EvaluationException;
/* -------------------------------------------------------------------------- */ public static final Function ABS = oneDouble(Math::abs);
// intermediate sub-classes (one-arg, two-arg and multi-arg) public static final Function ACOS = oneDouble(Math::acos);
public static final Function ACOSH = oneDouble(MathX::acosh);
public static final Function ASIN = oneDouble(Math::asin);
public static final Function ASINH = oneDouble(MathX::asinh);
public static final Function ATAN = oneDouble(Math::atan);
public static final Function ATANH = oneDouble(MathX::atanh);
public static final Function COS = oneDouble(Math::cos);
public static final Function COSH = oneDouble(MathX::cosh);
public static final Function DEGREES = oneDouble(Math::toDegrees);
public static final Function DOLLAR = NumericFunction::evaluateDollar;
public static abstract class OneArg extends Fixed1ArgFunction { private static ValueEval evaluateDollar(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
protected OneArg() { if (args.length != 1 && args.length != 2) {
// no fields to initialise return ErrorEval.VALUE_INVALID;
} }
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { try {
double result; double val = singleOperandEvaluate(args[0], srcRowIndex, srcColumnIndex);
try { double d1 = args.length == 1 ? 2.0 : singleOperandEvaluate(args[1], srcRowIndex, srcColumnIndex);
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);
}
double d = singleOperandEvaluate(args[0], srcCellRow, srcCellCol);
return evaluate(d);
}
protected abstract double evaluate(double d) throws EvaluationException;
}
public static abstract class TwoArg extends Fixed2ArgFunction {
protected TwoArg() {
// no fields to initialise
}
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
double result;
try {
double d0 = singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
double d1 = singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex);
result = evaluate(d0, d1);
checkValue(result);
} catch (EvaluationException e) {
return e.getErrorEval();
}
return new NumberEval(result);
}
protected abstract double evaluate(double d0, double d1) throws EvaluationException;
}
/* -------------------------------------------------------------------------- */
public static final Function ABS = new OneArg() {
protected double evaluate(double d) {
return Math.abs(d);
}
};
public static final Function ACOS = new OneArg() {
protected double evaluate(double d) {
return Math.acos(d);
}
};
public static final Function ACOSH = new OneArg() {
protected double evaluate(double d) {
return MathX.acosh(d);
}
};
public static final Function ASIN = new OneArg() {
protected double evaluate(double d) {
return Math.asin(d);
}
};
public static final Function ASINH = new OneArg() {
protected double evaluate(double d) {
return MathX.asinh(d);
}
};
public static final Function ATAN = new OneArg() {
protected double evaluate(double d) {
return Math.atan(d);
}
};
public static final Function ATANH = new OneArg() {
protected double evaluate(double d) {
return MathX.atanh(d);
}
};
public static final Function COS = new OneArg() {
protected double evaluate(double d) {
return Math.cos(d);
}
};
public static final Function COSH = new OneArg() {
protected double evaluate(double d) {
return MathX.cosh(d);
}
};
public static final Function DEGREES = new OneArg() {
protected double evaluate(double d) {
return Math.toDegrees(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 // second arg converts to int by truncating toward zero
int nPlaces = (int)d1; int nPlaces = (int)d1;
if (nPlaces > 127) { if (nPlaces > 127) {
return ErrorEval.VALUE_INVALID; return VALUE_INVALID;
} }
// TODO - DOLLAR() function impl is NQR // TODO - DOLLAR() function impl is NQR
// result should be StringEval, with leading '$' and thousands separators // result should be StringEval, with leading '$' and thousands separators
// current junits are asserting incorrect behaviour // current junits are asserting incorrect behaviour
return new NumberEval(val); return new NumberEval(val);
} }catch (EvaluationException e) {
}; return e.getErrorEval();
public static final Function EXP = new OneArg() {
protected double evaluate(double d) {
return Math.pow(Math.E, d);
}
};
public static final Function FACT = new OneArg() {
protected double evaluate(double d) {
return MathX.factorial((int)d);
}
};
public static final Function INT = new OneArg() {
protected double evaluate(double d) {
return Math.round(d-0.5);
}
};
public static final Function LN = new OneArg() {
protected double evaluate(double d) {
return Math.log(d);
}
};
public static final Function LOG10 = new OneArg() {
protected double evaluate(double d) {
return Math.log(d) / LOG_10_TO_BASE_e;
}
};
public static final Function RADIANS = new OneArg() {
protected double evaluate(double d) {
return Math.toRadians(d);
}
};
public static final Function SIGN = new OneArg() {
protected double evaluate(double d) {
return MathX.sign(d);
}
};
public static final Function SIN = new OneArg() {
protected double evaluate(double d) {
return Math.sin(d);
}
};
public static final Function SINH = new OneArg() {
protected double evaluate(double d) {
return MathX.sinh(d);
}
};
public static final Function SQRT = new OneArg() {
protected double evaluate(double d) {
return Math.sqrt(d);
}
};
public static final Function TAN = new OneArg() {
protected double evaluate(double d) {
return Math.tan(d);
}
};
public static final Function TANH = new OneArg() {
protected double evaluate(double d) {
return MathX.tanh(d);
}
};
/* -------------------------------------------------------------------------- */
public static final Function ATAN2 = new TwoArg() {
protected double evaluate(double d0, double d1) throws EvaluationException {
if (d0 == ZERO && d1 == ZERO) {
throw new EvaluationException(ErrorEval.DIV_ZERO);
}
return Math.atan2(d1, d0);
}
};
public static final Function CEILING = new TwoArg() {
protected double evaluate(double d0, double d1) {
return MathX.ceiling(d0, d1);
}
};
public static final Function COMBIN = new TwoArg() {
protected double evaluate(double d0, double d1) throws EvaluationException {
if (d0 > Integer.MAX_VALUE || d1 > Integer.MAX_VALUE) {
throw new EvaluationException(ErrorEval.NUM_ERROR);
}
return MathX.nChooseK((int) d0, (int) d1);
}
};
public static final Function FLOOR = new TwoArg() {
protected double evaluate(double d0, double d1) throws EvaluationException {
if (d1 == ZERO) {
if (d0 == ZERO) {
return ZERO;
}
throw new EvaluationException(ErrorEval.DIV_ZERO);
}
return MathX.floor(d0, d1);
}
};
public static final Function MOD = new TwoArg() {
protected double evaluate(double d0, double d1) throws EvaluationException {
if (d1 == ZERO) {
throw new EvaluationException(ErrorEval.DIV_ZERO);
}
return MathX.mod(d0, d1);
}
};
public static final Function POWER = new TwoArg() {
protected double evaluate(double d0, double d1) {
return Math.pow(d0, d1);
}
};
public static final Function ROUND = new TwoArg() {
protected double evaluate(double d0, double d1) {
return MathX.round(d0, (int)d1);
}
};
public static final Function ROUNDDOWN = new TwoArg() {
protected double evaluate(double d0, double d1) {
return MathX.roundDown(d0, (int)d1);
}
};
public static final Function ROUNDUP = new TwoArg() {
protected double evaluate(double d0, double d1) {
return MathX.roundUp(d0, (int)d1);
}
};
static final NumberEval TRUNC_ARG2_DEFAULT = new NumberEval(0);
public static final Function TRUNC = new Var1or2ArgFunction() {
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
return evaluate(srcRowIndex, srcColumnIndex, arg0, TRUNC_ARG2_DEFAULT);
}
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 = MathX.roundDown(d0, (int)d1);
checkValue(result);
}catch (EvaluationException e) {
return e.getErrorEval();
}
return new NumberEval(result);
}
};
/* -------------------------------------------------------------------------- */
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);
if (Double.compare(d1, Math.E) == 0) {
result = logE;
} else {
result = logE / Math.log(d1);
}
NumericFunction.checkValue(result);
} catch (EvaluationException e) {
return e.getErrorEval();
}
return new NumberEval(result);
} }
} }
public static final Function LOG = new Log(); public static final Function EXP = oneDouble(d -> Math.pow(Math.E, d));
public static final Function FACT = oneDouble(MathX::factorial);
public static final Function INT = oneDouble(d -> Math.round(d-0.5));
public static final Function LN = oneDouble(Math::log);
public static final Function LOG10 = oneDouble(d -> Math.log(d) / LOG_10_TO_BASE_e);
public static final Function RADIANS = oneDouble(Math::toRadians);
public static final Function SIGN = oneDouble(MathX::sign);
public static final Function SIN = oneDouble(Math::sin);
public static final Function SINH = oneDouble(MathX::sinh);
public static final Function SQRT = oneDouble(Math::sqrt);
public static final Function TAN = oneDouble(Math::tan);
public static final Function TANH = oneDouble(MathX::tanh);
/* -------------------------------------------------------------------------- */
public static final Function ATAN2 = twoDouble((d0, d1) ->
(d0 == ZERO && d1 == ZERO) ? ErrorEval.DIV_ZERO : Math.atan2(d1, d0)
);
public static final Function CEILING = twoDouble(MathX::ceiling);
public static final Function COMBIN = twoDouble((d0, d1) ->
(d0 > Integer.MAX_VALUE || d1 > Integer.MAX_VALUE) ? ErrorEval.NUM_ERROR : MathX.nChooseK((int) d0, (int) d1));
public static final Function FLOOR = twoDouble((d0, d1) ->
(d1 == ZERO) ? (d0 == ZERO ? ZERO : ErrorEval.DIV_ZERO) : MathX.floor(d0, d1));
public static final Function MOD = twoDouble((d0, d1) ->
(d1 == ZERO) ? ErrorEval.DIV_ZERO : MathX.mod(d0, d1));
public static final Function POWER = twoDouble(Math::pow);
public static final Function ROUND = twoDouble(MathX::round);
public static final Function ROUNDDOWN = twoDouble(MathX::roundDown);
public static final Function ROUNDUP = twoDouble(MathX::roundUp);
public static final Function TRUNC = NumericFunction::evaluateTrunc;
private static ValueEval evaluateTrunc(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
if (args.length != 1 && args.length != 2) {
return ErrorEval.VALUE_INVALID;
}
try {
double d0 = singleOperandEvaluate(args[0], srcRowIndex, srcColumnIndex);
double d1 = args.length == 1 ? 0 : singleOperandEvaluate(args[1], srcRowIndex, srcColumnIndex);
double result = MathX.roundDown(d0, d1);
checkValue(result);
return new NumberEval(result);
}catch (EvaluationException e) {
return e.getErrorEval();
}
}
/* -------------------------------------------------------------------------- */
public static final Function LOG = Log::evaluate;
static final NumberEval PI_EVAL = new NumberEval(Math.PI); static final NumberEval PI_EVAL = new NumberEval(Math.PI);
public static final Function PI = new Fixed0ArgFunction() { public static final Function PI = NumericFunction::evaluatePI;
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) {
return PI_EVAL; private static ValueEval evaluatePI(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
return (args.length != 0) ? ErrorEval.VALUE_INVALID : PI_EVAL;
}
public static final Function RAND = NumericFunction::evaluateRand;
private static ValueEval evaluateRand(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
return (args.length != 0) ? ErrorEval.VALUE_INVALID : new NumberEval(Math.random());
}
public static final Function POISSON = Poisson::evaluate;
public static final Function ODD = oneDouble(NumericFunction::evaluateOdd);
private static double evaluateOdd(double d) {
if (d==0) {
return 1;
} }
}; double dpm = Math.abs(d)+1;
public static final Function RAND = new Fixed0ArgFunction() { long x = ((long) dpm) & PARITY_MASK;
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { return MathX.sign(d) * ((Double.compare(x, dpm) == 0) ? x-1 : x+1);
return new NumberEval(Math.random()); }
public static final Function EVEN = oneDouble(NumericFunction::evaluateEven);
private static double evaluateEven(double d) {
if (d==0) {
return 0;
} }
};
public static final Function POISSON = new Fixed3ArgFunction() {
private static final double DEFAULT_RETURN_RESULT =1; double dpm = Math.abs(d);
long x = ((long) dpm) & PARITY_MASK;
/** return MathX.sign(d) * ((Double.compare(x, dpm) == 0) ? x : (x + 2));
* This checks is x = 0 and the mean = 0. }
* Excel currently returns the value 1 where as the
* maths common implementation will error.
* @param x The number.
* @param mean The mean.
* @return If a default value should be returned.
*/
private boolean isDefaultResult(double x, double mean) {
if ( x == 0 && mean == 0 ) {
return true;
}
return false;
}
private boolean checkArgument(double aDouble) throws EvaluationException {
NumericFunction.checkValue(aDouble);
// make sure that the number is positive
if (aDouble < 0) {
throw new EvaluationException(ErrorEval.NUM_ERROR);
}
return true;
}
private double probability(int k, double lambda) {
return Math.pow(lambda, k) * Math.exp(-lambda) / factorial(k);
}
private double cumulativeProbability(int x, double lambda) {
double result = 0;
for(int k = 0; k <= x; k++){
result += probability(k, lambda);
}
return result;
}
/** All long-representable factorials */
private final long[] FACTORIALS = new long[] {
1l, 1l, 2l,
6l, 24l, 120l,
720l, 5040l, 40320l,
362880l, 3628800l, 39916800l,
479001600l, 6227020800l, 87178291200l,
1307674368000l, 20922789888000l, 355687428096000l,
6402373705728000l, 121645100408832000l, 2432902008176640000l };
public long factorial(final int n) { private interface OneDoubleIf {
if (n < 0 || n > 20) { double apply(double d);
throw new IllegalArgumentException("Valid argument should be in the range [0..20]"); }
}
return FACTORIALS[n];
}
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, ValueEval arg2) {
// arguments/result for this function
double mean=0;
double x=0;
boolean cumulative = ((BoolEval)arg2).getBooleanValue();
double result=0;
try {
x = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
mean = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex);
// check for default result : excel implementation for 0,0
// is different to Math Common.
if (isDefaultResult(x,mean)) {
return new NumberEval(DEFAULT_RETURN_RESULT);
}
// check the arguments : as per excel function def
checkArgument(x);
checkArgument(mean);
// truncate x : as per excel function def
if ( cumulative ) {
result = cumulativeProbability((int)x, mean);
} else {
result = probability((int)x, mean);
}
// check the result
NumericFunction.checkValue(result);
private static Function oneDouble(OneDoubleIf doubleFun) {
return (args, srcCellRow, srcCellCol) -> {
if (args.length != 1) {
return VALUE_INVALID;
}
try {
double d = singleOperandEvaluate(args[0], srcCellRow, srcCellCol);
double res = doubleFun.apply(d);
return (Double.isNaN(res) || Double.isInfinite(res)) ? ErrorEval.NUM_ERROR : new NumberEval(res);
} catch (EvaluationException e) { } catch (EvaluationException e) {
return e.getErrorEval(); return e.getErrorEval();
} }
};
}
return new NumberEval(result); private interface TwoDoubleIf {
Object apply(double d1, double d2);
}
} private static Function twoDouble(TwoDoubleIf doubleFun) {
}; return (args, srcCellRow, srcCellCol) -> {
if (args.length != 2) {
return VALUE_INVALID;
}
try {
double d1 = singleOperandEvaluate(args[0], srcCellRow, srcCellCol);
double d2 = singleOperandEvaluate(args[1], srcCellRow, srcCellCol);
Object res = doubleFun.apply(d1, d2);
if (res instanceof ErrorEval) {
return (ErrorEval)res;
}
assert(res instanceof Double);
double d = (Double)res;
return (Double.isNaN(d) || Double.isInfinite(d)) ? ErrorEval.NUM_ERROR : new NumberEval(d);
} catch (EvaluationException e) {
return e.getErrorEval();
}
};
}
} }

View File

@ -1,39 +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.ss.formula.functions;
/**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*
*/
public final class Odd extends NumericFunction.OneArg {
private static final long PARITY_MASK = 0xFFFFFFFFFFFFFFFEL;
protected double evaluate(double d) {
if (d==0) {
return 1;
}
return (d>0) ? calcOdd(d) : -calcOdd(-d);
}
private static long calcOdd(double d) {
double dpm1 = d+1;
long x = ((long) dpm1) & PARITY_MASK;
return ( Double.compare(x, dpm1) == 0 ) ? x-1 : x+1;
}
}

View File

@ -0,0 +1,115 @@
/* ====================================================================
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.ss.formula.functions;
import org.apache.poi.ss.formula.eval.BoolEval;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval;
public class Poisson {
private static final double DEFAULT_RETURN_RESULT =1;
/** All long-representable factorials */
private static final long[] FACTORIALS = {
1L, 1L, 2L,
6L, 24L, 120L,
720L, 5040L, 40320L,
362880L, 3628800L, 39916800L,
479001600L, 6227020800L, 87178291200L,
1307674368000L, 20922789888000L, 355687428096000L,
6402373705728000L, 121645100408832000L, 2432902008176640000L };
/**
* This checks is x = 0 and the mean = 0.
* Excel currently returns the value 1 where as the
* maths common implementation will error.
* @param x The number.
* @param mean The mean.
* @return If a default value should be returned.
*/
private static boolean isDefaultResult(double x, double mean) {
return x == 0 && mean == 0;
}
private static void checkArgument(double aDouble) throws EvaluationException {
NumericFunction.checkValue(aDouble);
// make sure that the number is positive
if (aDouble < 0) {
throw new EvaluationException(ErrorEval.NUM_ERROR);
}
}
private static double probability(int k, double lambda) {
return Math.pow(lambda, k) * Math.exp(-lambda) / factorial(k);
}
private static double cumulativeProbability(int x, double lambda) {
double result = 0;
for(int k = 0; k <= x; k++){
result += probability(k, lambda);
}
return result;
}
private static long factorial(final int n) {
if (n < 0 || n > 20) {
throw new IllegalArgumentException("Valid argument should be in the range [0..20]");
}
return FACTORIALS[n];
}
public static ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
if (args.length != 3) {
return ErrorEval.VALUE_INVALID;
}
ValueEval arg0 = args[0];
ValueEval arg1 = args[1];
ValueEval arg2 = args[2];
try {
// arguments/result for this function
double x = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex);
double mean = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex);
// check for default result : excel implementation for 0,0
// is different to Math Common.
if (isDefaultResult(x,mean)) {
return new NumberEval(DEFAULT_RETURN_RESULT);
}
// check the arguments : as per excel function def
checkArgument(x);
checkArgument(mean);
// truncate x : as per excel function def
boolean cumulative = ((BoolEval)arg2).getBooleanValue();
double result = cumulative ? cumulativeProbability((int) x, mean) : probability((int) x, mean);
// check the result
NumericFunction.checkValue(result);
return new NumberEval(result);
} catch (EvaluationException e) {
return e.getErrorEval();
}
}
}

View File

@ -26,18 +26,19 @@ import org.apache.poi.ss.formula.eval.ValueEval;
/** /**
* Implementation for the Excel function ROW * Implementation for the Excel function ROW
*/ */
public final class RowFunc implements Function0Arg, Function1Arg { public final class RowFunc {
public static ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
if (args.length > 1) {
return 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; int rnum;
if (args.length == 0) {
if (arg0 instanceof AreaEval) { rnum = srcRowIndex;
rnum = ((AreaEval) arg0).getFirstRow(); } else if (args[0] instanceof AreaEval) {
} else if (arg0 instanceof RefEval) { rnum = ((AreaEval) args[0]).getFirstRow();
rnum = ((RefEval) arg0).getRow(); } else if (args[0] instanceof RefEval) {
rnum = ((RefEval) args[0]).getRow();
} else { } else {
// anything else is not valid argument // anything else is not valid argument
return ErrorEval.VALUE_INVALID; return ErrorEval.VALUE_INVALID;
@ -45,13 +46,4 @@ public final class RowFunc implements Function0Arg, Function1Arg {
return new NumberEval(rnum + 1.); 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;
}
} }

View File

@ -19,6 +19,7 @@ package org.apache.poi.ss.formula.functions;
import java.util.Calendar; import java.util.Calendar;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.NumberEval; import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.DateUtil;
@ -27,8 +28,11 @@ import org.apache.poi.util.LocaleUtil;
/** /**
* Implementation of Excel TODAY() Function<br> * Implementation of Excel TODAY() Function<br>
*/ */
public final class Today extends Fixed0ArgFunction { public final class Today {
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { public static ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
if (args.length != 0) {
return ErrorEval.VALUE_INVALID;
}
Calendar now = LocaleUtil.getLocaleCalendar(); Calendar now = LocaleUtil.getLocaleCalendar();
now.clear(Calendar.HOUR); now.clear(Calendar.HOUR);
now.set(Calendar.HOUR_OF_DAY,0); now.set(Calendar.HOUR_OF_DAY,0);

View File

@ -24,14 +24,12 @@ import org.junit.jupiter.api.Test;
/** /**
* Tests for ROW(), ROWS(), COLUMN(), COLUMNS() * Tests for ROW(), ROWS(), COLUMN(), COLUMNS()
*
* @author Josh Micich
*/ */
final class TestRowCol { final class TestRowCol {
@Test @Test
void testCol() { void testCol() {
Function target = new Column(); Function target = Column::evaluate;
{ {
ValueEval[] args = { EvalFactory.createRefEval("C5"), }; ValueEval[] args = { EvalFactory.createRefEval("C5"), };
double actual = NumericFunctionInvoker.invoke(target, args); double actual = NumericFunctionInvoker.invoke(target, args);
@ -46,7 +44,7 @@ final class TestRowCol {
@Test @Test
void testRow() { void testRow() {
Function target = new RowFunc(); Function target = RowFunc::evaluate;
{ {
ValueEval[] args = { EvalFactory.createRefEval("C5"), }; ValueEval[] args = { EvalFactory.createRefEval("C5"), };
double actual = NumericFunctionInvoker.invoke(target, args); double actual = NumericFunctionInvoker.invoke(target, args);