You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by fa...@apache.org on 2021/05/22 20:56:49 UTC

svn commit: r1890120 [21/43] - in /poi/trunk/poi/src: main/java/org/apache/poi/ main/java/org/apache/poi/ddf/ main/java/org/apache/poi/extractor/ main/java/org/apache/poi/hpsf/ main/java/org/apache/poi/hssf/ main/java/org/apache/poi/hssf/dev/ main/java...

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/NumericFunction.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/NumericFunction.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/NumericFunction.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/NumericFunction.java Sat May 22 20:56:44 2021
@@ -23,218 +23,218 @@ import org.apache.poi.ss.formula.eval.*;
 
 public abstract class NumericFunction implements Function {
 
-	private static final double ZERO = 0.0;
-	private static final double TEN = 10.0;
-	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 {
-		if (arg == null) {
-			throw new IllegalArgumentException("arg must not be null");
-		}
-		ValueEval ve = OperandResolver.getSingleValue(arg, srcRowIndex, srcColumnIndex);
-		double result = OperandResolver.coerceValueToDouble(ve);
-		checkValue(result);
-		return result;
-	}
-
-	/**
-	 * @throws EvaluationException (#NUM!) if {@code result} is {@code NaN} or {@code Infinity}
-	 */
-	public static void checkValue(double result) throws EvaluationException {
-		if (Double.isNaN(result) || Double.isInfinite(result)) {
-			throw new EvaluationException(ErrorEval.NUM_ERROR);
-		}
-	}
-
-	@Override
-	public final ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
-		double result;
-		try {
-			result = eval(args, srcCellRow, srcCellCol);
-			checkValue(result);
-		} catch (EvaluationException e) {
-			return e.getErrorEval();
-		}
-		return new NumberEval(result);
-	}
-
-	protected abstract double eval(ValueEval[] args, int srcCellRow, int srcCellCol) throws EvaluationException;
-
-	public static final Function ABS = oneDouble(Math::abs);
-	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;
-
-	private static ValueEval evaluateDollar(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
-		if (args.length != 1 && args.length != 2) {
-			return ErrorEval.VALUE_INVALID;
-		}
-		try {
-			double val = singleOperandEvaluate(args[0], srcRowIndex, srcColumnIndex);
-			double d1 = args.length == 1 ? 2.0 : singleOperandEvaluate(args[1], srcRowIndex, srcColumnIndex);
-
-			// second arg converts to int by truncating toward zero
-			int nPlaces = (int)d1;
-
-			if (nPlaces > 127) {
-				return VALUE_INVALID;
-			}
-
-			// TODO - DOLLAR() function impl is NQR
-			// result should be StringEval, with leading '$' and thousands separators
-			// current junits are asserting incorrect behaviour
-			return new NumberEval(val);
-		}catch (EvaluationException e) {
-			return e.getErrorEval();
-		}
-	}
-
-	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);
-	public static final Function PI = NumericFunction::evaluatePI;
-
-	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;
-		long x = ((long) dpm) & PARITY_MASK;
-		return MathX.sign(d) * ((Double.compare(x, dpm) == 0) ? x-1 : x+1);
-	}
-
-
-	public static final Function EVEN = oneDouble(NumericFunction::evaluateEven);
-
-	private static double evaluateEven(double d) {
-		if (d==0) {
-			return 0;
-		}
-
-		double dpm = Math.abs(d);
-		long x = ((long) dpm) & PARITY_MASK;
-		return MathX.sign(d) * ((Double.compare(x, dpm) == 0) ? x : (x + 2));
-	}
-
-
-	private interface OneDoubleIf {
-		double apply(double d);
-	}
-
-	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) {
-				return e.getErrorEval();
-			}
-		};
-	}
-
-	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();
-			}
-		};
-	}
+    private static final double ZERO = 0.0;
+    private static final double TEN = 10.0;
+    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 {
+        if (arg == null) {
+            throw new IllegalArgumentException("arg must not be null");
+        }
+        ValueEval ve = OperandResolver.getSingleValue(arg, srcRowIndex, srcColumnIndex);
+        double result = OperandResolver.coerceValueToDouble(ve);
+        checkValue(result);
+        return result;
+    }
+
+    /**
+     * @throws EvaluationException (#NUM!) if {@code result} is {@code NaN} or {@code Infinity}
+     */
+    public static void checkValue(double result) throws EvaluationException {
+        if (Double.isNaN(result) || Double.isInfinite(result)) {
+            throw new EvaluationException(ErrorEval.NUM_ERROR);
+        }
+    }
+
+    @Override
+    public final ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
+        double result;
+        try {
+            result = eval(args, srcCellRow, srcCellCol);
+            checkValue(result);
+        } catch (EvaluationException e) {
+            return e.getErrorEval();
+        }
+        return new NumberEval(result);
+    }
+
+    protected abstract double eval(ValueEval[] args, int srcCellRow, int srcCellCol) throws EvaluationException;
+
+    public static final Function ABS = oneDouble(Math::abs);
+    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;
+
+    private static ValueEval evaluateDollar(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+        if (args.length != 1 && args.length != 2) {
+            return ErrorEval.VALUE_INVALID;
+        }
+        try {
+            double val = singleOperandEvaluate(args[0], srcRowIndex, srcColumnIndex);
+            double d1 = args.length == 1 ? 2.0 : singleOperandEvaluate(args[1], srcRowIndex, srcColumnIndex);
+
+            // second arg converts to int by truncating toward zero
+            int nPlaces = (int)d1;
+
+            if (nPlaces > 127) {
+                return VALUE_INVALID;
+            }
+
+            // TODO - DOLLAR() function impl is NQR
+            // result should be StringEval, with leading '$' and thousands separators
+            // current junits are asserting incorrect behaviour
+            return new NumberEval(val);
+        }catch (EvaluationException e) {
+            return e.getErrorEval();
+        }
+    }
+
+    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);
+    public static final Function PI = NumericFunction::evaluatePI;
+
+    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;
+        long x = ((long) dpm) & PARITY_MASK;
+        return MathX.sign(d) * ((Double.compare(x, dpm) == 0) ? x-1 : x+1);
+    }
+
+
+    public static final Function EVEN = oneDouble(NumericFunction::evaluateEven);
+
+    private static double evaluateEven(double d) {
+        if (d==0) {
+            return 0;
+        }
+
+        double dpm = Math.abs(d);
+        long x = ((long) dpm) & PARITY_MASK;
+        return MathX.sign(d) * ((Double.compare(x, dpm) == 0) ? x : (x + 2));
+    }
+
+
+    private interface OneDoubleIf {
+        double apply(double d);
+    }
+
+    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) {
+                return e.getErrorEval();
+            }
+        };
+    }
+
+    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();
+            }
+        };
+    }
 }

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/PPMT.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/PPMT.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/PPMT.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/PPMT.java Sat May 22 20:56:44 2021
@@ -26,30 +26,30 @@ import org.apache.poi.ss.formula.eval.*;
   */
 public class PPMT extends NumericFunction {
 
-	@Override
-	public double eval(ValueEval[] args, int srcCellRow, int srcCellCol) throws EvaluationException {
+    @Override
+    public double eval(ValueEval[] args, int srcCellRow, int srcCellCol) throws EvaluationException {
 
-		if(args.length < 4)
-        		throw new EvaluationException(ErrorEval.VALUE_INVALID);
+        if(args.length < 4)
+                throw new EvaluationException(ErrorEval.VALUE_INVALID);
 
-		double result;
+        double result;
 
-		ValueEval v1 = OperandResolver.getSingleValue(args[0], srcCellRow, srcCellCol);
+        ValueEval v1 = OperandResolver.getSingleValue(args[0], srcCellRow, srcCellCol);
                 ValueEval v2 = OperandResolver.getSingleValue(args[1], srcCellRow, srcCellCol);
                 ValueEval v3 = OperandResolver.getSingleValue(args[2], srcCellRow, srcCellCol);
                 ValueEval v4 = OperandResolver.getSingleValue(args[3], srcCellRow, srcCellCol);
 
-		double interestRate = OperandResolver.coerceValueToDouble(v1);
+        double interestRate = OperandResolver.coerceValueToDouble(v1);
                 int period = OperandResolver.coerceValueToInt(v2);
                 int numberPayments = OperandResolver.coerceValueToInt(v3);
                 double PV = OperandResolver.coerceValueToDouble(v4);
 
-		result = Finance.ppmt(interestRate, period, numberPayments, PV) ;
+        result = Finance.ppmt(interestRate, period, numberPayments, PV) ;
 
-		checkValue(result);
+        checkValue(result);
 
-		return result;
-	}
+        return result;
+    }
 
 
 

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Rank.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Rank.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Rank.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Rank.java Sat May 22 20:56:44 2021
@@ -33,10 +33,10 @@ import org.apache.poi.ss.formula.eval.Va
  * Returns the rank of a number in a list of numbers. The rank of a number is its size relative to other values in a list.
 
  * Syntax:
- *	RANK(number,ref,order)
- *	   Number   is the number whose rank you want to find.
- *	   Ref	 is an array of, or a reference to, a list of numbers. Nonnumeric values in ref are ignored.
- *	   Order   is a number specifying how to rank number.
+ *  RANK(number,ref,order)
+ *     Number   is the number whose rank you want to find.
+ *     Ref   is an array of, or a reference to, a list of numbers. Nonnumeric values in ref are ignored.
+ *     Order   is a number specifying how to rank number.
 
  * If order is 0 (zero) or omitted, Microsoft Excel ranks number as if ref were a list sorted in descending order.
  * If order is any nonzero value, Microsoft Excel ranks number as if ref were a list sorted in ascending order.

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Replace.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Replace.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Replace.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Replace.java Sat May 22 20:56:44 2021
@@ -37,36 +37,36 @@ import org.apache.poi.ss.formula.eval.Va
  */
 public final class Replace extends Fixed4ArgFunction {
 
-	public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
-			ValueEval arg2, ValueEval arg3) {
+    public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+            ValueEval arg2, ValueEval arg3) {
 
-		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();
-		}
+        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;
-		}
-		StringBuilder strBuff = new StringBuilder(oldStr);
-		// remove any characters that should be replaced
-		if (startNum <= oldStr.length() && numChars != 0) {
-			strBuff.delete(startNum - 1, startNum - 1 + numChars);
-		}
-		// now insert (or append) newStr
-		if (startNum > strBuff.length()) {
-			strBuff.append(newStr);
-		} else {
-			strBuff.insert(startNum - 1, newStr);
-		}
-		return new StringEval(strBuff.toString());
-	}
+        if (startNum < 1 || numChars < 0) {
+            return ErrorEval.VALUE_INVALID;
+        }
+        StringBuilder strBuff = new StringBuilder(oldStr);
+        // remove any characters that should be replaced
+        if (startNum <= oldStr.length() && numChars != 0) {
+            strBuff.delete(startNum - 1, startNum - 1 + numChars);
+        }
+        // now insert (or append) newStr
+        if (startNum > strBuff.length()) {
+            strBuff.append(newStr);
+        } else {
+            strBuff.insert(startNum - 1, newStr);
+        }
+        return new StringEval(strBuff.toString());
+    }
 }

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Rept.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Rept.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Rept.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Rept.java Sat May 22 20:56:44 2021
@@ -31,7 +31,7 @@ import org.apache.poi.ss.formula.eval.Va
  * Repeats text a given number of times. Use REPT to fill a cell with a number of instances of a text string.
  *
  * text : text The text that you want to repeat.
