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;
import org.apache.poi.ss.formula.TwoDEval;
/**
* @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
@ -47,20 +48,6 @@ public interface AreaEval extends ValueEval {
*/
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
* <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() {
return _lastRow;
}
public final ValueEval getAbsoluteValue(int row, int col) {
int rowOffsetIx = row - _firstRow;
int colOffsetIx = col - _firstColumn;
@ -106,6 +105,10 @@ public abstract class AreaEvalBase implements AreaEval {
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 int getWidth() {

View File

@ -17,13 +17,13 @@
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.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.OperandResolver;
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:
@ -61,13 +61,13 @@ public abstract class BooleanFunction implements Function {
*/
for (int i=0, iSize=args.length; i<iSize; i++) {
ValueEval arg = args[i];
if (arg instanceof AreaEval) {
AreaEval ae = (AreaEval) arg;
if (arg instanceof TwoDEval) {
TwoDEval ae = (TwoDEval) arg;
int height = ae.getHeight();
int width = ae.getWidth();
for (int rrIx=0; rrIx<height; rrIx++) {
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);
if (tempVe != null) {
result = partialEvaluate(result, tempVe.booleanValue());

View File

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

View File

@ -17,9 +17,9 @@
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.ValueEval;
import org.apache.poi.ss.formula.TwoDEval;
/**
* 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
*/
public static int countMatchingCellsInArea(AreaEval areaEval, I_MatchPredicate criteriaPredicate) {
public static int countMatchingCellsInArea(TwoDEval areaEval, I_MatchPredicate criteriaPredicate) {
int result = 0;
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.getRelativeValue(rrIx, rcIx);
ValueEval ve = areaEval.getValue(rrIx, rcIx);
if(criteriaPredicate.matches(ve)) {
result++;
}
@ -69,8 +69,8 @@ final class CountUtils {
if (eval == null) {
throw new IllegalArgumentException("eval must not be null");
}
if (eval instanceof AreaEval) {
return CountUtils.countMatchingCellsInArea((AreaEval) eval, criteriaPredicate);
if (eval instanceof TwoDEval) {
return countMatchingCellsInArea((TwoDEval) eval, criteriaPredicate);
}
if (eval instanceof RefEval) {
return CountUtils.countMatchingCell((RefEval) eval, criteriaPredicate);

View File

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

View File

@ -17,12 +17,12 @@
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.EvaluationException;
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.functions.LookupUtils.ValueVector;
import org.apache.poi.ss.formula.TwoDEval;
/**
* Implementation of the HLOOKUP() function.<p/>
*
@ -53,7 +53,7 @@ public final class Hlookup extends Var3or4ArgFunction {
// Evaluation order:
// arg0 lookup_value, arg1 table_array, arg3 range_lookup, find lookup value, arg2 row_index, fetch result
ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
AreaEval tableArray = LookupUtils.resolveTableArrayArg(arg1);
TwoDEval tableArray = LookupUtils.resolveTableArrayArg(arg1);
boolean isRangeLookup = LookupUtils.resolveRangeLookupArg(arg3, srcRowIndex, srcColumnIndex);
int colIndex = LookupUtils.lookupIndexOfValue(lookupValue, LookupUtils.createRowVector(tableArray, 0), isRangeLookup);
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
*/
private ValueVector createResultColumnVector(AreaEval tableArray, int rowIndex) throws EvaluationException {
private ValueVector createResultColumnVector(TwoDEval tableArray, int rowIndex) throws EvaluationException {
if(rowIndex >= tableArray.getHeight()) {
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.RefEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.ss.formula.TwoDEval;
/**
* 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 ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
AreaEval reference = convertFirstArg(arg0);
TwoDEval reference = convertFirstArg(arg0);
boolean colArgWasPassed = false;
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,
ValueEval arg2) {
AreaEval reference = convertFirstArg(arg0);
TwoDEval reference = convertFirstArg(arg0);
boolean colArgWasPassed = true;
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
}
private static AreaEval convertFirstArg(ValueEval arg0) {
private static TwoDEval convertFirstArg(ValueEval arg0) {
ValueEval firstArg = arg0;
if (firstArg instanceof RefEval) {
// convert to area ref for simpler code in getValueFromArea()
return ((RefEval)firstArg).offset(0, 0, 0, 0);
}
if((firstArg instanceof AreaEval)) {
return (AreaEval) firstArg;
if((firstArg instanceof TwoDEval)) {
return (TwoDEval) firstArg;
}
// else the other variation of this function takes an array as the first argument
// 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
* 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 rowArgWasEmpty = pRowIx == 0;
boolean colArgWasEmpty = pColumnIx == 0;
@ -145,7 +146,13 @@ public final class Index implements Function2Arg, Function3Arg, Function4Arg {
}
} else if (ae.isColumn()) {
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 {
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
// if either arg is missing (or blank) the logic is similar to OperandResolver.getSingleValue()
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 {
rowIx = pRowIx-1;
}
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 {
columnIx = pColumnIx-1;
}
@ -185,7 +204,7 @@ public final class Index implements Function2Arg, Function3Arg, Function4Arg {
if (rowIx < 0 || columnIx < 0 || rowIx >= height || columnIx >= width) {
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;
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.OperandResolver;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector;
import org.apache.poi.ss.formula.TwoDEval;
/**
* Implementation of Excel function LOOKUP.<p/>
@ -48,8 +48,8 @@ public final class Lookup extends Var2or3ArgFunction {
ValueEval arg2) {
try {
ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
AreaEval aeLookupVector = LookupUtils.resolveTableArrayArg(arg1);
AreaEval aeResultVector = LookupUtils.resolveTableArrayArg(arg2);
TwoDEval aeLookupVector = LookupUtils.resolveTableArrayArg(arg1);
TwoDEval aeResultVector = LookupUtils.resolveTableArrayArg(arg2);
ValueVector lookupVector = createVector(aeLookupVector);
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);
if (result != null) {
return result;

View File

@ -17,7 +17,6 @@
package org.apache.poi.hssf.record.formula.functions;
import org.apache.poi.hssf.record.formula.eval.AreaEval;
import org.apache.poi.hssf.record.formula.eval.BlankEval;
import org.apache.poi.hssf.record.formula.eval.BoolEval;
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.StringEval;
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
@ -47,15 +47,14 @@ final class LookupUtils {
private static final class RowVector implements ValueVector {
private final AreaEval _tableArray;
private final TwoDEval _tableArray;
private final int _size;
private final int _rowIndex;
public RowVector(AreaEval tableArray, int rowIndex) {
public RowVector(TwoDEval tableArray, int rowIndex) {
_rowIndex = rowIndex;
int _rowAbsoluteIndex = tableArray.getFirstRow() + rowIndex;
if(!tableArray.containsRow(_rowAbsoluteIndex)) {
int lastRowIx = tableArray.getLastRow() - tableArray.getFirstRow();
int lastRowIx = tableArray.getHeight() - 1;
if(rowIndex < 0 || rowIndex > lastRowIx) {
throw new IllegalArgumentException("Specified row index (" + rowIndex
+ ") is outside the allowed range (0.." + lastRowIx + ")");
}
@ -68,7 +67,7 @@ final class LookupUtils {
throw new ArrayIndexOutOfBoundsException("Specified index (" + index
+ ") is outside the allowed range (0.." + (_size-1) + ")");
}
return _tableArray.getRelativeValue(_rowIndex, index);
return _tableArray.getValue(_rowIndex, index);
}
public int getSize() {
return _size;
@ -77,15 +76,14 @@ final class LookupUtils {
private static final class ColumnVector implements ValueVector {
private final AreaEval _tableArray;
private final TwoDEval _tableArray;
private final int _size;
private final int _columnIndex;
public ColumnVector(AreaEval tableArray, int columnIndex) {
public ColumnVector(TwoDEval tableArray, int columnIndex) {
_columnIndex = columnIndex;
int _columnAbsoluteIndex = tableArray.getFirstColumn() + columnIndex;
if(!tableArray.containsColumn((short)_columnAbsoluteIndex)) {
int lastColIx = tableArray.getLastColumn() - tableArray.getFirstColumn();
int lastColIx = tableArray.getWidth()-1;
if(columnIndex < 0 || columnIndex > lastColIx) {
throw new IllegalArgumentException("Specified column index (" + columnIndex
+ ") is outside the allowed range (0.." + lastColIx + ")");
}
@ -98,23 +96,23 @@ final class LookupUtils {
throw new ArrayIndexOutOfBoundsException("Specified index (" + index
+ ") is outside the allowed range (0.." + (_size-1) + ")");
}
return _tableArray.getRelativeValue(index, _columnIndex);
return _tableArray.getValue(index, _columnIndex);
}
public int getSize() {
return _size;
}
}
public static ValueVector createRowVector(AreaEval tableArray, int relativeRowIndex) {
public static ValueVector createRowVector(TwoDEval tableArray, int 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 <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()) {
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
* which case it is interpreted as a 1x1 area ref. Other scalar values cause #VALUE! error.
*/
public static AreaEval resolveTableArrayArg(ValueEval eval) throws EvaluationException {
if (eval instanceof AreaEval) {
return (AreaEval) eval;
public static TwoDEval resolveTableArrayArg(ValueEval eval) throws EvaluationException {
if (eval instanceof TwoDEval) {
return (TwoDEval) eval;
}
if(eval instanceof RefEval) {

View File

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

View File

@ -21,7 +21,6 @@ import java.util.ArrayList;
import java.util.Arrays;
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.BoolEval;
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.StringEval;
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;
@ -92,13 +92,13 @@ public final class Mode implements Function {
}
private static void collectValues(ValueEval arg, List<Double> temp) throws EvaluationException {
if (arg instanceof AreaEval) {
AreaEval ae = (AreaEval) arg;
if (arg instanceof TwoDEval) {
TwoDEval ae = (TwoDEval) arg;
int width = ae.getWidth();
int height = ae.getHeight();
for (int rrIx = 0; rrIx < height; rrIx++) {
for (int rcIx = 0; rcIx < width; rcIx++) {
ValueEval ve1 = ae.getRelativeValue(rrIx, rcIx);
ValueEval ve1 = ae.getValue(rrIx, rcIx);
collectValue(ve1, temp, false);
}
}

View File

@ -17,11 +17,11 @@
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.NumberEval;
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;
/**
* Implementation for Excel ROWS function.
@ -33,8 +33,8 @@ public final class Rows extends Fixed1ArgFunction {
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
int result;
if (arg0 instanceof AreaEval) {
result = ((AreaEval) arg0).getHeight();
if (arg0 instanceof TwoDEval) {
result = ((TwoDEval) arg0).getHeight();
} else if (arg0 instanceof RefEval) {
result = 1;
} 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.StringEval;
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) {
return evaluateSingleProduct(args);
}
if(firstArg instanceof AreaEval) {
AreaEval ae = (AreaEval) firstArg;
if (firstArg instanceof TwoDEval) {
TwoDEval ae = (TwoDEval) firstArg;
if(ae.isRow() && ae.isColumn()) {
return evaluateSingleProduct(args);
}
@ -120,7 +121,7 @@ public final class Sumproduct implements Function {
private static ValueEval evaluateAreaSumProduct(ValueEval[] evalArgs) throws EvaluationException {
int maxN = evalArgs.length;
AreaEval[] args = new AreaEval[maxN];
TwoDEval[] args = new TwoDEval[maxN];
try {
System.arraycopy(evalArgs, 0, args, 0, maxN);
} 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 width = firstArg.getWidth(); // TODO - junit
@ -150,7 +151,7 @@ public final class Sumproduct implements Function {
for (int rcIx=0; rcIx<width; rcIx++) {
double term = 1D;
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;
}
acc += term;
@ -160,12 +161,12 @@ public final class Sumproduct implements Function {
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 width = areaEval.getWidth();
for (int rrIx=0; rrIx<height; rrIx++) {
for (int rcIx=0; rcIx<width; rcIx++) {
ValueEval ve = areaEval.getRelativeValue(rrIx, rcIx);
ValueEval ve = areaEval.getValue(rrIx, rcIx);
if (ve instanceof ErrorEval) {
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++) {
AreaEval areaEval = args[i];
TwoDEval areaEval = args[i];
// check that height and width match
if(areaEval.getHeight() != height) {
return false;

View File

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

View File

@ -17,13 +17,13 @@
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.EvaluationException;
import org.apache.poi.hssf.record.formula.eval.NumberEval;
import org.apache.poi.hssf.record.formula.eval.RefEval;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
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;
@ -71,10 +71,10 @@ public abstract class XYNumericFunction extends Fixed2ArgFunction {
}
private static final class AreaValueArray extends ValueArray {
private final AreaEval _ae;
private final TwoDEval _ae;
private final int _width;
public AreaValueArray(AreaEval ae) {
public AreaValueArray(TwoDEval ae) {
super(ae.getWidth() * ae.getHeight());
_ae = ae;
_width = ae.getWidth();
@ -82,7 +82,7 @@ public abstract class XYNumericFunction extends Fixed2ArgFunction {
protected ValueEval getItemInternal(int index) {
int rowIx = 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) {
throw new EvaluationException((ErrorEval) arg);
}
if (arg instanceof AreaEval) {
return new AreaValueArray((AreaEval) arg);
if (arg instanceof TwoDEval) {
return new AreaValueArray((TwoDEval) arg);
}
if (arg instanceof RefEval) {
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();
}