From: Josh Micich Date: Sun, 22 Nov 2009 07:29:40 +0000 (+0000) Subject: added fixed arg function interfaces, converted some functions X-Git-Tag: REL_3_6~37 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=b095f1d02a3026762e0bb09018c800774ca285cc;p=poi.git added fixed arg function interfaces, converted some functions git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@883045 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/ConcatEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/ConcatEval.java index 0db4994b59..53d8c7bc29 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/ConcatEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/ConcatEval.java @@ -17,12 +17,13 @@ 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(); @@ -30,29 +31,30 @@ public final class ConcatEval implements Function { // 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() + ")"); + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/IntersectionEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/IntersectionEval.java index b208bcd647..e30df36f59 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/IntersectionEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/IntersectionEval.java @@ -17,12 +17,13 @@ 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(); @@ -30,14 +31,11 @@ public final class IntersectionEval implements Function { // 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; diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/PercentEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/PercentEval.java index 0d509cc438..93db027b30 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/PercentEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/PercentEval.java @@ -17,6 +17,7 @@ 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; @@ -24,7 +25,7 @@ import org.apache.poi.hssf.record.formula.functions.Function; * Implementation of Excel formula token '%'.

* @author Josh Micich */ -public final class PercentEval implements Function { +public final class PercentEval extends Fixed1ArgFunction { public static final Function instance = new PercentEval(); @@ -32,13 +33,10 @@ public final class PercentEval implements Function { // 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(); diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/RangeEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/RangeEval.java index bd821f0acb..6a8186c7b7 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/RangeEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/RangeEval.java @@ -17,6 +17,7 @@ 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; @@ -24,7 +25,7 @@ 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(); @@ -32,14 +33,11 @@ public final class RangeEval implements Function { // 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(); diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/RelationalOperationEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/RelationalOperationEval.java index 35cf5b4347..63b68c441a 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/RelationalOperationEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/RelationalOperationEval.java @@ -17,6 +17,7 @@ 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; @@ -25,7 +26,7 @@ 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 true or false @@ -55,16 +56,13 @@ public abstract class RelationalOperationEval implements Function { * Blank < Positive numbers * */ - 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(); } diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/TwoOperandNumericOperation.java b/src/java/org/apache/poi/hssf/record/formula/eval/TwoOperandNumericOperation.java index 1584e17bba..7e6ac88364 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/TwoOperandNumericOperation.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/TwoOperandNumericOperation.java @@ -17,23 +17,23 @@ 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 '^' @@ -49,6 +49,7 @@ public abstract class TwoOperandNumericOperation implements Function { } return new NumberEval(result); } + protected abstract double evaluate(double d0, double d1) throws EvaluationException; public static final Function AddEval = new TwoOperandNumericOperation() { diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/UnaryMinusEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/UnaryMinusEval.java index 0d87ab036a..ba5f197dce 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/UnaryMinusEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/UnaryMinusEval.java @@ -17,14 +17,13 @@ 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(); @@ -32,13 +31,10 @@ public final class UnaryMinusEval implements Function { // 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(); diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/UnaryPlusEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/UnaryPlusEval.java index e2b137b4b3..b6f32e9b61 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/UnaryPlusEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/UnaryPlusEval.java @@ -17,14 +17,14 @@ 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(); @@ -32,13 +32,10 @@ public final class UnaryPlusEval implements Function { // 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! diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/CalendarFieldFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/CalendarFieldFunction.java index a4c445aa55..3261f209be 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/CalendarFieldFunction.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/CalendarFieldFunction.java @@ -34,7 +34,7 @@ import org.apache.poi.hssf.usermodel.HSSFDateUtil; * * @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); @@ -48,14 +48,10 @@ public final class CalendarFieldFunction implements Function { _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(); diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Column.java b/src/java/org/apache/poi/hssf/record/formula/functions/Column.java index e984cc2c7b..02a34b4e27 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Column.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Column.java @@ -23,39 +23,32 @@ 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; -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; } - - } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Columns.java b/src/java/org/apache/poi/hssf/record/formula/functions/Columns.java index ca0e97f305..0ef7e06324 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Columns.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Columns.java @@ -28,27 +28,14 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval; * * @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; diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Countblank.java b/src/java/org/apache/poi/hssf/record/formula/functions/Countblank.java index 473976e330..a668225da4 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Countblank.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Countblank.java @@ -19,7 +19,6 @@ 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.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; @@ -36,17 +35,11 @@ import org.apache.poi.hssf.record.formula.functions.CountUtils.I_MatchPredicate; * * @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) { diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Countif.java b/src/java/org/apache/poi/hssf/record/formula/functions/Countif.java index 2b45debec9..77fdf9bfc7 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Countif.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Countif.java @@ -44,7 +44,7 @@ import org.apache.poi.ss.usermodel.ErrorConstants; * * @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; @@ -400,23 +400,14 @@ public final class Countif implements Function { } } - 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); } /** diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/DateFunc.java b/src/java/org/apache/poi/hssf/record/formula/functions/DateFunc.java index 8c06837168..ca6df7ae23 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/DateFunc.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/DateFunc.java @@ -22,23 +22,37 @@ import java.util.GregorianCalendar; 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); diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Errortype.java b/src/java/org/apache/poi/hssf/record/formula/functions/Errortype.java index f96f3b2d8c..72de76273c 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Errortype.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Errortype.java @@ -50,12 +50,12 @@ import org.apache.poi.hssf.usermodel.HSSFErrorConstants; * * @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()); diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Fixed0ArgFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/Fixed0ArgFunction.java new file mode 100644 index 0000000000..ff3207b319 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Fixed0ArgFunction.java @@ -0,0 +1,35 @@ +/* ==================================================================== + 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); + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Fixed1ArgFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/Fixed1ArgFunction.java new file mode 100644 index 0000000000..6a12d9efc8 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Fixed1ArgFunction.java @@ -0,0 +1,35 @@ +/* ==================================================================== + 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]); + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Fixed2ArgFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/Fixed2ArgFunction.java new file mode 100644 index 0000000000..7695920b97 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Fixed2ArgFunction.java @@ -0,0 +1,35 @@ +/* ==================================================================== + 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]); + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Fixed3ArgFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/Fixed3ArgFunction.java new file mode 100644 index 0000000000..d4488ab7b7 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Fixed3ArgFunction.java @@ -0,0 +1,35 @@ +/* ==================================================================== + 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]); + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Fixed4ArgFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/Fixed4ArgFunction.java new file mode 100644 index 0000000000..5588714972 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Fixed4ArgFunction.java @@ -0,0 +1,35 @@ +/* ==================================================================== + 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]); + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Function0Arg.java b/src/java/org/apache/poi/hssf/record/formula/functions/Function0Arg.java new file mode 100644 index 0000000000..c61a87e0a2 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Function0Arg.java @@ -0,0 +1,32 @@ +/* ==================================================================== + 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); +} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Function1Arg.java b/src/java/org/apache/poi/hssf/record/formula/functions/Function1Arg.java new file mode 100644 index 0000000000..42007fa4cc --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Function1Arg.java @@ -0,0 +1,32 @@ +/* ==================================================================== + 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); +} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Function2Arg.java b/src/java/org/apache/poi/hssf/record/formula/functions/Function2Arg.java new file mode 100644 index 0000000000..b0ef472859 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Function2Arg.java @@ -0,0 +1,32 @@ +/* ==================================================================== + 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); +} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Function3Arg.java b/src/java/org/apache/poi/hssf/record/formula/functions/Function3Arg.java new file mode 100644 index 0000000000..7ee32b81c2 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Function3Arg.java @@ -0,0 +1,32 @@ +/* ==================================================================== + 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); +} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Function4Arg.java b/src/java/org/apache/poi/hssf/record/formula/functions/Function4Arg.java new file mode 100644 index 0000000000..7089432f75 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Function4Arg.java @@ -0,0 +1,32 @@ +/* ==================================================================== + 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); +} diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Na.java b/src/java/org/apache/poi/hssf/record/formula/functions/Na.java index e1f9fa612a..c66080b9d5 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Na.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Na.java @@ -25,10 +25,9 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval; * * @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; } - } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Now.java b/src/java/org/apache/poi/hssf/record/formula/functions/Now.java index a56bf27052..766f5694d4 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Now.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Now.java @@ -19,7 +19,6 @@ package org.apache.poi.hssf.record.formula.functions; 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; @@ -29,13 +28,9 @@ 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)); } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/NumericFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/NumericFunction.java index 01ef88c3c6..24b0ae2692 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/NumericFunction.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/NumericFunction.java @@ -39,7 +39,10 @@ public abstract class NumericFunction implements Function { return result; } - private static final void checkValue(double result) throws EvaluationException { + /** + * @throws EvaluationException (#NUM!) if result is NaN or Infinity + */ + static final void checkValue(double result) throws EvaluationException { if (Double.isNaN(result) || Double.isInfinite(result)) { throw new EvaluationException(ErrorEval.NUM_ERROR); } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Replace.java b/src/java/org/apache/poi/hssf/record/formula/functions/Replace.java index 2298656e7c..f2af838f91 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Replace.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Replace.java @@ -37,18 +37,23 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval; * * @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; diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Row.java b/src/java/org/apache/poi/hssf/record/formula/functions/Row.java index d0d0acb2c5..718ab7c27a 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Row.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Row.java @@ -23,39 +23,33 @@ 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; -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; } } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Rows.java b/src/java/org/apache/poi/hssf/record/formula/functions/Rows.java index fb1b025342..dfde69ae31 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Rows.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Rows.java @@ -28,27 +28,14 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval; * * @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; diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/T.java b/src/java/org/apache/poi/hssf/record/formula/functions/T.java index e4b43c0d1c..70869e462e 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/T.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/T.java @@ -30,16 +30,10 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval; * 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) { diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Time.java b/src/java/org/apache/poi/hssf/record/formula/functions/Time.java index 926ab3fed1..85f474028a 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Time.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Time.java @@ -29,7 +29,7 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval; * * 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; @@ -37,25 +37,23 @@ public final class Time implements Function { 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. diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Today.java b/src/java/org/apache/poi/hssf/record/formula/functions/Today.java index f6705aae10..f50ea73c1a 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Today.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Today.java @@ -20,7 +20,6 @@ package org.apache.poi.hssf.record.formula.functions; 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; @@ -30,12 +29,9 @@ 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); @@ -43,4 +39,3 @@ public final class Today implements Function { return new NumberEval(HSSFDateUtil.getExcelDate(now.getTime())); } } - diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Value.java b/src/java/org/apache/poi/hssf/record/formula/functions/Value.java index 8067e742e6..951f19cb40 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Value.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Value.java @@ -35,19 +35,16 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval; * * @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(); } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Var2or3ArgFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/Var2or3ArgFunction.java index 9f5483fa05..4928425f99 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Var2or3ArgFunction.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Var2or3ArgFunction.java @@ -26,7 +26,7 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval; * * @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) { @@ -37,10 +37,4 @@ abstract class Var2or3ArgFunction implements Function { } 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); } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java index 21c43d4855..e2c919489b 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java @@ -27,9 +27,8 @@ import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector; /** * @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; @@ -96,15 +95,12 @@ public abstract class XYNumericFunction implements Function { */ 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;