- * number_times:	A positive number specifying the number of times to repeat text.
+ * number_times:    A positive number specifying the number of times to repeat text.
  *
  * If number_times is 0 (zero), REPT returns "" (empty text).
  * If this argument contains a decimal value, this function ignores the numbers to the right side of the decimal point.

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Rows.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Rows.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Rows.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Rows.java Sat May 22 20:56:44 2021
@@ -28,16 +28,16 @@ import org.apache.poi.ss.formula.TwoDEva
  */
 public final class Rows extends Fixed1ArgFunction {
 
-	public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
+    public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
 
-		int result;
-		if (arg0 instanceof TwoDEval) {
-			result = ((TwoDEval) arg0).getHeight();
-		} else if (arg0 instanceof RefEval) {
-			result = 1;
-		} else { // anything else is not valid argument
-			return ErrorEval.VALUE_INVALID;
-		}
-		return new NumberEval(result);
-	}
+        int result;
+        if (arg0 instanceof TwoDEval) {
+            result = ((TwoDEval) arg0).getHeight();
+        } else if (arg0 instanceof RefEval) {
+            result = 1;
+        } else { // anything else is not valid argument
+            return ErrorEval.VALUE_INVALID;
+        }
+        return new NumberEval(result);
+    }
 }

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Slope.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Slope.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Slope.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Slope.java Sat May 22 20:56:44 2021
@@ -32,15 +32,15 @@ import org.apache.poi.ss.formula.functio
  */
 public final class Slope extends Fixed2ArgFunction {
 
-	private final LinearRegressionFunction func;
-	public Slope() {
-		func = new LinearRegressionFunction(FUNCTION.SLOPE);
-	}
+    private final LinearRegressionFunction func;
+    public Slope() {
+        func = new LinearRegressionFunction(FUNCTION.SLOPE);
+    }
 
-	@Override
-	public ValueEval evaluate(int srcRowIndex, int srcColumnIndex,
-			ValueEval arg0, ValueEval arg1) {
-		return func.evaluate(srcRowIndex, srcColumnIndex, arg0, arg1);
-	}
+    @Override
+    public ValueEval evaluate(int srcRowIndex, int srcColumnIndex,
+            ValueEval arg0, ValueEval arg1) {
+        return func.evaluate(srcRowIndex, srcColumnIndex, arg0, arg1);
+    }
 }
 

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Substitute.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Substitute.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Substitute.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Substitute.java Sat May 22 20:56:44 2021
@@ -28,82 +28,82 @@ import org.apache.poi.ss.formula.eval.Va
  */
 public final class Substitute extends Var3or4ArgFunction {
 
-	public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
-			ValueEval arg2) {
-		String result;
-		try {
-			String oldStr = TextFunction.evaluateStringArg(arg0, srcRowIndex, srcColumnIndex);
-			String searchStr = TextFunction.evaluateStringArg(arg1, srcRowIndex, srcColumnIndex);
-			String newStr = TextFunction.evaluateStringArg(arg2, srcRowIndex, srcColumnIndex);
-
-			result = replaceAllOccurrences(oldStr, searchStr, newStr);
-		} catch (EvaluationException e) {
-			return e.getErrorEval();
-		}
-		return new StringEval(result);
-	}
-
-	public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
-			ValueEval arg2, ValueEval arg3) {
-		String result;
-		try {
-			String oldStr = TextFunction.evaluateStringArg(arg0, srcRowIndex, srcColumnIndex);
-			String searchStr = TextFunction.evaluateStringArg(arg1, srcRowIndex, srcColumnIndex);
-			String newStr = TextFunction.evaluateStringArg(arg2, srcRowIndex, srcColumnIndex);
-
-			int instanceNumber = TextFunction.evaluateIntArg(arg3, srcRowIndex, srcColumnIndex);
-			if (instanceNumber < 1) {
-				return ErrorEval.VALUE_INVALID;
-			}
-			result = replaceOneOccurrence(oldStr, searchStr, newStr, instanceNumber);
-		} catch (EvaluationException e) {
-			return e.getErrorEval();
-		}
-		return new StringEval(result);
-	}
-
-	private static String replaceAllOccurrences(String oldStr, String searchStr, String newStr) {
-		// avoid endless loop when searching for nothing
-		if (searchStr.length() < 1) {
-			return oldStr;
-		}
-
-		StringBuilder sb = new StringBuilder();
-		int startIndex = 0;
-		while (true) {
-			int nextMatch = oldStr.indexOf(searchStr, startIndex);
-			if (nextMatch < 0) {
-				// store everything from end of last match to end of string
-				sb.append(oldStr.substring(startIndex));
-				return sb.toString();
-			}
-			// store everything from end of last match to start of this match
-			sb.append(oldStr, startIndex, nextMatch);
-			sb.append(newStr);
-			startIndex = nextMatch + searchStr.length();
-		}
-	}
-
-	private static String replaceOneOccurrence(String oldStr, String searchStr, String newStr, int instanceNumber) {
-		// avoid endless loop when searching for nothing
-		if (searchStr.length() < 1) {
-			return oldStr;
-		}
-		int startIndex = 0;
-		int count=0;
-		while (true) {
-			int nextMatch = oldStr.indexOf(searchStr, startIndex);
-			if (nextMatch < 0) {
-				// not enough occurrences found - leave unchanged
-				return oldStr;
-			}
-			count++;
-			if (count == instanceNumber) {
-				return oldStr.substring(0, nextMatch) +
-						newStr +
-						oldStr.substring(nextMatch + searchStr.length());
-			}
-			startIndex = nextMatch + searchStr.length();
-		}
-	}
+    public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+            ValueEval arg2) {
+        String result;
+        try {
+            String oldStr = TextFunction.evaluateStringArg(arg0, srcRowIndex, srcColumnIndex);
+            String searchStr = TextFunction.evaluateStringArg(arg1, srcRowIndex, srcColumnIndex);
+            String newStr = TextFunction.evaluateStringArg(arg2, srcRowIndex, srcColumnIndex);
+
+            result = replaceAllOccurrences(oldStr, searchStr, newStr);
+        } catch (EvaluationException e) {
+            return e.getErrorEval();
+        }
+        return new StringEval(result);
+    }
+
+    public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+            ValueEval arg2, ValueEval arg3) {
+        String result;
+        try {
+            String oldStr = TextFunction.evaluateStringArg(arg0, srcRowIndex, srcColumnIndex);
+            String searchStr = TextFunction.evaluateStringArg(arg1, srcRowIndex, srcColumnIndex);
+            String newStr = TextFunction.evaluateStringArg(arg2, srcRowIndex, srcColumnIndex);
+
+            int instanceNumber = TextFunction.evaluateIntArg(arg3, srcRowIndex, srcColumnIndex);
+            if (instanceNumber < 1) {
+                return ErrorEval.VALUE_INVALID;
+            }
+            result = replaceOneOccurrence(oldStr, searchStr, newStr, instanceNumber);
+        } catch (EvaluationException e) {
+            return e.getErrorEval();
+        }
+        return new StringEval(result);
+    }
+
+    private static String replaceAllOccurrences(String oldStr, String searchStr, String newStr) {
+        // avoid endless loop when searching for nothing
+        if (searchStr.length() < 1) {
+            return oldStr;
+        }
+
+        StringBuilder sb = new StringBuilder();
+        int startIndex = 0;
+        while (true) {
+            int nextMatch = oldStr.indexOf(searchStr, startIndex);
+            if (nextMatch < 0) {
+                // store everything from end of last match to end of string
+                sb.append(oldStr.substring(startIndex));
+                return sb.toString();
+            }
+            // store everything from end of last match to start of this match
+            sb.append(oldStr, startIndex, nextMatch);
+            sb.append(newStr);
+            startIndex = nextMatch + searchStr.length();
+        }
+    }
+
+    private static String replaceOneOccurrence(String oldStr, String searchStr, String newStr, int instanceNumber) {
+        // avoid endless loop when searching for nothing
+        if (searchStr.length() < 1) {
+            return oldStr;
+        }
+        int startIndex = 0;
+        int count=0;
+        while (true) {
+            int nextMatch = oldStr.indexOf(searchStr, startIndex);
+            if (nextMatch < 0) {
+                // not enough occurrences found - leave unchanged
+                return oldStr;
+            }
+            count++;
+            if (count == instanceNumber) {
+                return oldStr.substring(0, nextMatch) +
+                        newStr +
+                        oldStr.substring(nextMatch + searchStr.length());
+            }
+            startIndex = nextMatch + searchStr.length();
+        }
+    }
 }

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Subtotal.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Subtotal.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Subtotal.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Subtotal.java Sat May 22 20:56:44 2021
@@ -73,72 +73,72 @@ import org.apache.poi.ss.formula.eval.Va
  */
 public class Subtotal implements Function {
 
-	private static Function findFunction(int functionCode) throws EvaluationException {
+    private static Function findFunction(int functionCode) throws EvaluationException {
         switch (functionCode) {
-			case 1: return subtotalInstance(AggregateFunction.AVERAGE, true);
-			case 2: return Count.subtotalInstance(true);
-			case 3: return Counta.subtotalInstance(true);
-			case 4: return subtotalInstance(AggregateFunction.MAX, true);
-			case 5: return subtotalInstance(AggregateFunction.MIN, true);
-			case 6: return subtotalInstance(AggregateFunction.PRODUCT, true);
-			case 7: return subtotalInstance(AggregateFunction.STDEV, true);
-			case 8: throw new NotImplementedFunctionException("STDEVP");
-			case 9: return subtotalInstance(AggregateFunction.SUM, true);
-			case 10: throw new NotImplementedFunctionException("VAR");
-			case 11: throw new NotImplementedFunctionException("VARP");
-			case 101: return subtotalInstance(AggregateFunction.AVERAGE, false);
-			case 102: return Count.subtotalInstance(false);
-			case 103: return Counta.subtotalInstance(false);
-			case 104: return subtotalInstance(AggregateFunction.MAX, false);
-			case 105: return subtotalInstance(AggregateFunction.MIN, false);
-			case 106: return subtotalInstance(AggregateFunction.PRODUCT, false);
-			case 107: return subtotalInstance(AggregateFunction.STDEV, false);
-			case 108: throw new NotImplementedFunctionException("STDEVP SUBTOTAL with 'exclude hidden values' option");
-			case 109: return subtotalInstance(AggregateFunction.SUM, false);
-			case 110: throw new NotImplementedFunctionException("VAR SUBTOTAL with 'exclude hidden values' option");
-			case 111: throw new NotImplementedFunctionException("VARP SUBTOTAL with 'exclude hidden values' option");
-		}
-		throw EvaluationException.invalidValue();
-	}
-
-	@Override
-	public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
-		int nInnerArgs = args.length-1; // -1: first arg is used to select from a basic aggregate function
-		if (nInnerArgs < 1) {
-			return ErrorEval.VALUE_INVALID;
-		}
-
-		final Function innerFunc;
-		int functionCode;
-		try {
-			ValueEval ve = OperandResolver.getSingleValue(args[0], srcRowIndex, srcColumnIndex);
+            case 1: return subtotalInstance(AggregateFunction.AVERAGE, true);
+            case 2: return Count.subtotalInstance(true);
+            case 3: return Counta.subtotalInstance(true);
+            case 4: return subtotalInstance(AggregateFunction.MAX, true);
+            case 5: return subtotalInstance(AggregateFunction.MIN, true);
+            case 6: return subtotalInstance(AggregateFunction.PRODUCT, true);
+            case 7: return subtotalInstance(AggregateFunction.STDEV, true);
+            case 8: throw new NotImplementedFunctionException("STDEVP");
+            case 9: return subtotalInstance(AggregateFunction.SUM, true);
+            case 10: throw new NotImplementedFunctionException("VAR");
+            case 11: throw new NotImplementedFunctionException("VARP");
+            case 101: return subtotalInstance(AggregateFunction.AVERAGE, false);
+            case 102: return Count.subtotalInstance(false);
+            case 103: return Counta.subtotalInstance(false);
+            case 104: return subtotalInstance(AggregateFunction.MAX, false);
+            case 105: return subtotalInstance(AggregateFunction.MIN, false);
+            case 106: return subtotalInstance(AggregateFunction.PRODUCT, false);
+            case 107: return subtotalInstance(AggregateFunction.STDEV, false);
+            case 108: throw new NotImplementedFunctionException("STDEVP SUBTOTAL with 'exclude hidden values' option");
+            case 109: return subtotalInstance(AggregateFunction.SUM, false);
+            case 110: throw new NotImplementedFunctionException("VAR SUBTOTAL with 'exclude hidden values' option");
+            case 111: throw new NotImplementedFunctionException("VARP SUBTOTAL with 'exclude hidden values' option");
+        }
+        throw EvaluationException.invalidValue();
+    }
+
+    @Override
+    public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+        int nInnerArgs = args.length-1; // -1: first arg is used to select from a basic aggregate function
+        if (nInnerArgs < 1) {
+            return ErrorEval.VALUE_INVALID;
+        }
+
+        final Function innerFunc;
+        int functionCode;
+        try {
+            ValueEval ve = OperandResolver.getSingleValue(args[0], srcRowIndex, srcColumnIndex);
             functionCode = OperandResolver.coerceValueToInt(ve);
-			innerFunc = findFunction(functionCode);
-		} catch (EvaluationException e) {
-			return e.getErrorEval();
-		}
-
-		// ignore the first arg, this is the function-type, we check for the length above
-		final List<ValueEval> list = new ArrayList<>(Arrays.asList(args).subList(1, args.length));
-
-		Iterator<ValueEval> it = list.iterator();
-
-		// See https://support.office.com/en-us/article/SUBTOTAL-function-7b027003-f060-4ade-9040-e478765b9939
-		// "If there are other subtotals within ref1, ref2,... (or nested subtotals), these nested subtotals are ignored to avoid double counting."
-		// For array references it is handled in other evaluation steps, but we need to handle this here for references to subtotal-functions
-		while(it.hasNext()) {
-			ValueEval eval = it.next();
-			if(eval instanceof LazyRefEval) {
-				LazyRefEval lazyRefEval = (LazyRefEval) eval;
-				if(lazyRefEval.isSubTotal()) {
-					it.remove();
-				}
-				if (functionCode > 100 && lazyRefEval.isRowHidden()) {
-				    it.remove();
-				}
-			}
-		}
+            innerFunc = findFunction(functionCode);
+        } catch (EvaluationException e) {
+            return e.getErrorEval();
+        }
+
+        // ignore the first arg, this is the function-type, we check for the length above
+        final List<ValueEval> list = new ArrayList<>(Arrays.asList(args).subList(1, args.length));
+
+        Iterator<ValueEval> it = list.iterator();
+
+        // See https://support.office.com/en-us/article/SUBTOTAL-function-7b027003-f060-4ade-9040-e478765b9939
+        // "If there are other subtotals within ref1, ref2,... (or nested subtotals), these nested subtotals are ignored to avoid double counting."
+        // For array references it is handled in other evaluation steps, but we need to handle this here for references to subtotal-functions
+        while(it.hasNext()) {
+            ValueEval eval = it.next();
+            if(eval instanceof LazyRefEval) {
+                LazyRefEval lazyRefEval = (LazyRefEval) eval;
+                if(lazyRefEval.isSubTotal()) {
+                    it.remove();
+                }
+                if (functionCode > 100 && lazyRefEval.isRowHidden()) {
+                    it.remove();
+                }
+            }
+        }
 
