Created new TwoDEval interface for AreaEvals (in preparation for patch 48292)

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@888665 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2009-12-09 00:50:11 +00:00
parent 47e084cfcd
commit 288e76df7e
18 changed files with 158 additions and 99 deletions

View File

@ -17,11 +17,12 @@
package org.apache.poi.hssf.record.formula.eval; package org.apache.poi.hssf.record.formula.eval;
import org.apache.poi.ss.formula.TwoDEval;
/** /**
* @author Amol S. Deshmukh < amolweb at ya hoo dot com > * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
* *
*/ */
public interface AreaEval extends ValueEval { public interface AreaEval extends TwoDEval {
/** /**
* returns the 0-based index of the first row in * returns the 0-based index of the first row in
@ -47,20 +48,6 @@ public interface AreaEval extends ValueEval {
*/ */
int getLastColumn(); int getLastColumn();
/**
* returns true if the Area's start and end row indexes
* are same. This result of this method should agree
* with getFirstRow() == getLastRow().
*/
boolean isRow();
/**
* returns true if the Area's start and end col indexes
* are same. This result of this method should agree
* with getFirstColumn() == getLastColumn().
*/
boolean isColumn();
/** /**
* @return the ValueEval from within this area at the specified row and col index. Never * @return the ValueEval from within this area at the specified row and col index. Never
* <code>null</code> (possibly {@link BlankEval}). The specified indexes should be absolute * <code>null</code> (possibly {@link BlankEval}). The specified indexes should be absolute

View File

@ -66,7 +66,6 @@ public abstract class AreaEvalBase implements AreaEval {
public final int getLastRow() { public final int getLastRow() {
return _lastRow; return _lastRow;
} }
public final ValueEval getAbsoluteValue(int row, int col) { public final ValueEval getAbsoluteValue(int row, int col) {
int rowOffsetIx = row - _firstRow; int rowOffsetIx = row - _firstRow;
int colOffsetIx = col - _firstColumn; int colOffsetIx = col - _firstColumn;
@ -106,6 +105,10 @@ public abstract class AreaEvalBase implements AreaEval {
return _lastRow-_firstRow+1; return _lastRow-_firstRow+1;
} }
public final ValueEval getValue(int row, int col) {
return getRelativeValue(row, col);
}
public abstract ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex); public abstract ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex);
public int getWidth() { public int getWidth() {

View File

@ -17,13 +17,13 @@
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.AreaEval;
import org.apache.poi.hssf.record.formula.eval.BoolEval; import org.apache.poi.hssf.record.formula.eval.BoolEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval; import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.eval.EvaluationException; import org.apache.poi.hssf.record.formula.eval.EvaluationException;
import org.apache.poi.hssf.record.formula.eval.OperandResolver; import org.apache.poi.hssf.record.formula.eval.OperandResolver;
import org.apache.poi.hssf.record.formula.eval.RefEval; import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.ss.formula.TwoDEval;
/** /**
* Here are the general rules concerning Boolean functions: * Here are the general rules concerning Boolean functions:
@ -61,13 +61,13 @@ public abstract class BooleanFunction implements Function {
*/ */
for (int i=0, iSize=args.length; i<iSize; i++) { for (int i=0, iSize=args.length; i<iSize; i++) {
ValueEval arg = args[i]; ValueEval arg = args[i];
if (arg instanceof AreaEval) { if (arg instanceof TwoDEval) {
AreaEval ae = (AreaEval) arg; TwoDEval ae = (TwoDEval) arg;
int height = ae.getHeight(); int height = ae.getHeight();
int width = ae.getWidth(); int width = ae.getWidth();
for (int rrIx=0; rrIx<height; rrIx++) { for (int rrIx=0; rrIx<height; rrIx++) {
for (int rcIx=0; rcIx<width; rcIx++) { for (int rcIx=0; rcIx<width; rcIx++) {
ValueEval ve = ae.getRelativeValue(rrIx, rcIx); ValueEval ve = ae.getValue(rrIx, rcIx);
Boolean tempVe = OperandResolver.coerceValueToBoolean(ve, true); Boolean tempVe = OperandResolver.coerceValueToBoolean(ve, true);
if (tempVe != null) { if (tempVe != null) {
result = partialEvaluate(result, tempVe.booleanValue()); result = partialEvaluate(result, tempVe.booleanValue());

View File

@ -17,11 +17,11 @@
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.AreaEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval; import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; 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.RefEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.ss.formula.TwoDEval;
/** /**
* Implementation for Excel COLUMNS function. * Implementation for Excel COLUMNS function.
@ -33,8 +33,8 @@ public final class Columns extends Fixed1ArgFunction {
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
int result; int result;
if (arg0 instanceof AreaEval) { if (arg0 instanceof TwoDEval) {
result = ((AreaEval) arg0).getWidth(); result = ((TwoDEval) arg0).getWidth();
} else if (arg0 instanceof RefEval) { } else if (arg0 instanceof RefEval) {
result = 1; result = 1;
} else { // anything else is not valid argument } else { // anything else is not valid argument

View File

@ -17,9 +17,9 @@
package org.apache.poi.hssf.record.formula.functions; 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.RefEval; import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.ss.formula.TwoDEval;
/** /**
* Common logic for COUNT, COUNTA and COUNTIF * Common logic for COUNT, COUNTA and COUNTIF
@ -41,14 +41,14 @@ final class CountUtils {
/** /**
* @return the number of evaluated cells in the range that match the specified criteria * @return the number of evaluated cells in the range that match the specified criteria
*/ */
public static int countMatchingCellsInArea(AreaEval areaEval, I_MatchPredicate criteriaPredicate) { public static int countMatchingCellsInArea(TwoDEval areaEval, I_MatchPredicate criteriaPredicate) {
int result = 0; int result = 0;
int height = areaEval.getHeight(); int height = areaEval.getHeight();
int width = areaEval.getWidth(); int width = areaEval.getWidth();
for (int rrIx=0; rrIx<height; rrIx++) { for (int rrIx=0; rrIx<height; rrIx++) {
for (int rcIx=0; rcIx<width; rcIx++) { for (int rcIx=0; rcIx<width; rcIx++) {
ValueEval ve = areaEval.getRelativeValue(rrIx, rcIx); ValueEval ve = areaEval.getValue(rrIx, rcIx);
if(criteriaPredicate.matches(ve)) { if(criteriaPredicate.matches(ve)) {
result++; result++;
} }
@ -69,8 +69,8 @@ final class CountUtils {
if (eval == null) { if (eval == null) {
throw new IllegalArgumentException("eval must not be null"); throw new IllegalArgumentException("eval must not be null");
} }
if (eval instanceof AreaEval) { if (eval instanceof TwoDEval) {
return CountUtils.countMatchingCellsInArea((AreaEval) eval, criteriaPredicate); return countMatchingCellsInArea((TwoDEval) eval, criteriaPredicate);
} }
if (eval instanceof RefEval) { if (eval instanceof RefEval) {
return CountUtils.countMatchingCell((RefEval) eval, criteriaPredicate); return CountUtils.countMatchingCell((RefEval) eval, criteriaPredicate);

View File

@ -17,12 +17,12 @@
package org.apache.poi.hssf.record.formula.functions; 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.BlankEval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; 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.RefEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.functions.CountUtils.I_MatchPredicate; import org.apache.poi.hssf.record.formula.functions.CountUtils.I_MatchPredicate;
import org.apache.poi.ss.formula.TwoDEval;
/** /**
* Implementation for the function COUNTBLANK * Implementation for the function COUNTBLANK
@ -42,8 +42,8 @@ public final class Countblank extends Fixed1ArgFunction {
double result; double result;
if (arg0 instanceof RefEval) { if (arg0 instanceof RefEval) {
result = CountUtils.countMatchingCell((RefEval) arg0, predicate); result = CountUtils.countMatchingCell((RefEval) arg0, predicate);
} else if (arg0 instanceof AreaEval) { } else if (arg0 instanceof TwoDEval) {
result = CountUtils.countMatchingCellsInArea((AreaEval) arg0, predicate); result = CountUtils.countMatchingCellsInArea((TwoDEval) arg0, predicate);
} else { } else {
throw new IllegalArgumentException("Bad range arg type (" + arg0.getClass().getName() + ")"); throw new IllegalArgumentException("Bad range arg type (" + arg0.getClass().getName() + ")");
} }

View File

@ -19,7 +19,6 @@ package org.apache.poi.hssf.record.formula.functions;
import java.util.regex.Pattern; import java.util.regex.Pattern;
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.BlankEval;
import org.apache.poi.hssf.record.formula.eval.BoolEval; import org.apache.poi.hssf.record.formula.eval.BoolEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval; import org.apache.poi.hssf.record.formula.eval.ErrorEval;
@ -30,6 +29,7 @@ import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.StringEval; import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.functions.CountUtils.I_MatchPredicate; import org.apache.poi.hssf.record.formula.functions.CountUtils.I_MatchPredicate;
import org.apache.poi.ss.formula.TwoDEval;
import org.apache.poi.ss.usermodel.ErrorConstants; import org.apache.poi.ss.usermodel.ErrorConstants;
/** /**
@ -417,8 +417,8 @@ public final class Countif extends Fixed2ArgFunction {
if (rangeArg instanceof RefEval) { if (rangeArg instanceof RefEval) {
return CountUtils.countMatchingCell((RefEval) rangeArg, criteriaPredicate); return CountUtils.countMatchingCell((RefEval) rangeArg, criteriaPredicate);
} else if (rangeArg instanceof AreaEval) { } else if (rangeArg instanceof TwoDEval) {
return CountUtils.countMatchingCellsInArea((AreaEval) rangeArg, criteriaPredicate); return CountUtils.countMatchingCellsInArea((TwoDEval) rangeArg, criteriaPredicate);
} else { } else {
throw new IllegalArgumentException("Bad range arg type (" + rangeArg.getClass().getName() + ")"); throw new IllegalArgumentException("Bad range arg type (" + rangeArg.getClass().getName() + ")");
} }

View File

@ -17,12 +17,12 @@
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.AreaEval;
import org.apache.poi.hssf.record.formula.eval.BoolEval; import org.apache.poi.hssf.record.formula.eval.BoolEval;
import org.apache.poi.hssf.record.formula.eval.EvaluationException; import org.apache.poi.hssf.record.formula.eval.EvaluationException;
import org.apache.poi.hssf.record.formula.eval.OperandResolver; import org.apache.poi.hssf.record.formula.eval.OperandResolver;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector; import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector;
import org.apache.poi.ss.formula.TwoDEval;
/** /**
* Implementation of the HLOOKUP() function.<p/> * Implementation of the HLOOKUP() function.<p/>
* *
@ -53,7 +53,7 @@ public final class Hlookup extends Var3or4ArgFunction {
// Evaluation order: // Evaluation order:
// arg0 lookup_value, arg1 table_array, arg3 range_lookup, find lookup value, arg2 row_index, fetch result // arg0 lookup_value, arg1 table_array, arg3 range_lookup, find lookup value, arg2 row_index, fetch result
ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
AreaEval tableArray = LookupUtils.resolveTableArrayArg(arg1); TwoDEval tableArray = LookupUtils.resolveTableArrayArg(arg1);
boolean isRangeLookup = LookupUtils.resolveRangeLookupArg(arg3, srcRowIndex, srcColumnIndex); boolean isRangeLookup = LookupUtils.resolveRangeLookupArg(arg3, srcRowIndex, srcColumnIndex);
int colIndex = LookupUtils.lookupIndexOfValue(lookupValue, LookupUtils.createRowVector(tableArray, 0), isRangeLookup); int colIndex = LookupUtils.lookupIndexOfValue(lookupValue, LookupUtils.createRowVector(tableArray, 0), isRangeLookup);
int rowIndex = LookupUtils.resolveRowOrColIndexArg(arg2, srcRowIndex, srcColumnIndex); int rowIndex = LookupUtils.resolveRowOrColIndexArg(arg2, srcRowIndex, srcColumnIndex);
@ -71,7 +71,7 @@ public final class Hlookup extends Var3or4ArgFunction {
* *
* @throws EvaluationException (#REF!) if colIndex is too high * @throws EvaluationException (#REF!) if colIndex is too high
*/ */
private ValueVector createResultColumnVector(AreaEval tableArray, int rowIndex) throws EvaluationException { private ValueVector createResultColumnVector(TwoDEval tableArray, int rowIndex) throws EvaluationException {
if(rowIndex >= tableArray.getHeight()) { if(rowIndex >= tableArray.getHeight()) {
throw EvaluationException.invalidRef(); throw EvaluationException.invalidRef();
} }

View File

@ -25,6 +25,7 @@ import org.apache.poi.hssf.record.formula.eval.MissingArgEval;
import org.apache.poi.hssf.record.formula.eval.OperandResolver; import org.apache.poi.hssf.record.formula.eval.OperandResolver;
import org.apache.poi.hssf.record.formula.eval.RefEval; import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.ss.formula.TwoDEval;
/** /**
* Implementation for the Excel function INDEX * Implementation for the Excel function INDEX
@ -47,7 +48,7 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval;
public final class Index implements Function2Arg, Function3Arg, Function4Arg { public final class Index implements Function2Arg, Function3Arg, Function4Arg {
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
AreaEval reference = convertFirstArg(arg0); TwoDEval reference = convertFirstArg(arg0);
boolean colArgWasPassed = false; boolean colArgWasPassed = false;
int columnIx = 0; int columnIx = 0;
@ -60,7 +61,7 @@ public final class Index implements Function2Arg, Function3Arg, Function4Arg {
} }
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
ValueEval arg2) { ValueEval arg2) {
AreaEval reference = convertFirstArg(arg0); TwoDEval reference = convertFirstArg(arg0);
boolean colArgWasPassed = true; boolean colArgWasPassed = true;
try { try {
@ -81,14 +82,14 @@ public final class Index implements Function2Arg, Function3Arg, Function4Arg {
// The formula parser doesn't seem to support this yet. Not sure if the evaluator does either // The formula parser doesn't seem to support this yet. Not sure if the evaluator does either
} }
private static AreaEval convertFirstArg(ValueEval arg0) { private static TwoDEval convertFirstArg(ValueEval arg0) {
ValueEval firstArg = arg0; ValueEval firstArg = arg0;
if (firstArg instanceof RefEval) { if (firstArg instanceof RefEval) {
// convert to area ref for simpler code in getValueFromArea() // convert to area ref for simpler code in getValueFromArea()
return ((RefEval)firstArg).offset(0, 0, 0, 0); return ((RefEval)firstArg).offset(0, 0, 0, 0);
} }
if((firstArg instanceof AreaEval)) { if((firstArg instanceof TwoDEval)) {
return (AreaEval) firstArg; return (TwoDEval) firstArg;
} }
// else the other variation of this function takes an array as the first argument // else the other variation of this function takes an array as the first argument
// it seems like interface 'ArrayEval' does not even exist yet // it seems like interface 'ArrayEval' does not even exist yet
@ -117,7 +118,7 @@ public final class Index implements Function2Arg, Function3Arg, Function4Arg {
* <code>true</code>. This parameter is needed because error codes are slightly * <code>true</code>. This parameter is needed because error codes are slightly
* different when only 2 args are passed. * different when only 2 args are passed.
*/ */
private static ValueEval getValueFromArea(AreaEval ae, int pRowIx, int pColumnIx, private static ValueEval getValueFromArea(TwoDEval ae, int pRowIx, int pColumnIx,
boolean colArgWasPassed, int srcRowIx, int srcColIx) throws EvaluationException { boolean colArgWasPassed, int srcRowIx, int srcColIx) throws EvaluationException {
boolean rowArgWasEmpty = pRowIx == 0; boolean rowArgWasEmpty = pRowIx == 0;
boolean colArgWasEmpty = pColumnIx == 0; boolean colArgWasEmpty = pColumnIx == 0;
@ -145,7 +146,13 @@ public final class Index implements Function2Arg, Function3Arg, Function4Arg {
} }
} else if (ae.isColumn()) { } else if (ae.isColumn()) {
if (rowArgWasEmpty) { if (rowArgWasEmpty) {
rowIx = srcRowIx - ae.getFirstRow(); if (ae instanceof AreaEval) {
rowIx = srcRowIx - ((AreaEval) ae).getFirstRow();
} else {
// TODO - ArrayEval
// rowIx = relative row of evaluating cell in its array formula cell group
throw new RuntimeException("incomplete code - ");
}
} else { } else {
rowIx = pRowIx-1; rowIx = pRowIx-1;
} }
@ -164,12 +171,24 @@ public final class Index implements Function2Arg, Function3Arg, Function4Arg {
// Normal case - area ref is 2-D, and both index args were provided // Normal case - area ref is 2-D, and both index args were provided
// if either arg is missing (or blank) the logic is similar to OperandResolver.getSingleValue() // if either arg is missing (or blank) the logic is similar to OperandResolver.getSingleValue()
if (rowArgWasEmpty) { if (rowArgWasEmpty) {
rowIx = srcRowIx - ae.getFirstRow(); if (ae instanceof AreaEval) {
rowIx = srcRowIx - ((AreaEval) ae).getFirstRow();
} else {
// TODO - ArrayEval
// rowIx = relative row of evaluating cell in its array formula cell group
throw new RuntimeException("incomplete code - ");
}
} else { } else {
rowIx = pRowIx-1; rowIx = pRowIx-1;
} }
if (colArgWasEmpty) { if (colArgWasEmpty) {
columnIx = srcColIx - ae.getFirstColumn(); if (ae instanceof AreaEval) {
columnIx = srcColIx - ((AreaEval) ae).getFirstColumn();
} else {
// TODO - ArrayEval
// colIx = relative col of evaluating cell in its array formula cell group
throw new RuntimeException("incomplete code - ");
}
} else { } else {
columnIx = pColumnIx-1; columnIx = pColumnIx-1;
} }
@ -185,7 +204,7 @@ public final class Index implements Function2Arg, Function3Arg, Function4Arg {
if (rowIx < 0 || columnIx < 0 || rowIx >= height || columnIx >= width) { if (rowIx < 0 || columnIx < 0 || rowIx >= height || columnIx >= width) {
throw new EvaluationException(ErrorEval.VALUE_INVALID); throw new EvaluationException(ErrorEval.VALUE_INVALID);
} }
return ae.getRelativeValue(rowIx, columnIx); return ae.getValue(rowIx, columnIx);
} }

View File

@ -17,11 +17,11 @@
package org.apache.poi.hssf.record.formula.functions; 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.EvaluationException; import org.apache.poi.hssf.record.formula.eval.EvaluationException;
import org.apache.poi.hssf.record.formula.eval.OperandResolver; import org.apache.poi.hssf.record.formula.eval.OperandResolver;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector; import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector;
import org.apache.poi.ss.formula.TwoDEval;
/** /**
* Implementation of Excel function LOOKUP.<p/> * Implementation of Excel function LOOKUP.<p/>
@ -48,8 +48,8 @@ public final class Lookup extends Var2or3ArgFunction {
ValueEval arg2) { ValueEval arg2) {
try { try {
ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
AreaEval aeLookupVector = LookupUtils.resolveTableArrayArg(arg1); TwoDEval aeLookupVector = LookupUtils.resolveTableArrayArg(arg1);
AreaEval aeResultVector = LookupUtils.resolveTableArrayArg(arg2); TwoDEval aeResultVector = LookupUtils.resolveTableArrayArg(arg2);
ValueVector lookupVector = createVector(aeLookupVector); ValueVector lookupVector = createVector(aeLookupVector);
ValueVector resultVector = createVector(aeResultVector); ValueVector resultVector = createVector(aeResultVector);
@ -65,7 +65,7 @@ public final class Lookup extends Var2or3ArgFunction {
} }
} }
private static ValueVector createVector(AreaEval ae) { private static ValueVector createVector(TwoDEval ae) {
ValueVector result = LookupUtils.createVector(ae); ValueVector result = LookupUtils.createVector(ae);
if (result != null) { if (result != null) {
return result; return result;

View File

@ -17,7 +17,6 @@
package org.apache.poi.hssf.record.formula.functions; 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.BlankEval;
import org.apache.poi.hssf.record.formula.eval.BoolEval; import org.apache.poi.hssf.record.formula.eval.BoolEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval; import org.apache.poi.hssf.record.formula.eval.ErrorEval;
@ -28,6 +27,7 @@ import org.apache.poi.hssf.record.formula.eval.OperandResolver;
import org.apache.poi.hssf.record.formula.eval.RefEval; import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.StringEval; import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.ss.formula.TwoDEval;
/** /**
* Common functionality used by VLOOKUP, HLOOKUP, LOOKUP and MATCH * Common functionality used by VLOOKUP, HLOOKUP, LOOKUP and MATCH
@ -47,15 +47,14 @@ final class LookupUtils {
private static final class RowVector implements ValueVector { private static final class RowVector implements ValueVector {
private final AreaEval _tableArray; private final TwoDEval _tableArray;
private final int _size; private final int _size;
private final int _rowIndex; private final int _rowIndex;
public RowVector(AreaEval tableArray, int rowIndex) { public RowVector(TwoDEval tableArray, int rowIndex) {
_rowIndex = rowIndex; _rowIndex = rowIndex;
int _rowAbsoluteIndex = tableArray.getFirstRow() + rowIndex; int lastRowIx = tableArray.getHeight() - 1;
if(!tableArray.containsRow(_rowAbsoluteIndex)) { if(rowIndex < 0 || rowIndex > lastRowIx) {
int lastRowIx = tableArray.getLastRow() - tableArray.getFirstRow();
throw new IllegalArgumentException("Specified row index (" + rowIndex throw new IllegalArgumentException("Specified row index (" + rowIndex
+ ") is outside the allowed range (0.." + lastRowIx + ")"); + ") is outside the allowed range (0.." + lastRowIx + ")");
} }
@ -68,7 +67,7 @@ final class LookupUtils {
throw new ArrayIndexOutOfBoundsException("Specified index (" + index throw new ArrayIndexOutOfBoundsException("Specified index (" + index
+ ") is outside the allowed range (0.." + (_size-1) + ")"); + ") is outside the allowed range (0.." + (_size-1) + ")");
} }
return _tableArray.getRelativeValue(_rowIndex, index); return _tableArray.getValue(_rowIndex, index);
} }
public int getSize() { public int getSize() {
return _size; return _size;
@ -77,15 +76,14 @@ final class LookupUtils {
private static final class ColumnVector implements ValueVector { private static final class ColumnVector implements ValueVector {
private final AreaEval _tableArray; private final TwoDEval _tableArray;
private final int _size; private final int _size;
private final int _columnIndex; private final int _columnIndex;
public ColumnVector(AreaEval tableArray, int columnIndex) { public ColumnVector(TwoDEval tableArray, int columnIndex) {
_columnIndex = columnIndex; _columnIndex = columnIndex;
int _columnAbsoluteIndex = tableArray.getFirstColumn() + columnIndex; int lastColIx = tableArray.getWidth()-1;
if(!tableArray.containsColumn((short)_columnAbsoluteIndex)) { if(columnIndex < 0 || columnIndex > lastColIx) {
int lastColIx = tableArray.getLastColumn() - tableArray.getFirstColumn();
throw new IllegalArgumentException("Specified column index (" + columnIndex throw new IllegalArgumentException("Specified column index (" + columnIndex
+ ") is outside the allowed range (0.." + lastColIx + ")"); + ") is outside the allowed range (0.." + lastColIx + ")");
} }
@ -98,23 +96,23 @@ final class LookupUtils {
throw new ArrayIndexOutOfBoundsException("Specified index (" + index throw new ArrayIndexOutOfBoundsException("Specified index (" + index
+ ") is outside the allowed range (0.." + (_size-1) + ")"); + ") is outside the allowed range (0.." + (_size-1) + ")");
} }
return _tableArray.getRelativeValue(index, _columnIndex); return _tableArray.getValue(index, _columnIndex);
} }
public int getSize() { public int getSize() {
return _size; return _size;
} }
} }
public static ValueVector createRowVector(AreaEval tableArray, int relativeRowIndex) { public static ValueVector createRowVector(TwoDEval tableArray, int relativeRowIndex) {
return new RowVector(tableArray, relativeRowIndex); return new RowVector(tableArray, relativeRowIndex);
} }
public static ValueVector createColumnVector(AreaEval tableArray, int relativeColumnIndex) { public static ValueVector createColumnVector(TwoDEval tableArray, int relativeColumnIndex) {
return new ColumnVector(tableArray, relativeColumnIndex); return new ColumnVector(tableArray, relativeColumnIndex);
} }
/** /**
* @return <code>null</code> if the supplied area is neither a single row nor a single colum * @return <code>null</code> if the supplied area is neither a single row nor a single colum
*/ */
public static ValueVector createVector(AreaEval ae) { public static ValueVector createVector(TwoDEval ae) {
if (ae.isColumn()) { if (ae.isColumn()) {
return createColumnVector(ae, 0); return createColumnVector(ae, 0);
} }
@ -361,9 +359,9 @@ final class LookupUtils {
* The second argument (table_array) should be an area ref, but can actually be a cell ref, in * The second argument (table_array) should be an area ref, but can actually be a cell ref, in
* which case it is interpreted as a 1x1 area ref. Other scalar values cause #VALUE! error. * which case it is interpreted as a 1x1 area ref. Other scalar values cause #VALUE! error.
*/ */
public static AreaEval resolveTableArrayArg(ValueEval eval) throws EvaluationException { public static TwoDEval resolveTableArrayArg(ValueEval eval) throws EvaluationException {
if (eval instanceof AreaEval) { if (eval instanceof TwoDEval) {
return (AreaEval) eval; return (TwoDEval) eval;
} }
if(eval instanceof RefEval) { if(eval instanceof RefEval) {

View File

@ -17,7 +17,6 @@
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.AreaEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval; import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.EvaluationException; 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.NumberEval;
@ -29,6 +28,7 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.functions.LookupUtils.CompareResult; import org.apache.poi.hssf.record.formula.functions.LookupUtils.CompareResult;
import org.apache.poi.hssf.record.formula.functions.LookupUtils.LookupValueComparer; import org.apache.poi.hssf.record.formula.functions.LookupUtils.LookupValueComparer;
import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector; import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector;
import org.apache.poi.ss.formula.TwoDEval;
/** /**
* Implementation for the MATCH() Excel function.<p/> * Implementation for the MATCH() Excel function.<p/>
@ -130,8 +130,8 @@ public final class Match extends Var2or3ArgFunction {
RefEval re = (RefEval) eval; RefEval re = (RefEval) eval;
return new SingleValueVector(re.getInnerValueEval()); return new SingleValueVector(re.getInnerValueEval());
} }
if (eval instanceof AreaEval) { if (eval instanceof TwoDEval) {
ValueVector result = LookupUtils.createVector((AreaEval)eval); ValueVector result = LookupUtils.createVector((TwoDEval)eval);
if (result == null) { if (result == null) {
throw new EvaluationException(ErrorEval.NA); throw new EvaluationException(ErrorEval.NA);
} }

View File

@ -21,7 +21,6 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
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.BlankEval;
import org.apache.poi.hssf.record.formula.eval.BoolEval; import org.apache.poi.hssf.record.formula.eval.BoolEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval; import org.apache.poi.hssf.record.formula.eval.ErrorEval;
@ -30,6 +29,7 @@ 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.RefEval;
import org.apache.poi.hssf.record.formula.eval.StringEval; import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.ss.formula.TwoDEval;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
@ -92,13 +92,13 @@ public final class Mode implements Function {
} }
private static void collectValues(ValueEval arg, List<Double> temp) throws EvaluationException { private static void collectValues(ValueEval arg, List<Double> temp) throws EvaluationException {
if (arg instanceof AreaEval) { if (arg instanceof TwoDEval) {
AreaEval ae = (AreaEval) arg; TwoDEval ae = (TwoDEval) arg;
int width = ae.getWidth(); int width = ae.getWidth();
int height = ae.getHeight(); int height = ae.getHeight();
for (int rrIx = 0; rrIx < height; rrIx++) { for (int rrIx = 0; rrIx < height; rrIx++) {
for (int rcIx = 0; rcIx < width; rcIx++) { for (int rcIx = 0; rcIx < width; rcIx++) {
ValueEval ve1 = ae.getRelativeValue(rrIx, rcIx); ValueEval ve1 = ae.getValue(rrIx, rcIx);
collectValue(ve1, temp, false); collectValue(ve1, temp, false);
} }
} }

View File

@ -17,11 +17,11 @@
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.AreaEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval; import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.NumberEval; 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.RefEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.ss.formula.TwoDEval;
/** /**
* Implementation for Excel ROWS function. * Implementation for Excel ROWS function.
@ -33,8 +33,8 @@ 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; int result;
if (arg0 instanceof AreaEval) { if (arg0 instanceof TwoDEval) {
result = ((AreaEval) arg0).getHeight(); result = ((TwoDEval) arg0).getHeight();
} else if (arg0 instanceof RefEval) { } else if (arg0 instanceof RefEval) {
result = 1; result = 1;
} else { // anything else is not valid argument } else { // anything else is not valid argument

View File

@ -26,6 +26,7 @@ import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
import org.apache.poi.hssf.record.formula.eval.RefEval; import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.StringEval; import org.apache.poi.hssf.record.formula.eval.StringEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.ss.formula.TwoDEval;
/** /**
@ -68,8 +69,8 @@ public final class Sumproduct implements Function {
if(firstArg instanceof RefEval) { if(firstArg instanceof RefEval) {
return evaluateSingleProduct(args); return evaluateSingleProduct(args);
} }
if(firstArg instanceof AreaEval) { if (firstArg instanceof TwoDEval) {
AreaEval ae = (AreaEval) firstArg; TwoDEval ae = (TwoDEval) firstArg;
if(ae.isRow() && ae.isColumn()) { if(ae.isRow() && ae.isColumn()) {
return evaluateSingleProduct(args); return evaluateSingleProduct(args);
} }
@ -120,7 +121,7 @@ public final class Sumproduct implements Function {
private static ValueEval evaluateAreaSumProduct(ValueEval[] evalArgs) throws EvaluationException { private static ValueEval evaluateAreaSumProduct(ValueEval[] evalArgs) throws EvaluationException {
int maxN = evalArgs.length; int maxN = evalArgs.length;
AreaEval[] args = new AreaEval[maxN]; TwoDEval[] args = new TwoDEval[maxN];
try { try {
System.arraycopy(evalArgs, 0, args, 0, maxN); System.arraycopy(evalArgs, 0, args, 0, maxN);
} catch (ArrayStoreException e) { } catch (ArrayStoreException e) {
@ -129,7 +130,7 @@ public final class Sumproduct implements Function {
} }
AreaEval firstArg = args[0]; TwoDEval firstArg = args[0];
int height = firstArg.getHeight(); int height = firstArg.getHeight();
int width = firstArg.getWidth(); // TODO - junit int width = firstArg.getWidth(); // TODO - junit
@ -150,7 +151,7 @@ public final class Sumproduct implements Function {
for (int rcIx=0; rcIx<width; rcIx++) { for (int rcIx=0; rcIx<width; rcIx++) {
double term = 1D; double term = 1D;
for(int n=0; n<maxN; n++) { for(int n=0; n<maxN; n++) {
double val = getProductTerm(args[n].getRelativeValue(rrIx, rcIx), false); double val = getProductTerm(args[n].getValue(rrIx, rcIx), false);
term *= val; term *= val;
} }
acc += term; acc += term;
@ -160,12 +161,12 @@ public final class Sumproduct implements Function {
return new NumberEval(acc); return new NumberEval(acc);
} }
private static void throwFirstError(AreaEval areaEval) throws EvaluationException { private static void throwFirstError(TwoDEval areaEval) throws EvaluationException {
int height = areaEval.getHeight(); int height = areaEval.getHeight();
int width = areaEval.getWidth(); int width = areaEval.getWidth();
for (int rrIx=0; rrIx<height; rrIx++) { for (int rrIx=0; rrIx<height; rrIx++) {
for (int rcIx=0; rcIx<width; rcIx++) { for (int rcIx=0; rcIx<width; rcIx++) {
ValueEval ve = areaEval.getRelativeValue(rrIx, rcIx); ValueEval ve = areaEval.getValue(rrIx, rcIx);
if (ve instanceof ErrorEval) { if (ve instanceof ErrorEval) {
throw new EvaluationException((ErrorEval) ve); throw new EvaluationException((ErrorEval) ve);
} }
@ -173,9 +174,9 @@ public final class Sumproduct implements Function {
} }
} }
private static boolean areasAllSameSize(AreaEval[] args, int height, int width) { private static boolean areasAllSameSize(TwoDEval[] args, int height, int width) {
for (int i = 0; i < args.length; i++) { for (int i = 0; i < args.length; i++) {
AreaEval areaEval = args[i]; TwoDEval areaEval = args[i];
// check that height and width match // check that height and width match
if(areaEval.getHeight() != height) { if(areaEval.getHeight() != height) {
return false; return false;

View File

@ -17,12 +17,12 @@
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.AreaEval;
import org.apache.poi.hssf.record.formula.eval.BoolEval; import org.apache.poi.hssf.record.formula.eval.BoolEval;
import org.apache.poi.hssf.record.formula.eval.EvaluationException; import org.apache.poi.hssf.record.formula.eval.EvaluationException;
import org.apache.poi.hssf.record.formula.eval.OperandResolver; import org.apache.poi.hssf.record.formula.eval.OperandResolver;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector; import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector;
import org.apache.poi.ss.formula.TwoDEval;
/** /**
* Implementation of the VLOOKUP() function.<p/> * Implementation of the VLOOKUP() function.<p/>
* *
@ -53,7 +53,7 @@ public final class Vlookup extends Var3or4ArgFunction {
// Evaluation order: // Evaluation order:
// arg0 lookup_value, arg1 table_array, arg3 range_lookup, find lookup value, arg2 col_index, fetch result // arg0 lookup_value, arg1 table_array, arg3 range_lookup, find lookup value, arg2 col_index, fetch result
ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
AreaEval tableArray = LookupUtils.resolveTableArrayArg(arg1); TwoDEval tableArray = LookupUtils.resolveTableArrayArg(arg1);
boolean isRangeLookup = LookupUtils.resolveRangeLookupArg(arg3, srcRowIndex, srcColumnIndex); boolean isRangeLookup = LookupUtils.resolveRangeLookupArg(arg3, srcRowIndex, srcColumnIndex);
int rowIndex = LookupUtils.lookupIndexOfValue(lookupValue, LookupUtils.createColumnVector(tableArray, 0), isRangeLookup); int rowIndex = LookupUtils.lookupIndexOfValue(lookupValue, LookupUtils.createColumnVector(tableArray, 0), isRangeLookup);
int colIndex = LookupUtils.resolveRowOrColIndexArg(arg2, srcRowIndex, srcColumnIndex); int colIndex = LookupUtils.resolveRowOrColIndexArg(arg2, srcRowIndex, srcColumnIndex);
@ -72,7 +72,7 @@ public final class Vlookup extends Var3or4ArgFunction {
* *
* @throws EvaluationException (#REF!) if colIndex is too high * @throws EvaluationException (#REF!) if colIndex is too high
*/ */
private ValueVector createResultColumnVector(AreaEval tableArray, int colIndex) throws EvaluationException { private ValueVector createResultColumnVector(TwoDEval tableArray, int colIndex) throws EvaluationException {
if(colIndex >= tableArray.getWidth()) { if(colIndex >= tableArray.getWidth()) {
throw EvaluationException.invalidRef(); throw EvaluationException.invalidRef();
} }

View File

@ -17,13 +17,13 @@
package org.apache.poi.hssf.record.formula.functions; package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.AreaEval;
import org.apache.poi.hssf.record.formula.eval.ErrorEval; import org.apache.poi.hssf.record.formula.eval.ErrorEval;
import org.apache.poi.hssf.record.formula.eval.EvaluationException; 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.NumberEval;
import org.apache.poi.hssf.record.formula.eval.RefEval; import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval; import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector; import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector;
import org.apache.poi.ss.formula.TwoDEval;
/** /**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt; * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
@ -71,10 +71,10 @@ public abstract class XYNumericFunction extends Fixed2ArgFunction {
} }
private static final class AreaValueArray extends ValueArray { private static final class AreaValueArray extends ValueArray {
private final AreaEval _ae; private final TwoDEval _ae;
private final int _width; private final int _width;
public AreaValueArray(AreaEval ae) { public AreaValueArray(TwoDEval ae) {
super(ae.getWidth() * ae.getHeight()); super(ae.getWidth() * ae.getHeight());
_ae = ae; _ae = ae;
_width = ae.getWidth(); _width = ae.getWidth();
@ -82,7 +82,7 @@ public abstract class XYNumericFunction extends Fixed2ArgFunction {
protected ValueEval getItemInternal(int index) { protected ValueEval getItemInternal(int index) {
int rowIx = index / _width; int rowIx = index / _width;
int colIx = index % _width; int colIx = index % _width;
return _ae.getRelativeValue(rowIx, colIx); return _ae.getValue(rowIx, colIx);
} }
} }
@ -166,8 +166,8 @@ public abstract class XYNumericFunction extends Fixed2ArgFunction {
if (arg instanceof ErrorEval) { if (arg instanceof ErrorEval) {
throw new EvaluationException((ErrorEval) arg); throw new EvaluationException((ErrorEval) arg);
} }
if (arg instanceof AreaEval) { if (arg instanceof TwoDEval) {
return new AreaValueArray((AreaEval) arg); return new AreaValueArray((TwoDEval) arg);
} }
if (arg instanceof RefEval) { if (arg instanceof RefEval) {
return new RefValueArray((RefEval) arg); return new RefValueArray((RefEval) arg);

View File

@ -0,0 +1,51 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.ss.formula;
import org.apache.poi.hssf.record.formula.eval.AreaEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
/**
* Common interface of {@link AreaEval} and {@link ArrayEval}
*
* @author Josh Micich
*/
public interface TwoDEval extends ValueEval {
/**
* @param row relative row index (zero based)
* @param col relative column index (zero based)
* @return element at the specified row and col position
*/
public ValueEval getValue(int row, int col);
int getWidth();
int getHeight();
/**
* @return <code>true</code> if the area has just a single row, this also includes
* the trivial case when the area has just a single cell.
*/
boolean isRow();
/**
* @return <code>true</code> if the area has just a single column, this also includes
* the trivial case when the area has just a single cell.
*/
boolean isColumn();
}