-		return innerFunc.evaluate(list.toArray(new ValueEval[0]), srcRowIndex, srcColumnIndex);
-	}
+        return innerFunc.evaluate(list.toArray(new ValueEval[0]), srcRowIndex, srcColumnIndex);
+    }
 }

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumif.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumif.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumif.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumif.java Sat May 22 20:56:44 2021
@@ -39,96 +39,96 @@ import org.apache.poi.ss.formula.functio
  */
 public final class Sumif extends Var2or3ArgFunction {
 
-	@Override
-	public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
+    @Override
+    public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
 
-		AreaEval aeRange;
-		try {
-			aeRange = convertRangeArg(arg0);
-		} catch (EvaluationException e) {
-			return e.getErrorEval();
-		}
-		return eval(srcRowIndex, srcColumnIndex, arg1, aeRange, aeRange);
-	}
-
-	@Override
-	public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
-			ValueEval arg2) {
-
-		AreaEval aeRange;
-		AreaEval aeSum;
-		try {
-			aeRange = convertRangeArg(arg0);
-			aeSum = createSumRange(arg2, aeRange);
-		} catch (EvaluationException e) {
-			return e.getErrorEval();
-		}
-		return eval(srcRowIndex, srcColumnIndex, arg1, aeRange, aeSum);
-	}
-
-	private static ValueEval eval(int srcRowIndex, int srcColumnIndex, ValueEval arg1, AreaEval aeRange,
-			AreaEval aeSum) {
-		// TODO - junit to prove last arg must be srcColumnIndex and not srcRowIndex
-		I_MatchPredicate mp = Countif.createCriteriaPredicate(arg1, srcRowIndex, srcColumnIndex);
-
-		// handle empty cells
-		if(mp == null) {
-		    return NumberEval.ZERO;
-		}
-
-		double result = sumMatchingCells(aeRange, mp, aeSum);
-		return new NumberEval(result);
-	}
-
-	private static double sumMatchingCells(AreaEval aeRange, I_MatchPredicate mp, AreaEval aeSum) {
-		int height=aeRange.getHeight();
-		int width= aeRange.getWidth();
-
-		double result = 0.0;
-		for (int r=0; r<height; r++) {
-			for (int c=0; c<width; c++) {
-				result += accumulate(aeRange, mp, aeSum, r, c);
-			}
-		}
-		return result;
-	}
-
-	private static double accumulate(AreaEval aeRange, I_MatchPredicate mp, AreaEval aeSum, int relRowIndex,
-			int relColIndex) {
-
-		if (!mp.matches(aeRange.getRelativeValue(relRowIndex, relColIndex))) {
-			return 0.0;
-		}
-		ValueEval addend = aeSum.getRelativeValue(relRowIndex, relColIndex);
-		if (addend instanceof NumberEval) {
-			return ((NumberEval)addend).getNumberValue();
-		}
-		// everything else (including string and boolean values) counts as zero
-		return 0.0;
-	}
-
-	/**
-	 * @return a range of the same dimensions as aeRange using eval to define the top left corner.
-	 * @throws EvaluationException if eval is not a reference
-	 */
-	private static AreaEval createSumRange(ValueEval eval, AreaEval aeRange) throws EvaluationException {
-		if (eval instanceof AreaEval) {
-			return ((AreaEval) eval).offset(0, aeRange.getHeight()-1, 0, aeRange.getWidth()-1);
-		}
-		if (eval instanceof RefEval) {
-			return ((RefEval)eval).offset(0, aeRange.getHeight()-1, 0, aeRange.getWidth()-1);
-		}
-		throw new EvaluationException(ErrorEval.VALUE_INVALID);
-	}
-
-	private static AreaEval convertRangeArg(ValueEval eval) throws EvaluationException {
-		if (eval instanceof AreaEval) {
-			return (AreaEval) eval;
-		}
-		if (eval instanceof RefEval) {
-			return ((RefEval)eval).offset(0, 0, 0, 0);
-		}
-		throw new EvaluationException(ErrorEval.VALUE_INVALID);
-	}
+        AreaEval aeRange;
+        try {
+            aeRange = convertRangeArg(arg0);
+        } catch (EvaluationException e) {
+            return e.getErrorEval();
+        }
+        return eval(srcRowIndex, srcColumnIndex, arg1, aeRange, aeRange);
+    }
+
+    @Override
+    public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+            ValueEval arg2) {
+
+        AreaEval aeRange;
+        AreaEval aeSum;
+        try {
+            aeRange = convertRangeArg(arg0);
+            aeSum = createSumRange(arg2, aeRange);
+        } catch (EvaluationException e) {
+            return e.getErrorEval();
+        }
+        return eval(srcRowIndex, srcColumnIndex, arg1, aeRange, aeSum);
+    }
+
+    private static ValueEval eval(int srcRowIndex, int srcColumnIndex, ValueEval arg1, AreaEval aeRange,
+            AreaEval aeSum) {
+        // TODO - junit to prove last arg must be srcColumnIndex and not srcRowIndex
+        I_MatchPredicate mp = Countif.createCriteriaPredicate(arg1, srcRowIndex, srcColumnIndex);
+
+        // handle empty cells
+        if(mp == null) {
+            return NumberEval.ZERO;
+        }
+
+        double result = sumMatchingCells(aeRange, mp, aeSum);
+        return new NumberEval(result);
+    }
+
+    private static double sumMatchingCells(AreaEval aeRange, I_MatchPredicate mp, AreaEval aeSum) {
+        int height=aeRange.getHeight();
+        int width= aeRange.getWidth();
+
+        double result = 0.0;
+        for (int r=0; r<height; r++) {
+            for (int c=0; c<width; c++) {
+                result += accumulate(aeRange, mp, aeSum, r, c);
+            }
+        }
+        return result;
+    }
+
+    private static double accumulate(AreaEval aeRange, I_MatchPredicate mp, AreaEval aeSum, int relRowIndex,
+            int relColIndex) {
+
+        if (!mp.matches(aeRange.getRelativeValue(relRowIndex, relColIndex))) {
+            return 0.0;
+        }
+        ValueEval addend = aeSum.getRelativeValue(relRowIndex, relColIndex);
+        if (addend instanceof NumberEval) {
+            return ((NumberEval)addend).getNumberValue();
+        }
+        // everything else (including string and boolean values) counts as zero
+        return 0.0;
+    }
+
+    /**
+     * @return a range of the same dimensions as aeRange using eval to define the top left corner.
+     * @throws EvaluationException if eval is not a reference
+     */
+    private static AreaEval createSumRange(ValueEval eval, AreaEval aeRange) throws EvaluationException {
+        if (eval instanceof AreaEval) {
+            return ((AreaEval) eval).offset(0, aeRange.getHeight()-1, 0, aeRange.getWidth()-1);
+        }
+        if (eval instanceof RefEval) {
+            return ((RefEval)eval).offset(0, aeRange.getHeight()-1, 0, aeRange.getWidth()-1);
+        }
+        throw new EvaluationException(ErrorEval.VALUE_INVALID);
+    }
+
+    private static AreaEval convertRangeArg(ValueEval eval) throws EvaluationException {
+        if (eval instanceof AreaEval) {
+            return (AreaEval) eval;
+        }
+        if (eval instanceof RefEval) {
+            return ((RefEval)eval).offset(0, 0, 0, 0);
+        }
+        throw new EvaluationException(ErrorEval.VALUE_INVALID);
+    }
 
 }

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumproduct.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumproduct.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumproduct.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumproduct.java Sat May 22 20:56:44 2021
@@ -46,190 +46,190 @@ import org.apache.poi.ss.formula.eval.Va
  * of the <b>n</b>th array<br>
  * Assuming each array has the same dimensions (W, H), the result is defined as:<br>
  * SUMPRODUCT = &Sigma;<sub><b>i</b>: 1..H</sub> &nbsp;
- * 	(&nbsp; &Sigma;<sub><b>j</b>: 1..W</sub> &nbsp;
- * 	  (&nbsp; &Pi;<sub><b>n</b>: 1..N</sub>
- * 			A<b>n</b><sub>(<b>i</b>,<b>j</b>)</sub>&nbsp;
+ *  (&nbsp; &Sigma;<sub><b>j</b>: 1..W</sub> &nbsp;
+ *    (&nbsp; &Pi;<sub><b>n</b>: 1..N</sub>
+ *          A<b>n</b><sub>(<b>i</b>,<b>j</b>)</sub>&nbsp;
  *    )&nbsp;
  *  )
  */
 public final class Sumproduct implements Function {
 
 
-	@Override
-	public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
+    @Override
+    public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
 
-		int maxN = args.length;
+        int maxN = args.length;
 
-		if(maxN < 1) {
-			return ErrorEval.VALUE_INVALID;
-		}
-		ValueEval firstArg = args[0];
-		try {
-			if(firstArg instanceof NumericValueEval) {
-				return evaluateSingleProduct(args);
-			}
-			if(firstArg instanceof RefEval) {
-				return evaluateSingleProduct(args);
-			}
-			if (firstArg instanceof TwoDEval) {
-				TwoDEval ae = (TwoDEval) firstArg;
-				if(ae.isRow() && ae.isColumn()) {
-					return evaluateSingleProduct(args);
-				}
-				return evaluateAreaSumProduct(args);
-			}
-		} catch (EvaluationException e) {
-			return e.getErrorEval();
-		}
-		throw new RuntimeException("Invalid arg type for SUMPRODUCT: ("
-				+ firstArg.getClass().getName() + ")");
-	}
-
-	private static ValueEval evaluateSingleProduct(ValueEval[] evalArgs) throws EvaluationException {
-		int maxN = evalArgs.length;
-
-		double term = 1D;
-		for (ValueEval evalArg : evalArgs) {
-			double val = getScalarValue(evalArg);
-			term *= val;
-		}
-		return new NumberEval(term);
-	}
-
-	private static double getScalarValue(ValueEval arg) throws EvaluationException {
-
-		ValueEval eval;
-		if (arg instanceof RefEval) {
-			RefEval re = (RefEval) arg;
-			if (re.getNumberOfSheets() > 1) {
+        if(maxN < 1) {
+            return ErrorEval.VALUE_INVALID;
+        }
+        ValueEval firstArg = args[0];
+        try {
+            if(firstArg instanceof NumericValueEval) {
+                return evaluateSingleProduct(args);
+            }
+            if(firstArg instanceof RefEval) {
+                return evaluateSingleProduct(args);
+            }
+            if (firstArg instanceof TwoDEval) {
+                TwoDEval ae = (TwoDEval) firstArg;
+                if(ae.isRow() && ae.isColumn()) {
+                    return evaluateSingleProduct(args);
+                }
+                return evaluateAreaSumProduct(args);
+            }
+        } catch (EvaluationException e) {
+            return e.getErrorEval();
+        }
+        throw new RuntimeException("Invalid arg type for SUMPRODUCT: ("
+                + firstArg.getClass().getName() + ")");
+    }
+
+    private static ValueEval evaluateSingleProduct(ValueEval[] evalArgs) throws EvaluationException {
+        int maxN = evalArgs.length;
+
+        double term = 1D;
+        for (ValueEval evalArg : evalArgs) {
+            double val = getScalarValue(evalArg);
+            term *= val;
+        }
+        return new NumberEval(term);
+    }
+
+    private static double getScalarValue(ValueEval arg) throws EvaluationException {
+
+        ValueEval eval;
+        if (arg instanceof RefEval) {
+            RefEval re = (RefEval) arg;
+            if (re.getNumberOfSheets() > 1) {
                 throw new EvaluationException(ErrorEval.VALUE_INVALID);
-			}
-			eval = re.getInnerValueEval(re.getFirstSheetIndex());
-		} else {
-			eval = arg;
-		}
-
-		if (eval == null) {
-			throw new RuntimeException("parameter may not be null");
-		}
-		if (eval instanceof AreaEval) {
-			AreaEval ae = (AreaEval) eval;
-			// an area ref can work as a scalar value if it is 1x1
-			if(!ae.isColumn() || !ae.isRow()) {
-				throw new EvaluationException(ErrorEval.VALUE_INVALID);
-			}
-			eval = ae.getRelativeValue(0, 0);
-		}
-
-		return getProductTerm(eval, true);
-	}
-
-	private static ValueEval evaluateAreaSumProduct(ValueEval[] evalArgs) throws EvaluationException {
-		int maxN = evalArgs.length;
-		TwoDEval[] args;
-		try {
-			args = Arrays.copyOf(evalArgs, maxN, TwoDEval[].class);
-		} catch (ArrayStoreException e) {
-			// one of the other args was not an AreaRef
-			return ErrorEval.VALUE_INVALID;
-		}
-
-
-		TwoDEval firstArg = args[0];
-
-		int height = firstArg.getHeight();
-		int width = firstArg.getWidth(); // TODO - junit
-
-		// first check dimensions
-		if (!areasAllSameSize(args, height, width)) {
-			// normally this results in #VALUE!,
-			// but errors in individual cells take precedence
-			for (int i = 1; i < args.length; i++) {
-				throwFirstError(args[i]);
-			}
-			return ErrorEval.VALUE_INVALID;
-		}
-
-		double acc = 0;
-
-		for (int rrIx=0; rrIx<height; rrIx++) {
-			for (int rcIx=0; rcIx<width; rcIx++) {
-				double term = 1D;
-				for(int n=0; n<maxN; n++) {
-					double val = getProductTerm(args[n].getValue(rrIx, rcIx), false);
-					term *= val;
-				}
-				acc += term;
-			}
-		}
-
-		return new NumberEval(acc);
-	}
-
-	private static void throwFirstError(TwoDEval areaEval) throws EvaluationException {
-		int height = areaEval.getHeight();
-		int width = areaEval.getWidth();
-		for (int rrIx=0; rrIx<height; rrIx++) {
-			for (int rcIx=0; rcIx<width; rcIx++) {
-				ValueEval ve = areaEval.getValue(rrIx, rcIx);
-				if (ve instanceof ErrorEval) {
-					throw new EvaluationException((ErrorEval) ve);
-				}
-			}
-		}
-	}
-
-	private static boolean areasAllSameSize(TwoDEval[] args, int height, int width) {
-		for (TwoDEval areaEval : args) {
-			// check that height and width match
-			if (areaEval.getHeight() != height) {
-				return false;
-			}
-			if (areaEval.getWidth() != width) {
-				return false;
-			}
-		}
-		return true;
-	}
-
-
-	/**
-	 * Determines a {@code double} value for the specified {@code ValueEval}.
-	 * @param isScalarProduct {@code false} for SUMPRODUCTs over area refs.
-	 * @throws EvaluationException if {@code ve} represents an error value.
-	 * <p>
-	 * Note - string values and empty cells are interpreted differently depending on
-	 * {@code isScalarProduct}.  For scalar products, if any term is blank or a string, the
-	 * error (#VALUE!) is raised.  For area (sum)products, if any term is blank or a string, the
-	 * result is zero.
-	 */
-	private static double getProductTerm(ValueEval ve, boolean isScalarProduct) throws EvaluationException {
-
-		if(ve instanceof BlankEval || ve == null) {
-			// TODO - shouldn't BlankEval.INSTANCE be used always instead of null?
-			// null seems to occur when the blank cell is part of an area ref (but not reliably)
-			if(isScalarProduct) {
-				throw new EvaluationException(ErrorEval.VALUE_INVALID);
-			}
-			return 0;
-		}
-
-		if(ve instanceof ErrorEval) {
-			throw new EvaluationException((ErrorEval)ve);
-		}
-		if(ve instanceof StringEval) {
-			if(isScalarProduct) {
-				throw new EvaluationException(ErrorEval.VALUE_INVALID);
-			}
-			// Note for area SUMPRODUCTs, string values are interpreted as zero
-			// even if they would parse as valid numeric values
-			return 0;
-		}
-		if(ve instanceof NumericValueEval) {
-			NumericValueEval nve = (NumericValueEval) ve;
-			return nve.getNumberValue();
-		}
-		throw new RuntimeException("Unexpected value eval class ("
-				+ ve.getClass().getName() + ")");
-	}
+            }
+            eval = re.getInnerValueEval(re.getFirstSheetIndex());
+        } else {
+            eval = arg;
+        }
+
+        if (eval == null) {
+            throw new RuntimeException("parameter may not be null");
+        }
+        if (eval instanceof AreaEval) {
+            AreaEval ae = (AreaEval) eval;
+            // an area ref can work as a scalar value if it is 1x1
+            if(!ae.isColumn() || !ae.isRow()) {
+                throw new EvaluationException(ErrorEval.VALUE_INVALID);
+            }
+            eval = ae.getRelativeValue(0, 0);
+        }
+
+        return getProductTerm(eval, true);
+    }
+
+    private static ValueEval evaluateAreaSumProduct(ValueEval[] evalArgs) throws EvaluationException {
+        int maxN = evalArgs.length;
+        TwoDEval[] args;
+        try {
+            args = Arrays.copyOf(evalArgs, maxN, TwoDEval[].class);
+        } catch (ArrayStoreException e) {
+            // one of the other args was not an AreaRef
+            return ErrorEval.VALUE_INVALID;
+        }
+
+
+        TwoDEval firstArg = args[0];
+
+        int height = firstArg.getHeight();
+        int width = firstArg.getWidth(); // TODO - junit
+
+        // first check dimensions
+        if (!areasAllSameSize(args, height, width)) {
+            // normally this results in #VALUE!,
+            // but errors in individual cells take precedence
+            for (int i = 1; i < args.length; i++) {
+                throwFirstError(args[i]);
+            }
+            return ErrorEval.VALUE_INVALID;
+        }
+
+        double acc = 0;
+
+        for (int rrIx=0; rrIx<height; rrIx++) {
+            for (int rcIx=0; rcIx<width; rcIx++) {
+                double term = 1D;
+                for(int n=0; n<maxN; n++) {
+                    double val = getProductTerm(args[n].getValue(rrIx, rcIx), false);
+                    term *= val;
+                }
+                acc += term;
+            }
+        }
+
+        return new NumberEval(acc);
+    }
+
+    private static void throwFirstError(TwoDEval areaEval) throws EvaluationException {
+        int height = areaEval.getHeight();
+        int width = areaEval.getWidth();
+        for (int rrIx=0; rrIx<height; rrIx++) {
+            for (int rcIx=0; rcIx<width; rcIx++) {
+                ValueEval ve = areaEval.getValue(rrIx, rcIx);
+                if (ve instanceof ErrorEval) {
+                    throw new EvaluationException((ErrorEval) ve);
+                }
+            }
+        }
+    }
+
+    private static boolean areasAllSameSize(TwoDEval[] args, int height, int width) {
+        for (TwoDEval areaEval : args) {
+            // check that height and width match
+            if (areaEval.getHeight() != height) {
+                return false;
+            }
+            if (areaEval.getWidth() != width) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+
+    /**
+     * Determines a {@code double} value for the specified {@code ValueEval}.
+     * @param isScalarProduct {@code false} for SUMPRODUCTs over area refs.
+     * @throws EvaluationException if {@code ve} represents an error value.
+     * <p>
+     * Note - string values and empty cells are interpreted differently depending on
+     * {@code isScalarProduct}.  For scalar products, if any term is blank or a string, the
+     * error (#VALUE!) is raised.  For area (sum)products, if any term is blank or a string, the
+     * result is zero.
+     */
+    private static double getProductTerm(ValueEval ve, boolean isScalarProduct) throws EvaluationException {
+
+        if(ve instanceof BlankEval || ve == null) {
+            // TODO - shouldn't BlankEval.INSTANCE be used always instead of null?
+            // null seems to occur when the blank cell is part of an area ref (but not reliably)
+            if(isScalarProduct) {
+                throw new EvaluationException(ErrorEval.VALUE_INVALID);
+            }
+            return 0;
+        }
+
+        if(ve instanceof ErrorEval) {
+            throw new EvaluationException((ErrorEval)ve);
+        }
+        if(ve instanceof StringEval) {
+            if(isScalarProduct) {
+                throw new EvaluationException(ErrorEval.VALUE_INVALID);
+            }
+            // Note for area SUMPRODUCTs, string values are interpreted as zero
+            // even if they would parse as valid numeric values
+            return 0;
+        }
+        if(ve instanceof NumericValueEval) {
+            NumericValueEval nve = (NumericValueEval) ve;
+            return nve.getNumberValue();
+        }
+        throw new RuntimeException("Unexpected value eval class ("
+                + ve.getClass().getName() + ")");
+    }
 }

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumx2my2.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumx2my2.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumx2my2.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumx2my2.java Sat May 22 20:56:44 2021
@@ -29,15 +29,15 @@ package org.apache.poi.ss.formula.functi
  */
 public final class Sumx2my2 extends XYNumericFunction {
 
-	private static final Accumulator XSquaredMinusYSquaredAccumulator = new Accumulator() {
-		@Override
+    private static final Accumulator XSquaredMinusYSquaredAccumulator = new Accumulator() {
+        @Override
         public double accumulate(double x, double y) {
-			return x * x - y * y;
-		}
-	};
+            return x * x - y * y;
+        }
+    };
 
-	@Override
-	protected Accumulator createAccumulator() {
-		return XSquaredMinusYSquaredAccumulator;
-	}
+    @Override
+    protected Accumulator createAccumulator() {
+        return XSquaredMinusYSquaredAccumulator;
+    }
 }

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumx2py2.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumx2py2.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumx2py2.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumx2py2.java Sat May 22 20:56:44 2021
@@ -29,15 +29,15 @@ package org.apache.poi.ss.formula.functi
  */
 public final class Sumx2py2 extends XYNumericFunction {
 
-	private static final Accumulator XSquaredPlusYSquaredAccumulator = new Accumulator() {
-		@Override
+    private static final Accumulator XSquaredPlusYSquaredAccumulator = new Accumulator() {
+        @Override
         public double accumulate(double x, double y) {
-			return x * x + y * y;
-		}
-	};
+            return x * x + y * y;
+        }
+    };
 
-	@Override
-	protected Accumulator createAccumulator() {
-		return XSquaredPlusYSquaredAccumulator;
-	}
+    @Override
+    protected Accumulator createAccumulator() {
+        return XSquaredPlusYSquaredAccumulator;
+    }
 }

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumxmy2.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumxmy2.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumxmy2.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Sumxmy2.java Sat May 22 20:56:44 2021
@@ -28,16 +28,16 @@ package org.apache.poi.ss.formula.functi
  */
 public final class Sumxmy2 extends XYNumericFunction {
 
-	private static final Accumulator XMinusYSquaredAccumulator = new Accumulator() {
-		@Override
+    private static final Accumulator XMinusYSquaredAccumulator = new Accumulator() {
+        @Override
         public double accumulate(double x, double y) {
-			double xmy = x - y;
-			return xmy * xmy;
-		}
-	};
+            double xmy = x - y;
+            return xmy * xmy;
+        }
+    };
 
-	@Override
-	protected Accumulator createAccumulator() {
-		return XMinusYSquaredAccumulator;
-	}
+    @Override
+    protected Accumulator createAccumulator() {
+        return XMinusYSquaredAccumulator;
+    }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org