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 [20/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/Lookup.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Lookup.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Lookup.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Lookup.java Sat May 22 20:56:44 2021
@@ -37,69 +37,69 @@ import org.apache.poi.ss.formula.TwoDEva
*/
public final class Lookup extends Var2or3ArgFunction {
- @Override
- public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
- // complex rules to choose lookupVector and resultVector from the single area ref
-
- try {
- /*
- The array form of LOOKUP is very similar to the HLOOKUP and VLOOKUP functions. The difference is that HLOOKUP searches for the value of lookup_value in the first row, VLOOKUP searches in the first column, and LOOKUP searches according to the dimensions of array.
- If array covers an area that is wider than it is tall (more columns than rows), LOOKUP searches for the value of lookup_value in the first row.
- If an array is square or is taller than it is wide (more rows than columns), LOOKUP searches in the first column.
- With the HLOOKUP and VLOOKUP functions, you can index down or across, but LOOKUP always selects the last value in the row or column.
- */
- ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
- TwoDEval lookupArray = LookupUtils.resolveTableArrayArg(arg1);
- ValueVector lookupVector;
- ValueVector resultVector;
-
- if (lookupArray.getWidth() > lookupArray.getHeight()) {
- // If array covers an area that is wider than it is tall (more columns than rows), LOOKUP searches for the value of lookup_value in the first row.
- lookupVector = createVector(lookupArray.getRow(0));
- resultVector = createVector(lookupArray.getRow(lookupArray.getHeight() - 1));
- } else {
- // If an array is square or is taller than it is wide (more rows than columns), LOOKUP searches in the first column.
- lookupVector = createVector(lookupArray.getColumn(0));
- resultVector = createVector(lookupArray.getColumn(lookupArray.getWidth() - 1));
- }
- // if a rectangular area reference was passed in as arg1, lookupVector and resultVector should be the same size
- assert (lookupVector.getSize() == resultVector.getSize());
-
- int index = LookupUtils.lookupIndexOfValue(lookupValue, lookupVector, true);
- return resultVector.getItem(index);
- } catch (final EvaluationException e) {
- return e.getErrorEval();
- }
- }
-
- @Override
- public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
- ValueEval arg2) {
- try {
- ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
- TwoDEval aeLookupVector = LookupUtils.resolveTableArrayArg(arg1);
- TwoDEval aeResultVector = LookupUtils.resolveTableArrayArg(arg2);
-
- ValueVector lookupVector = createVector(aeLookupVector);
- ValueVector resultVector = createVector(aeResultVector);
- if(lookupVector.getSize() > resultVector.getSize()) {
- // Excel seems to handle this by accessing past the end of the result vector.
- throw new RuntimeException("Lookup vector and result vector of differing sizes not supported yet");
- }
- int index = LookupUtils.lookupIndexOfValue(lookupValue, lookupVector, true);
-
- return resultVector.getItem(index);
- } catch (EvaluationException e) {
- return e.getErrorEval();
- }
- }
-
- private static ValueVector createVector(TwoDEval ae) {
- ValueVector result = LookupUtils.createVector(ae);
- if (result != null) {
- return result;
- }
- // extra complexity required to emulate the way LOOKUP can handles these abnormal cases.
- throw new RuntimeException("non-vector lookup or result areas not supported yet");
- }
+ @Override
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
+ // complex rules to choose lookupVector and resultVector from the single area ref
+
+ try {
+ /*
+ The array form of LOOKUP is very similar to the HLOOKUP and VLOOKUP functions. The difference is that HLOOKUP searches for the value of lookup_value in the first row, VLOOKUP searches in the first column, and LOOKUP searches according to the dimensions of array.
+ If array covers an area that is wider than it is tall (more columns than rows), LOOKUP searches for the value of lookup_value in the first row.
+ If an array is square or is taller than it is wide (more rows than columns), LOOKUP searches in the first column.
+ With the HLOOKUP and VLOOKUP functions, you can index down or across, but LOOKUP always selects the last value in the row or column.
+ */
+ ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
+ TwoDEval lookupArray = LookupUtils.resolveTableArrayArg(arg1);
+ ValueVector lookupVector;
+ ValueVector resultVector;
+
+ if (lookupArray.getWidth() > lookupArray.getHeight()) {
+ // If array covers an area that is wider than it is tall (more columns than rows), LOOKUP searches for the value of lookup_value in the first row.
+ lookupVector = createVector(lookupArray.getRow(0));
+ resultVector = createVector(lookupArray.getRow(lookupArray.getHeight() - 1));
+ } else {
+ // If an array is square or is taller than it is wide (more rows than columns), LOOKUP searches in the first column.
+ lookupVector = createVector(lookupArray.getColumn(0));
+ resultVector = createVector(lookupArray.getColumn(lookupArray.getWidth() - 1));
+ }
+ // if a rectangular area reference was passed in as arg1, lookupVector and resultVector should be the same size
+ assert (lookupVector.getSize() == resultVector.getSize());
+
+ int index = LookupUtils.lookupIndexOfValue(lookupValue, lookupVector, true);
+ return resultVector.getItem(index);
+ } catch (final EvaluationException e) {
+ return e.getErrorEval();
+ }
+ }
+
+ @Override
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+ ValueEval arg2) {
+ try {
+ ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
+ TwoDEval aeLookupVector = LookupUtils.resolveTableArrayArg(arg1);
+ TwoDEval aeResultVector = LookupUtils.resolveTableArrayArg(arg2);
+
+ ValueVector lookupVector = createVector(aeLookupVector);
+ ValueVector resultVector = createVector(aeResultVector);
+ if(lookupVector.getSize() > resultVector.getSize()) {
+ // Excel seems to handle this by accessing past the end of the result vector.
+ throw new RuntimeException("Lookup vector and result vector of differing sizes not supported yet");
+ }
+ int index = LookupUtils.lookupIndexOfValue(lookupValue, lookupVector, true);
+
+ return resultVector.getItem(index);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+ }
+
+ private static ValueVector createVector(TwoDEval ae) {
+ ValueVector result = LookupUtils.createVector(ae);
+ if (result != null) {
+ return result;
+ }
+ // extra complexity required to emulate the way LOOKUP can handles these abnormal cases.
+ throw new RuntimeException("non-vector lookup or result areas not supported yet");
+ }
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/LookupUtils.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/LookupUtils.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/LookupUtils.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/LookupUtils.java Sat May 22 20:56:44 2021
@@ -38,76 +38,76 @@ import org.apache.poi.ss.formula.eval.Va
*/
final class LookupUtils {
- /**
- * Represents a single row or column within an {@code AreaEval}.
- */
- public interface ValueVector {
- ValueEval getItem(int index);
- int getSize();
- }
-
-
- private static final class RowVector implements ValueVector {
-
- private final TwoDEval _tableArray;
- private final int _size;
- private final int _rowIndex;
-
- public RowVector(TwoDEval tableArray, int rowIndex) {
- _rowIndex = rowIndex;
- int lastRowIx = tableArray.getHeight() - 1;
- if(rowIndex < 0 || rowIndex > lastRowIx) {
- throw new IllegalArgumentException("Specified row index (" + rowIndex
- + ") is outside the allowed range (0.." + lastRowIx + ")");
- }
- _tableArray = tableArray;
- _size = tableArray.getWidth();
- }
-
- @Override
- public ValueEval getItem(int index) {
- if(index > _size) {
- throw new ArrayIndexOutOfBoundsException("Specified index (" + index
- + ") is outside the allowed range (0.." + (_size-1) + ")");
- }
- return _tableArray.getValue(_rowIndex, index);
- }
- @Override
- public int getSize() {
- return _size;
- }
- }
-
- private static final class ColumnVector implements ValueVector {
-
- private final TwoDEval _tableArray;
- private final int _size;
- private final int _columnIndex;
-
- public ColumnVector(TwoDEval tableArray, int columnIndex) {
- _columnIndex = columnIndex;
- int lastColIx = tableArray.getWidth()-1;
- if(columnIndex < 0 || columnIndex > lastColIx) {
- throw new IllegalArgumentException("Specified column index (" + columnIndex
- + ") is outside the allowed range (0.." + lastColIx + ")");
- }
- _tableArray = tableArray;
- _size = _tableArray.getHeight();
- }
-
- @Override
- public ValueEval getItem(int index) {
- if(index > _size) {
- throw new ArrayIndexOutOfBoundsException("Specified index (" + index
- + ") is outside the allowed range (0.." + (_size-1) + ")");
- }
- return _tableArray.getValue(index, _columnIndex);
- }
- @Override
- public int getSize() {
- return _size;
- }
- }
+ /**
+ * Represents a single row or column within an {@code AreaEval}.
+ */
+ public interface ValueVector {
+ ValueEval getItem(int index);
+ int getSize();
+ }
+
+
+ private static final class RowVector implements ValueVector {
+
+ private final TwoDEval _tableArray;
+ private final int _size;
+ private final int _rowIndex;
+
+ public RowVector(TwoDEval tableArray, int rowIndex) {
+ _rowIndex = rowIndex;
+ int lastRowIx = tableArray.getHeight() - 1;
+ if(rowIndex < 0 || rowIndex > lastRowIx) {
+ throw new IllegalArgumentException("Specified row index (" + rowIndex
+ + ") is outside the allowed range (0.." + lastRowIx + ")");
+ }
+ _tableArray = tableArray;
+ _size = tableArray.getWidth();
+ }
+
+ @Override
+ public ValueEval getItem(int index) {
+ if(index > _size) {
+ throw new ArrayIndexOutOfBoundsException("Specified index (" + index
+ + ") is outside the allowed range (0.." + (_size-1) + ")");
+ }
+ return _tableArray.getValue(_rowIndex, index);
+ }
+ @Override
+ public int getSize() {
+ return _size;
+ }
+ }
+
+ private static final class ColumnVector implements ValueVector {
+
+ private final TwoDEval _tableArray;
+ private final int _size;
+ private final int _columnIndex;
+
+ public ColumnVector(TwoDEval tableArray, int columnIndex) {
+ _columnIndex = columnIndex;
+ int lastColIx = tableArray.getWidth()-1;
+ if(columnIndex < 0 || columnIndex > lastColIx) {
+ throw new IllegalArgumentException("Specified column index (" + columnIndex
+ + ") is outside the allowed range (0.." + lastColIx + ")");
+ }
+ _tableArray = tableArray;
+ _size = _tableArray.getHeight();
+ }
+
+ @Override
+ public ValueEval getItem(int index) {
+ if(index > _size) {
+ throw new ArrayIndexOutOfBoundsException("Specified index (" + index
+ + ") is outside the allowed range (0.." + (_size-1) + ")");
+ }
+ return _tableArray.getValue(index, _columnIndex);
+ }
+ @Override
+ public int getSize() {
+ return _size;
+ }
+ }
private static final class SheetVector implements ValueVector {
private final RefEval _re;
@@ -119,7 +119,7 @@ final class LookupUtils {
}
@Override
- public ValueEval getItem(int index) {
+ public ValueEval getItem(int index) {
if(index >= _size) {
throw new ArrayIndexOutOfBoundsException("Specified index (" + index
+ ") is outside the allowed range (0.." + (_size-1) + ")");
@@ -128,78 +128,78 @@ final class LookupUtils {
return _re.getInnerValueEval(sheetIndex);
}
@Override
- public int getSize() {
+ public int getSize() {
return _size;
}
}
- public static ValueVector createRowVector(TwoDEval tableArray, int relativeRowIndex) {
- return new RowVector(tableArray, relativeRowIndex);
- }
- public static ValueVector createColumnVector(TwoDEval tableArray, int relativeColumnIndex) {
- return new ColumnVector(tableArray, relativeColumnIndex);
- }
- /**
- * @return {@code null} if the supplied area is neither a single row nor a single column
- */
- public static ValueVector createVector(TwoDEval ae) {
- if (ae.isColumn()) {
- return createColumnVector(ae, 0);
- }
- if (ae.isRow()) {
- return createRowVector(ae, 0);
- }
- return null;
- }
-
- public static ValueVector createVector(RefEval re) {
- return new SheetVector(re);
- }
-
- /**
- * Enumeration to support <b>4</b> valued comparison results.<p>
- * Excel lookup functions have complex behaviour in the case where the lookup array has mixed
- * types, and/or is unordered. Contrary to suggestions in some Excel documentation, there
- * does not appear to be a universal ordering across types. The binary search algorithm used
- * changes behaviour when the evaluated 'mid' value has a different type to the lookup value.<p>
- *
- * A simple int might have done the same job, but there is risk in confusion with the well
- * known {@code Comparable.compareTo()} and {@code Comparator.compare()} which both use
- * a ubiquitous 3 value result encoding.
- */
- public static final class CompareResult {
- private final boolean _isTypeMismatch;
- private final boolean _isLessThan;
- private final boolean _isEqual;
- private final boolean _isGreaterThan;
-
- private CompareResult(boolean isTypeMismatch, int simpleCompareResult) {
- if(isTypeMismatch) {
- _isTypeMismatch = true;
- _isLessThan = false;
- _isEqual = false;
- _isGreaterThan = false;
- } else {
- _isTypeMismatch = false;
- _isLessThan = simpleCompareResult < 0;
- _isEqual = simpleCompareResult == 0;
- _isGreaterThan = simpleCompareResult > 0;
- }
- }
- public static final CompareResult TYPE_MISMATCH = new CompareResult(true, 0);
- public static final CompareResult LESS_THAN = new CompareResult(false, -1);
- public static final CompareResult EQUAL = new CompareResult(false, 0);
- public static final CompareResult GREATER_THAN = new CompareResult(false, +1);
-
- public static CompareResult valueOf(int simpleCompareResult) {
- if(simpleCompareResult < 0) {
- return LESS_THAN;
- }
- if(simpleCompareResult > 0) {
- return GREATER_THAN;
- }
- return EQUAL;
- }
+ public static ValueVector createRowVector(TwoDEval tableArray, int relativeRowIndex) {
+ return new RowVector(tableArray, relativeRowIndex);
+ }
+ public static ValueVector createColumnVector(TwoDEval tableArray, int relativeColumnIndex) {
+ return new ColumnVector(tableArray, relativeColumnIndex);
+ }
+ /**
+ * @return {@code null} if the supplied area is neither a single row nor a single column
+ */
+ public static ValueVector createVector(TwoDEval ae) {
+ if (ae.isColumn()) {
+ return createColumnVector(ae, 0);
+ }
+ if (ae.isRow()) {
+ return createRowVector(ae, 0);
+ }
+ return null;
+ }
+
+ public static ValueVector createVector(RefEval re) {
+ return new SheetVector(re);
+ }
+
+ /**
+ * Enumeration to support <b>4</b> valued comparison results.<p>
+ * Excel lookup functions have complex behaviour in the case where the lookup array has mixed
+ * types, and/or is unordered. Contrary to suggestions in some Excel documentation, there
+ * does not appear to be a universal ordering across types. The binary search algorithm used
+ * changes behaviour when the evaluated 'mid' value has a different type to the lookup value.<p>
+ *
+ * A simple int might have done the same job, but there is risk in confusion with the well
+ * known {@code Comparable.compareTo()} and {@code Comparator.compare()} which both use
+ * a ubiquitous 3 value result encoding.
+ */
+ public static final class CompareResult {
+ private final boolean _isTypeMismatch;
+ private final boolean _isLessThan;
+ private final boolean _isEqual;
+ private final boolean _isGreaterThan;
+
+ private CompareResult(boolean isTypeMismatch, int simpleCompareResult) {
+ if(isTypeMismatch) {
+ _isTypeMismatch = true;
+ _isLessThan = false;
+ _isEqual = false;
+ _isGreaterThan = false;
+ } else {
+ _isTypeMismatch = false;
+ _isLessThan = simpleCompareResult < 0;
+ _isEqual = simpleCompareResult == 0;
+ _isGreaterThan = simpleCompareResult > 0;
+ }
+ }
+ public static final CompareResult TYPE_MISMATCH = new CompareResult(true, 0);
+ public static final CompareResult LESS_THAN = new CompareResult(false, -1);
+ public static final CompareResult EQUAL = new CompareResult(false, 0);
+ public static final CompareResult GREATER_THAN = new CompareResult(false, +1);
+
+ public static CompareResult valueOf(int simpleCompareResult) {
+ if(simpleCompareResult < 0) {
+ return LESS_THAN;
+ }
+ if(simpleCompareResult > 0) {
+ return GREATER_THAN;
+ }
+ return EQUAL;
+ }
public static CompareResult valueOf(boolean matches) {
if(matches) {
@@ -209,78 +209,78 @@ final class LookupUtils {
}
- public boolean isTypeMismatch() {
- return _isTypeMismatch;
- }
- public boolean isLessThan() {
- return _isLessThan;
- }
- public boolean isEqual() {
- return _isEqual;
- }
- public boolean isGreaterThan() {
- return _isGreaterThan;
- }
- public String toString() {
- return getClass().getName() + " [" +
- formatAsString() +
- "]";
- }
-
- private String formatAsString() {
- if(_isTypeMismatch) {
- return "TYPE_MISMATCH";
- }
- if(_isLessThan) {
- return "LESS_THAN";
- }
- if(_isEqual) {
- return "EQUAL";
- }
- if(_isGreaterThan) {
- return "GREATER_THAN";
- }
- // toString must be reliable
- return "??error??";
- }
- }
-
- public interface LookupValueComparer {
- /**
- * @return one of 4 instances or {@code CompareResult}: {@code LESS_THAN}, {@code EQUAL},
- * {@code GREATER_THAN} or {@code TYPE_MISMATCH}
- */
- CompareResult compareTo(ValueEval other);
- }
-
- private static abstract class LookupValueComparerBase implements LookupValueComparer {
-
- private final Class<? extends ValueEval> _targetClass;
- protected LookupValueComparerBase(ValueEval targetValue) {
- if(targetValue == null) {
- throw new RuntimeException("targetValue cannot be null");
- }
- _targetClass = targetValue.getClass();
- }
- @Override
- public final CompareResult compareTo(ValueEval other) {
- if (other == null) {
- throw new RuntimeException("compare to value cannot be null");
- }
- if (_targetClass != other.getClass()) {
- return CompareResult.TYPE_MISMATCH;
- }
- return compareSameType(other);
- }
- public String toString() {
- return getClass().getName() + " [" +
- getValueAsString() +
- "]";
- }
- protected abstract CompareResult compareSameType(ValueEval other);
- /** used only for debug purposes */
- protected abstract String getValueAsString();
- }
+ public boolean isTypeMismatch() {
+ return _isTypeMismatch;
+ }
+ public boolean isLessThan() {
+ return _isLessThan;
+ }
+ public boolean isEqual() {
+ return _isEqual;
+ }
+ public boolean isGreaterThan() {
+ return _isGreaterThan;
+ }
+ public String toString() {
+ return getClass().getName() + " [" +
+ formatAsString() +
+ "]";
+ }
+
+ private String formatAsString() {
+ if(_isTypeMismatch) {
+ return "TYPE_MISMATCH";
+ }
+ if(_isLessThan) {
+ return "LESS_THAN";
+ }
+ if(_isEqual) {
+ return "EQUAL";
+ }
+ if(_isGreaterThan) {
+ return "GREATER_THAN";
+ }
+ // toString must be reliable
+ return "??error??";
+ }
+ }
+
+ public interface LookupValueComparer {
+ /**
+ * @return one of 4 instances or {@code CompareResult}: {@code LESS_THAN}, {@code EQUAL},
+ * {@code GREATER_THAN} or {@code TYPE_MISMATCH}
+ */
+ CompareResult compareTo(ValueEval other);
+ }
+
+ private static abstract class LookupValueComparerBase implements LookupValueComparer {
+
+ private final Class<? extends ValueEval> _targetClass;
+ protected LookupValueComparerBase(ValueEval targetValue) {
+ if(targetValue == null) {
+ throw new RuntimeException("targetValue cannot be null");
+ }
+ _targetClass = targetValue.getClass();
+ }
+ @Override
+ public final CompareResult compareTo(ValueEval other) {
+ if (other == null) {
+ throw new RuntimeException("compare to value cannot be null");
+ }
+ if (_targetClass != other.getClass()) {
+ return CompareResult.TYPE_MISMATCH;
+ }
+ return compareSameType(other);
+ }
+ public String toString() {
+ return getClass().getName() + " [" +
+ getValueAsString() +
+ "]";
+ }
+ protected abstract CompareResult compareSameType(ValueEval other);
+ /** used only for debug purposes */
+ protected abstract String getValueAsString();
+ }
private static final class StringLookupComparer extends LookupValueComparerBase {
@@ -291,15 +291,15 @@ final class LookupUtils {
private final boolean _isMatchFunction;
protected StringLookupComparer(StringEval se, boolean matchExact, boolean isMatchFunction) {
- super(se);
- _value = se.getStringValue();
+ super(se);
+ _value = se.getStringValue();
_wildCardPattern = Countif.StringMatcher.getWildCardPattern(_value);
_matchExact = matchExact;
_isMatchFunction = isMatchFunction;
- }
+ }
- @Override
- protected CompareResult compareSameType(ValueEval other) {
+ @Override
+ protected CompareResult compareSameType(ValueEval other) {
StringEval se = (StringEval) other;
String stringValue = se.getStringValue();
@@ -314,363 +314,363 @@ final class LookupUtils {
}
return CompareResult.valueOf(_value.compareToIgnoreCase(stringValue));
- }
- @Override
- protected String getValueAsString() {
- return _value;
- }
- }
- private static final class NumberLookupComparer extends LookupValueComparerBase {
- private final double _value;
-
- protected NumberLookupComparer(NumberEval ne) {
- super(ne);
- _value = ne.getNumberValue();
- }
- @Override
- protected CompareResult compareSameType(ValueEval other) {
- NumberEval ne = (NumberEval) other;
- return CompareResult.valueOf(Double.compare(_value, ne.getNumberValue()));
- }
- @Override
- protected String getValueAsString() {
- return String.valueOf(_value);
- }
- }
- private static final class BooleanLookupComparer extends LookupValueComparerBase {
- private final boolean _value;
-
- protected BooleanLookupComparer(BoolEval be) {
- super(be);
- _value = be.getBooleanValue();
- }
- @Override
- protected CompareResult compareSameType(ValueEval other) {
- BoolEval be = (BoolEval) other;
- boolean otherVal = be.getBooleanValue();
- if(_value == otherVal) {
- return CompareResult.EQUAL;
- }
- // TRUE > FALSE
- if(_value) {
- return CompareResult.GREATER_THAN;
- }
- return CompareResult.LESS_THAN;
- }
- @Override
- protected String getValueAsString() {
- return String.valueOf(_value);
- }
- }
-
- /**
- * Processes the third argument to VLOOKUP, or HLOOKUP (<b>col_index_num</b>
- * or <b>row_index_num</b> respectively).<br>
- * Sample behaviour:
- * <table>
- * <caption>Sample behaviour</caption>
- * <tr><th>Input Return</th><th>Value </th><th>Thrown Error</th></tr>
- * <tr><td>5</td><td>4</td><td> </td></tr>
- * <tr><td>2.9</td><td>2</td><td> </td></tr>
- * <tr><td>"5"</td><td>4</td><td> </td></tr>
- * <tr><td>"2.18e1"</td><td>21</td><td> </td></tr>
- * <tr><td>"-$2"</td><td>-3</td><td>*</td></tr>
- * <tr><td>FALSE</td><td>-1</td><td>*</td></tr>
- * <tr><td>TRUE</td><td>0</td><td> </td></tr>
- * <tr><td>"TRUE"</td><td> </td><td>#REF!</td></tr>
- * <tr><td>"abc"</td><td> </td><td>#REF!</td></tr>
- * <tr><td>""</td><td> </td><td>#REF!</td></tr>
- * <tr><td><blank></td><td> </td><td>#VALUE!</td></tr>
- * </table><br>
- *
- * Note - out of range errors (result index too high) are handled by the caller.
- * @return column or row index as a zero-based value, never negative.
- * @throws EvaluationException when the specified arg cannot be coerced to a non-negative integer
- */
- public static int resolveRowOrColIndexArg(ValueEval rowColIndexArg, int srcCellRow, int srcCellCol) throws EvaluationException {
- if(rowColIndexArg == null) {
- throw new IllegalArgumentException("argument must not be null");
- }
-
- ValueEval veRowColIndexArg;
- try {
- veRowColIndexArg = OperandResolver.getSingleValue(rowColIndexArg, srcCellRow, (short)srcCellCol);
- } catch (EvaluationException e) {
- // All errors get translated to #REF!
- throw EvaluationException.invalidRef();
- }
- int oneBasedIndex;
- if(veRowColIndexArg instanceof StringEval) {
- StringEval se = (StringEval) veRowColIndexArg;
- String strVal = se.getStringValue();
- Double dVal = OperandResolver.parseDouble(strVal);
- if(dVal == null) {
- // String does not resolve to a number. Raise #REF! error.
- throw EvaluationException.invalidRef();
- // This includes text booleans "TRUE" and "FALSE". They are not valid.
- }
- // else - numeric value parses OK
- }
- // actual BoolEval values get interpreted as FALSE->0 and TRUE->1
- oneBasedIndex = OperandResolver.coerceValueToInt(veRowColIndexArg);
- if (oneBasedIndex < 1) {
- // note this is asymmetric with the errors when the index is too large (#REF!)
- throw EvaluationException.invalidValue();
- }
- return oneBasedIndex - 1; // convert to zero based
- }
-
-
-
- /**
- * 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 TwoDEval resolveTableArrayArg(ValueEval eval) throws EvaluationException {
- if (eval instanceof TwoDEval) {
- return (TwoDEval) eval;
- }
-
- if(eval instanceof RefEval) {
- RefEval refEval = (RefEval) eval;
- // Make this cell ref look like a 1x1 area ref.
-
- // It doesn't matter if eval is a 2D or 3D ref, because that detail is never asked of AreaEval.
- return refEval.offset(0, 0, 0, 0);
- }
- throw EvaluationException.invalidValue();
- }
-
-
- /**
- * Resolves the last (optional) parameter (<b>range_lookup</b>) to the VLOOKUP and HLOOKUP functions.
- * @param rangeLookupArg must not be {@code null}
- */
- public static boolean resolveRangeLookupArg(ValueEval rangeLookupArg, int srcCellRow, int srcCellCol) throws EvaluationException {
-
- ValueEval valEval = OperandResolver.getSingleValue(rangeLookupArg, srcCellRow, srcCellCol);
- if(valEval == MissingArgEval.instance) {
- // Tricky:
- // forth arg exists but is not supplied: "=VLOOKUP(A1,A2:A4,2,)"
- return false;
- }
- if(valEval instanceof BlankEval) {
- // Tricky:
- // fourth arg supplied but evaluates to blank
- // this does not get the default value
- return false;
- }
- if(valEval instanceof BoolEval) {
- // Happy day flow
- BoolEval boolEval = (BoolEval) valEval;
- return boolEval.getBooleanValue();
- }
-
- if (valEval instanceof StringEval) {
- String stringValue = ((StringEval) valEval).getStringValue();
- if(stringValue.length() < 1) {
- // More trickiness:
- // Empty string is not the same as BlankEval. It causes #VALUE! error
- throw EvaluationException.invalidValue();
- }
- // TODO move parseBoolean to OperandResolver
- Boolean b = Countif.parseBoolean(stringValue);
- if(b != null) {
- // string converted to boolean OK
- return b;
- }
- // Even more trickiness:
- // Note - even if the StringEval represents a number value (for example "1"),
- // Excel does not resolve it to a boolean.
- throw EvaluationException.invalidValue();
- // This is in contrast to the code below,, where NumberEvals values (for
- // example 0.01) *do* resolve to equivalent boolean values.
- }
- if (valEval instanceof NumericValueEval) {
- NumericValueEval nve = (NumericValueEval) valEval;
- // zero is FALSE, everything else is TRUE
- return 0.0 != nve.getNumberValue();
- }
- throw new RuntimeException("Unexpected eval type (" + valEval + ")");
- }
-
- public static int lookupIndexOfValue(ValueEval lookupValue, ValueVector vector, boolean isRangeLookup) throws EvaluationException {
- LookupValueComparer lookupComparer = createLookupComparer(lookupValue, isRangeLookup, false);
- int result;
- if(isRangeLookup) {
- result = performBinarySearch(vector, lookupComparer);
- } else {
- result = lookupIndexOfExactValue(lookupComparer, vector);
- }
- if(result < 0) {
- throw new EvaluationException(ErrorEval.NA);
- }
- return result;
- }
-
-
- /**
- * Finds first (lowest index) exact occurrence of specified value.
- * @param lookupComparer the value to be found in column or row vector
- * @param vector the values to be searched. For VLOOKUP this is the first column of the
- * tableArray. For HLOOKUP this is the first row of the tableArray.
- * @return zero based index into the vector, -1 if value cannot be found
- */
- private static int lookupIndexOfExactValue(LookupValueComparer lookupComparer, ValueVector vector) {
-
- // find first occurrence of lookup value
- int size = vector.getSize();
- for (int i = 0; i < size; i++) {
- if(lookupComparer.compareTo(vector.getItem(i)).isEqual()) {
- return i;
- }
- }
- return -1;
- }
-
-
- /**
- * Encapsulates some standard binary search functionality so the unusual Excel behaviour can
- * be clearly distinguished.
- */
- private static final class BinarySearchIndexes {
-
- private int _lowIx;
- private int _highIx;
-
- public BinarySearchIndexes(int highIx) {
- _lowIx = -1;
- _highIx = highIx;
- }
-
- /**
- * @return -1 if the search range is empty
- */
- public int getMidIx() {
- int ixDiff = _highIx - _lowIx;
- if(ixDiff < 2) {
- return -1;
- }
- return _lowIx + (ixDiff / 2);
- }
-
- public int getLowIx() {
- return _lowIx;
- }
- public int getHighIx() {
- return _highIx;
- }
- public void narrowSearch(int midIx, boolean isLessThan) {
- if(isLessThan) {
- _highIx = midIx;
- } else {
- _lowIx = midIx;
- }
- }
- }
- /**
- * Excel has funny behaviour when the some elements in the search vector are the wrong type.
- *
- */
- private static int performBinarySearch(ValueVector vector, LookupValueComparer lookupComparer) {
- // both low and high indexes point to values assumed too low and too high.
- BinarySearchIndexes bsi = new BinarySearchIndexes(vector.getSize());
-
- while(true) {
- int midIx = bsi.getMidIx();
-
- if(midIx < 0) {
- return bsi.getLowIx();
- }
- CompareResult cr = lookupComparer.compareTo(vector.getItem(midIx));
- if(cr.isTypeMismatch()) {
- int newMidIx = handleMidValueTypeMismatch(lookupComparer, vector, bsi, midIx);
- if(newMidIx < 0) {
- continue;
- }
- midIx = newMidIx;
- cr = lookupComparer.compareTo(vector.getItem(midIx));
- }
- if(cr.isEqual()) {
- return findLastIndexInRunOfEqualValues(lookupComparer, vector, midIx, bsi.getHighIx());
- }
- bsi.narrowSearch(midIx, cr.isLessThan());
- }
- }
- /**
- * Excel seems to handle mismatched types initially by just stepping 'mid' ix forward to the
- * first compatible value.
- * @param midIx 'mid' index (value which has the wrong type)
- * @return usually -1, signifying that the BinarySearchIndex has been narrowed to the new mid
- * index. Zero or greater signifies that an exact match for the lookup value was found
- */
- private static int handleMidValueTypeMismatch(LookupValueComparer lookupComparer, ValueVector vector,
- BinarySearchIndexes bsi, int midIx) {
- int newMid = midIx;
- int highIx = bsi.getHighIx();
-
- while(true) {
- newMid++;
- if(newMid == highIx) {
- // every element from midIx to highIx was the wrong type
- // move highIx down to the low end of the mid values
- bsi.narrowSearch(midIx, true);
- return -1;
- }
- CompareResult cr = lookupComparer.compareTo(vector.getItem(newMid));
- if(cr.isLessThan() && newMid == highIx-1) {
- // move highIx down to the low end of the mid values
- bsi.narrowSearch(midIx, true);
- return -1;
- // but only when "newMid == highIx-1"? slightly weird.
- // It would seem more efficient to always do this.
- }
- if(cr.isTypeMismatch()) {
- // keep stepping over values until the right type is found
- continue;
- }
- if(cr.isEqual()) {
- return newMid;
- }
- // Note - if moving highIx down (due to lookup<vector[newMid]),
- // this execution path only moves highIx it down as far as newMid, not midIx,
- // which would be more efficient.
- bsi.narrowSearch(newMid, cr.isLessThan());
- return -1;
- }
- }
- /**
- * Once the binary search has found a single match, (V/H)LOOKUP steps one by one over subsequent
- * values to choose the last matching item.
- */
- private static int findLastIndexInRunOfEqualValues(LookupValueComparer lookupComparer, ValueVector vector,
- int firstFoundIndex, int maxIx) {
- for(int i=firstFoundIndex+1; i<maxIx; i++) {
- if(!lookupComparer.compareTo(vector.getItem(i)).isEqual()) {
- return i-1;
- }
- }
- return maxIx - 1;
- }
-
- public static LookupValueComparer createLookupComparer(ValueEval lookupValue, boolean matchExact, boolean isMatchFunction) {
-
- if (lookupValue == BlankEval.instance) {
- // blank eval translates to zero
- // Note - a blank eval in the lookup column/row never matches anything
- // empty string in the lookup column/row can only be matched by explicit empty string
- return new NumberLookupComparer(NumberEval.ZERO);
- }
- if (lookupValue instanceof StringEval) {
+ }
+ @Override
+ protected String getValueAsString() {
+ return _value;
+ }
+ }
+ private static final class NumberLookupComparer extends LookupValueComparerBase {
+ private final double _value;
+
+ protected NumberLookupComparer(NumberEval ne) {
+ super(ne);
+ _value = ne.getNumberValue();
+ }
+ @Override
+ protected CompareResult compareSameType(ValueEval other) {
+ NumberEval ne = (NumberEval) other;
+ return CompareResult.valueOf(Double.compare(_value, ne.getNumberValue()));
+ }
+ @Override
+ protected String getValueAsString() {
+ return String.valueOf(_value);
+ }
+ }
+ private static final class BooleanLookupComparer extends LookupValueComparerBase {
+ private final boolean _value;
+
+ protected BooleanLookupComparer(BoolEval be) {
+ super(be);
+ _value = be.getBooleanValue();
+ }
+ @Override
+ protected CompareResult compareSameType(ValueEval other) {
+ BoolEval be = (BoolEval) other;
+ boolean otherVal = be.getBooleanValue();
+ if(_value == otherVal) {
+ return CompareResult.EQUAL;
+ }
+ // TRUE > FALSE
+ if(_value) {
+ return CompareResult.GREATER_THAN;
+ }
+ return CompareResult.LESS_THAN;
+ }
+ @Override
+ protected String getValueAsString() {
+ return String.valueOf(_value);
+ }
+ }
+
+ /**
+ * Processes the third argument to VLOOKUP, or HLOOKUP (<b>col_index_num</b>
+ * or <b>row_index_num</b> respectively).<br>
+ * Sample behaviour:
+ * <table>
+ * <caption>Sample behaviour</caption>
+ * <tr><th>Input Return</th><th>Value </th><th>Thrown Error</th></tr>
+ * <tr><td>5</td><td>4</td><td> </td></tr>
+ * <tr><td>2.9</td><td>2</td><td> </td></tr>
+ * <tr><td>"5"</td><td>4</td><td> </td></tr>
+ * <tr><td>"2.18e1"</td><td>21</td><td> </td></tr>
+ * <tr><td>"-$2"</td><td>-3</td><td>*</td></tr>
+ * <tr><td>FALSE</td><td>-1</td><td>*</td></tr>
+ * <tr><td>TRUE</td><td>0</td><td> </td></tr>
+ * <tr><td>"TRUE"</td><td> </td><td>#REF!</td></tr>
+ * <tr><td>"abc"</td><td> </td><td>#REF!</td></tr>
+ * <tr><td>""</td><td> </td><td>#REF!</td></tr>
+ * <tr><td><blank></td><td> </td><td>#VALUE!</td></tr>
+ * </table><br>
+ *
+ * Note - out of range errors (result index too high) are handled by the caller.
+ * @return column or row index as a zero-based value, never negative.
+ * @throws EvaluationException when the specified arg cannot be coerced to a non-negative integer
+ */
+ public static int resolveRowOrColIndexArg(ValueEval rowColIndexArg, int srcCellRow, int srcCellCol) throws EvaluationException {
+ if(rowColIndexArg == null) {
+ throw new IllegalArgumentException("argument must not be null");
+ }
+
+ ValueEval veRowColIndexArg;
+ try {
+ veRowColIndexArg = OperandResolver.getSingleValue(rowColIndexArg, srcCellRow, (short)srcCellCol);
+ } catch (EvaluationException e) {
+ // All errors get translated to #REF!
+ throw EvaluationException.invalidRef();
+ }
+ int oneBasedIndex;
+ if(veRowColIndexArg instanceof StringEval) {
+ StringEval se = (StringEval) veRowColIndexArg;
+ String strVal = se.getStringValue();
+ Double dVal = OperandResolver.parseDouble(strVal);
+ if(dVal == null) {
+ // String does not resolve to a number. Raise #REF! error.
+ throw EvaluationException.invalidRef();
+ // This includes text booleans "TRUE" and "FALSE". They are not valid.
+ }
+ // else - numeric value parses OK
+ }
+ // actual BoolEval values get interpreted as FALSE->0 and TRUE->1
+ oneBasedIndex = OperandResolver.coerceValueToInt(veRowColIndexArg);
+ if (oneBasedIndex < 1) {
+ // note this is asymmetric with the errors when the index is too large (#REF!)
+ throw EvaluationException.invalidValue();
+ }
+ return oneBasedIndex - 1; // convert to zero based
+ }
+
+
+
+ /**
+ * 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 TwoDEval resolveTableArrayArg(ValueEval eval) throws EvaluationException {
+ if (eval instanceof TwoDEval) {
+ return (TwoDEval) eval;
+ }
+
+ if(eval instanceof RefEval) {
+ RefEval refEval = (RefEval) eval;
+ // Make this cell ref look like a 1x1 area ref.
+
+ // It doesn't matter if eval is a 2D or 3D ref, because that detail is never asked of AreaEval.
+ return refEval.offset(0, 0, 0, 0);
+ }
+ throw EvaluationException.invalidValue();
+ }
+
+
+ /**
+ * Resolves the last (optional) parameter (<b>range_lookup</b>) to the VLOOKUP and HLOOKUP functions.
+ * @param rangeLookupArg must not be {@code null}
+ */
+ public static boolean resolveRangeLookupArg(ValueEval rangeLookupArg, int srcCellRow, int srcCellCol) throws EvaluationException {
+
+ ValueEval valEval = OperandResolver.getSingleValue(rangeLookupArg, srcCellRow, srcCellCol);
+ if(valEval == MissingArgEval.instance) {
+ // Tricky:
+ // forth arg exists but is not supplied: "=VLOOKUP(A1,A2:A4,2,)"
+ return false;
+ }
+ if(valEval instanceof BlankEval) {
+ // Tricky:
+ // fourth arg supplied but evaluates to blank
+ // this does not get the default value
+ return false;
+ }
+ if(valEval instanceof BoolEval) {
+ // Happy day flow
+ BoolEval boolEval = (BoolEval) valEval;
+ return boolEval.getBooleanValue();
+ }
+
+ if (valEval instanceof StringEval) {
+ String stringValue = ((StringEval) valEval).getStringValue();
+ if(stringValue.length() < 1) {
+ // More trickiness:
+ // Empty string is not the same as BlankEval. It causes #VALUE! error
+ throw EvaluationException.invalidValue();
+ }
+ // TODO move parseBoolean to OperandResolver
+ Boolean b = Countif.parseBoolean(stringValue);
+ if(b != null) {
+ // string converted to boolean OK
+ return b;
+ }
+ // Even more trickiness:
+ // Note - even if the StringEval represents a number value (for example "1"),
+ // Excel does not resolve it to a boolean.
+ throw EvaluationException.invalidValue();
+ // This is in contrast to the code below,, where NumberEvals values (for
+ // example 0.01) *do* resolve to equivalent boolean values.
+ }
+ if (valEval instanceof NumericValueEval) {
+ NumericValueEval nve = (NumericValueEval) valEval;
+ // zero is FALSE, everything else is TRUE
+ return 0.0 != nve.getNumberValue();
+ }
+ throw new RuntimeException("Unexpected eval type (" + valEval + ")");
+ }
+
+ public static int lookupIndexOfValue(ValueEval lookupValue, ValueVector vector, boolean isRangeLookup) throws EvaluationException {
+ LookupValueComparer lookupComparer = createLookupComparer(lookupValue, isRangeLookup, false);
+ int result;
+ if(isRangeLookup) {
+ result = performBinarySearch(vector, lookupComparer);
+ } else {
+ result = lookupIndexOfExactValue(lookupComparer, vector);
+ }
+ if(result < 0) {
+ throw new EvaluationException(ErrorEval.NA);
+ }
+ return result;
+ }
+
+
+ /**
+ * Finds first (lowest index) exact occurrence of specified value.
+ * @param lookupComparer the value to be found in column or row vector
+ * @param vector the values to be searched. For VLOOKUP this is the first column of the
+ * tableArray. For HLOOKUP this is the first row of the tableArray.
+ * @return zero based index into the vector, -1 if value cannot be found
+ */
+ private static int lookupIndexOfExactValue(LookupValueComparer lookupComparer, ValueVector vector) {
+
+ // find first occurrence of lookup value
+ int size = vector.getSize();
+ for (int i = 0; i < size; i++) {
+ if(lookupComparer.compareTo(vector.getItem(i)).isEqual()) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+
+ /**
+ * Encapsulates some standard binary search functionality so the unusual Excel behaviour can
+ * be clearly distinguished.
+ */
+ private static final class BinarySearchIndexes {
+
+ private int _lowIx;
+ private int _highIx;
+
+ public BinarySearchIndexes(int highIx) {
+ _lowIx = -1;
+ _highIx = highIx;
+ }
+
+ /**
+ * @return -1 if the search range is empty
+ */
+ public int getMidIx() {
+ int ixDiff = _highIx - _lowIx;
+ if(ixDiff < 2) {
+ return -1;
+ }
+ return _lowIx + (ixDiff / 2);
+ }
+
+ public int getLowIx() {
+ return _lowIx;
+ }
+ public int getHighIx() {
+ return _highIx;
+ }
+ public void narrowSearch(int midIx, boolean isLessThan) {
+ if(isLessThan) {
+ _highIx = midIx;
+ } else {
+ _lowIx = midIx;
+ }
+ }
+ }
+ /**
+ * Excel has funny behaviour when the some elements in the search vector are the wrong type.
+ *
+ */
+ private static int performBinarySearch(ValueVector vector, LookupValueComparer lookupComparer) {
+ // both low and high indexes point to values assumed too low and too high.
+ BinarySearchIndexes bsi = new BinarySearchIndexes(vector.getSize());
+
+ while(true) {
+ int midIx = bsi.getMidIx();
+
+ if(midIx < 0) {
+ return bsi.getLowIx();
+ }
+ CompareResult cr = lookupComparer.compareTo(vector.getItem(midIx));
+ if(cr.isTypeMismatch()) {
+ int newMidIx = handleMidValueTypeMismatch(lookupComparer, vector, bsi, midIx);
+ if(newMidIx < 0) {
+ continue;
+ }
+ midIx = newMidIx;
+ cr = lookupComparer.compareTo(vector.getItem(midIx));
+ }
+ if(cr.isEqual()) {
+ return findLastIndexInRunOfEqualValues(lookupComparer, vector, midIx, bsi.getHighIx());
+ }
+ bsi.narrowSearch(midIx, cr.isLessThan());
+ }
+ }
+ /**
+ * Excel seems to handle mismatched types initially by just stepping 'mid' ix forward to the
+ * first compatible value.
+ * @param midIx 'mid' index (value which has the wrong type)
+ * @return usually -1, signifying that the BinarySearchIndex has been narrowed to the new mid
+ * index. Zero or greater signifies that an exact match for the lookup value was found
+ */
+ private static int handleMidValueTypeMismatch(LookupValueComparer lookupComparer, ValueVector vector,
+ BinarySearchIndexes bsi, int midIx) {
+ int newMid = midIx;
+ int highIx = bsi.getHighIx();
+
+ while(true) {
+ newMid++;
+ if(newMid == highIx) {
+ // every element from midIx to highIx was the wrong type
+ // move highIx down to the low end of the mid values
+ bsi.narrowSearch(midIx, true);
+ return -1;
+ }
+ CompareResult cr = lookupComparer.compareTo(vector.getItem(newMid));
+ if(cr.isLessThan() && newMid == highIx-1) {
+ // move highIx down to the low end of the mid values
+ bsi.narrowSearch(midIx, true);
+ return -1;
+ // but only when "newMid == highIx-1"? slightly weird.
+ // It would seem more efficient to always do this.
+ }
+ if(cr.isTypeMismatch()) {
+ // keep stepping over values until the right type is found
+ continue;
+ }
+ if(cr.isEqual()) {
+ return newMid;
+ }
+ // Note - if moving highIx down (due to lookup<vector[newMid]),
+ // this execution path only moves highIx it down as far as newMid, not midIx,
+ // which would be more efficient.
+ bsi.narrowSearch(newMid, cr.isLessThan());
+ return -1;
+ }
+ }
+ /**
+ * Once the binary search has found a single match, (V/H)LOOKUP steps one by one over subsequent
+ * values to choose the last matching item.
+ */
+ private static int findLastIndexInRunOfEqualValues(LookupValueComparer lookupComparer, ValueVector vector,
+ int firstFoundIndex, int maxIx) {
+ for(int i=firstFoundIndex+1; i<maxIx; i++) {
+ if(!lookupComparer.compareTo(vector.getItem(i)).isEqual()) {
+ return i-1;
+ }
+ }
+ return maxIx - 1;
+ }
+
+ public static LookupValueComparer createLookupComparer(ValueEval lookupValue, boolean matchExact, boolean isMatchFunction) {
+
+ if (lookupValue == BlankEval.instance) {
+ // blank eval translates to zero
+ // Note - a blank eval in the lookup column/row never matches anything
+ // empty string in the lookup column/row can only be matched by explicit empty string
+ return new NumberLookupComparer(NumberEval.ZERO);
+ }
+ if (lookupValue instanceof StringEval) {
//TODO eventually here return a WildcardStringLookupComparer
- return new StringLookupComparer((StringEval) lookupValue, matchExact, isMatchFunction);
- }
- if (lookupValue instanceof NumberEval) {
- return new NumberLookupComparer((NumberEval) lookupValue);
- }
- if (lookupValue instanceof BoolEval) {
- return new BooleanLookupComparer((BoolEval) lookupValue);
- }
- throw new IllegalArgumentException("Bad lookup value type (" + lookupValue.getClass().getName() + ")");
- }
+ return new StringLookupComparer((StringEval) lookupValue, matchExact, isMatchFunction);
+ }
+ if (lookupValue instanceof NumberEval) {
+ return new NumberLookupComparer((NumberEval) lookupValue);
+ }
+ if (lookupValue instanceof BoolEval) {
+ return new BooleanLookupComparer((BoolEval) lookupValue);
+ }
+ throw new IllegalArgumentException("Bad lookup value type (" + lookupValue.getClass().getName() + ")");
+ }
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Match.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Match.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Match.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Match.java Sat May 22 20:56:44 2021
@@ -65,185 +65,185 @@ import org.apache.poi.ss.formula.functio
*/
public final class Match extends Var2or3ArgFunction {
- @Override
- public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
- // default match_type is 1.0
- return eval(srcRowIndex, srcColumnIndex, arg0, arg1, 1.0);
- }
-
-
- @Override
- public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
- ValueEval arg2) {
-
- double match_type;
-
- try {
- match_type = evaluateMatchTypeArg(arg2, srcRowIndex, srcColumnIndex);
- } catch (EvaluationException e) {
- // Excel/MATCH() seems to have slightly abnormal handling of errors with
- // the last parameter. Errors do not propagate up. Every error gets
- // translated into #REF!
- return ErrorEval.REF_INVALID;
- }
-
- return eval(srcRowIndex, srcColumnIndex, arg0, arg1, match_type);
- }
-
- private static ValueEval eval(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
- double match_type) {
- boolean matchExact = match_type == 0;
- // Note - Excel does not strictly require -1 and +1
- boolean findLargestLessThanOrEqual = match_type > 0;
-
- try {
- ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
- ValueVector lookupRange = evaluateLookupRange(arg1);
- int index = findIndexOfValue(lookupValue, lookupRange, matchExact, findLargestLessThanOrEqual);
- return new NumberEval(index + 1.); // +1 to convert to 1-based
- } catch (EvaluationException e) {
- return e.getErrorEval();
- }
- }
-
- private static final class SingleValueVector implements ValueVector {
-
- private final ValueEval _value;
-
- public SingleValueVector(ValueEval value) {
- _value = value;
- }
+ @Override
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
+ // default match_type is 1.0
+ return eval(srcRowIndex, srcColumnIndex, arg0, arg1, 1.0);
+ }
+
+
+ @Override
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+ ValueEval arg2) {
+
+ double match_type;
+
+ try {
+ match_type = evaluateMatchTypeArg(arg2, srcRowIndex, srcColumnIndex);
+ } catch (EvaluationException e) {
+ // Excel/MATCH() seems to have slightly abnormal handling of errors with
+ // the last parameter. Errors do not propagate up. Every error gets
+ // translated into #REF!
+ return ErrorEval.REF_INVALID;
+ }
+
+ return eval(srcRowIndex, srcColumnIndex, arg0, arg1, match_type);
+ }
+
+ private static ValueEval eval(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
+ double match_type) {
+ boolean matchExact = match_type == 0;
+ // Note - Excel does not strictly require -1 and +1
+ boolean findLargestLessThanOrEqual = match_type > 0;
+
+ try {
+ ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
+ ValueVector lookupRange = evaluateLookupRange(arg1);
+ int index = findIndexOfValue(lookupValue, lookupRange, matchExact, findLargestLessThanOrEqual);
+ return new NumberEval(index + 1.); // +1 to convert to 1-based
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+ }
+
+ private static final class SingleValueVector implements ValueVector {
+
+ private final ValueEval _value;
+
+ public SingleValueVector(ValueEval value) {
+ _value = value;
+ }
- @Override
+ @Override
public ValueEval getItem(int index) {
- if (index != 0) {
- throw new RuntimeException("Invalid index ("
- + index + ") only zero is allowed");
- }
- return _value;
- }
-
- @Override
- public int getSize() {
- return 1;
- }
- }
-
- private static ValueVector evaluateLookupRange(ValueEval eval) throws EvaluationException {
- if (eval instanceof RefEval) {
- RefEval re = (RefEval) eval;
- if (re.getNumberOfSheets() == 1) {
- return new SingleValueVector(re.getInnerValueEval(re.getFirstSheetIndex()));
- } else {
- return LookupUtils.createVector(re);
- }
- }
- if (eval instanceof TwoDEval) {
- ValueVector result = LookupUtils.createVector((TwoDEval)eval);
- if (result == null) {
- throw new EvaluationException(ErrorEval.NA);
- }
- return result;
- }
-
- // Error handling for lookup_range arg is also unusual
- if(eval instanceof NumericValueEval) {
- throw new EvaluationException(ErrorEval.NA);
- }
- if (eval instanceof StringEval) {
- StringEval se = (StringEval) eval;
- Double d = OperandResolver.parseDouble(se.getStringValue());
- if(d == null) {
- // plain string
- throw new EvaluationException(ErrorEval.VALUE_INVALID);
- }
- // else looks like a number
- throw new EvaluationException(ErrorEval.NA);
- }
- throw new RuntimeException("Unexpected eval type (" + eval + ")");
- }
-
-
-
- private static double evaluateMatchTypeArg(ValueEval arg, int srcCellRow, int srcCellCol)
- throws EvaluationException {
- ValueEval match_type = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
-
- if(match_type instanceof ErrorEval) {
- throw new EvaluationException((ErrorEval)match_type);
- }
- if(match_type instanceof NumericValueEval) {
- NumericValueEval ne = (NumericValueEval) match_type;
- return ne.getNumberValue();
- }
- if (match_type instanceof StringEval) {
- StringEval se = (StringEval) match_type;
- Double d = OperandResolver.parseDouble(se.getStringValue());
- if(d == null) {
- // plain string
- throw new EvaluationException(ErrorEval.VALUE_INVALID);
- }
- // if the string parses as a number, it is OK
- return d;
- }
- if (match_type instanceof MissingArgEval || match_type instanceof BlankEval) {
- // Excel-Online ignores a missing match-type and
- // uses the default-value instead
- return 1;
- }
- throw new RuntimeException("Unexpected match_type type (" + match_type.getClass().getName() + ")");
- }
-
- /**
- * @return zero based index
- */
- private static int findIndexOfValue(ValueEval lookupValue, ValueVector lookupRange,
- boolean matchExact, boolean findLargestLessThanOrEqual) throws EvaluationException {
-
- LookupValueComparer lookupComparer = createLookupComparer(lookupValue, matchExact);
-
- int size = lookupRange.getSize();
- if(matchExact) {
- for (int i = 0; i < size; i++) {
- if(lookupComparer.compareTo(lookupRange.getItem(i)).isEqual()) {
- return i;
- }
- }
- throw new EvaluationException(ErrorEval.NA);
- }
-
- if(findLargestLessThanOrEqual) {
- // Note - backward iteration
- for (int i = size - 1; i>=0; i--) {
- CompareResult cmp = lookupComparer.compareTo(lookupRange.getItem(i));
- if(cmp.isTypeMismatch()) {
- continue;
- }
- if(!cmp.isLessThan()) {
- return i;
- }
- }
- throw new EvaluationException(ErrorEval.NA);
- }
-
- // else - find smallest greater than or equal to
- // TODO - is binary search used for (match_type==+1) ?
- for (int i = 0; i<size; i++) {
- CompareResult cmp = lookupComparer.compareTo(lookupRange.getItem(i));
- if(cmp.isEqual()) {
- return i;
- }
- if(cmp.isGreaterThan()) {
- if(i<1) {
- throw new EvaluationException(ErrorEval.NA);
- }
- return i-1;
- }
- }
- return size-1;
- }
-
- private static LookupValueComparer createLookupComparer(ValueEval lookupValue, boolean matchExact) {
- return LookupUtils.createLookupComparer(lookupValue, matchExact, true);
- }
+ if (index != 0) {
+ throw new RuntimeException("Invalid index ("
+ + index + ") only zero is allowed");
+ }
+ return _value;
+ }
+
+ @Override
+ public int getSize() {
+ return 1;
+ }
+ }
+
+ private static ValueVector evaluateLookupRange(ValueEval eval) throws EvaluationException {
+ if (eval instanceof RefEval) {
+ RefEval re = (RefEval) eval;
+ if (re.getNumberOfSheets() == 1) {
+ return new SingleValueVector(re.getInnerValueEval(re.getFirstSheetIndex()));
+ } else {
+ return LookupUtils.createVector(re);
+ }
+ }
+ if (eval instanceof TwoDEval) {
+ ValueVector result = LookupUtils.createVector((TwoDEval)eval);
+ if (result == null) {
+ throw new EvaluationException(ErrorEval.NA);
+ }
+ return result;
+ }
+
+ // Error handling for lookup_range arg is also unusual
+ if(eval instanceof NumericValueEval) {
+ throw new EvaluationException(ErrorEval.NA);
+ }
+ if (eval instanceof StringEval) {
+ StringEval se = (StringEval) eval;
+ Double d = OperandResolver.parseDouble(se.getStringValue());
+ if(d == null) {
+ // plain string
+ throw new EvaluationException(ErrorEval.VALUE_INVALID);
+ }
+ // else looks like a number
+ throw new EvaluationException(ErrorEval.NA);
+ }
+ throw new RuntimeException("Unexpected eval type (" + eval + ")");
+ }
+
+
+
+ private static double evaluateMatchTypeArg(ValueEval arg, int srcCellRow, int srcCellCol)
+ throws EvaluationException {
+ ValueEval match_type = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
+
+ if(match_type instanceof ErrorEval) {
+ throw new EvaluationException((ErrorEval)match_type);
+ }
+ if(match_type instanceof NumericValueEval) {
+ NumericValueEval ne = (NumericValueEval) match_type;
+ return ne.getNumberValue();
+ }
+ if (match_type instanceof StringEval) {
+ StringEval se = (StringEval) match_type;
+ Double d = OperandResolver.parseDouble(se.getStringValue());
+ if(d == null) {
+ // plain string
+ throw new EvaluationException(ErrorEval.VALUE_INVALID);
+ }
+ // if the string parses as a number, it is OK
+ return d;
+ }
+ if (match_type instanceof MissingArgEval || match_type instanceof BlankEval) {
+ // Excel-Online ignores a missing match-type and
+ // uses the default-value instead
+ return 1;
+ }
+ throw new RuntimeException("Unexpected match_type type (" + match_type.getClass().getName() + ")");
+ }
+
+ /**
+ * @return zero based index
+ */
+ private static int findIndexOfValue(ValueEval lookupValue, ValueVector lookupRange,
+ boolean matchExact, boolean findLargestLessThanOrEqual) throws EvaluationException {
+
+ LookupValueComparer lookupComparer = createLookupComparer(lookupValue, matchExact);
+
+ int size = lookupRange.getSize();
+ if(matchExact) {
+ for (int i = 0; i < size; i++) {
+ if(lookupComparer.compareTo(lookupRange.getItem(i)).isEqual()) {
+ return i;
+ }
+ }
+ throw new EvaluationException(ErrorEval.NA);
+ }
+
+ if(findLargestLessThanOrEqual) {
+ // Note - backward iteration
+ for (int i = size - 1; i>=0; i--) {
+ CompareResult cmp = lookupComparer.compareTo(lookupRange.getItem(i));
+ if(cmp.isTypeMismatch()) {
+ continue;
+ }
+ if(!cmp.isLessThan()) {
+ return i;
+ }
+ }
+ throw new EvaluationException(ErrorEval.NA);
+ }
+
+ // else - find smallest greater than or equal to
+ // TODO - is binary search used for (match_type==+1) ?
+ for (int i = 0; i<size; i++) {
+ CompareResult cmp = lookupComparer.compareTo(lookupRange.getItem(i));
+ if(cmp.isEqual()) {
+ return i;
+ }
+ if(cmp.isGreaterThan()) {
+ if(i<1) {
+ throw new EvaluationException(ErrorEval.NA);
+ }
+ return i-1;
+ }
+ }
+ return size-1;
+ }
+
+ private static LookupValueComparer createLookupComparer(ValueEval lookupValue, boolean matchExact) {
+ return LookupUtils.createLookupComparer(lookupValue, matchExact, true);
+ }
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/MinaMaxa.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/MinaMaxa.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/MinaMaxa.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/MinaMaxa.java Sat May 22 20:56:44 2021
@@ -19,18 +19,18 @@ package org.apache.poi.ss.formula.functi
public abstract class MinaMaxa extends MultiOperandNumericFunction {
- protected MinaMaxa() {
- super(true, true);
- }
+ protected MinaMaxa() {
+ super(true, true);
+ }
- public static final Function MAXA = new MinaMaxa() {
- protected double evaluate(double[] values) {
- return values.length > 0 ? MathX.max(values) : 0;
- }
- };
- public static final Function MINA = new MinaMaxa() {
- protected double evaluate(double[] values) {
- return values.length > 0 ? MathX.min(values) : 0;
- }
- };
+ public static final Function MAXA = new MinaMaxa() {
+ protected double evaluate(double[] values) {
+ return values.length > 0 ? MathX.max(values) : 0;
+ }
+ };
+ public static final Function MINA = new MinaMaxa() {
+ protected double evaluate(double[] values) {
+ return values.length > 0 ? MathX.min(values) : 0;
+ }
+ };
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Mode.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Mode.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Mode.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Mode.java Sat May 22 20:56:44 2021
@@ -33,101 +33,101 @@ import org.apache.poi.ss.formula.eval.Va
public final class Mode implements Function {
- /**
- * if v is zero length or contains no duplicates, return value is
- * Double.NaN. Else returns the value that occurs most times and if there is
- * a tie, returns the first such value.
- *
- * @param v An array of values on which the mode is computed.
- */
- public static double evaluate(double[] v) throws EvaluationException {
- if (v.length < 2) {
- throw new EvaluationException(ErrorEval.NA);
- }
-
- // very naive impl, may need to be optimized
- int[] counts = new int[v.length];
- Arrays.fill(counts, 1);
- for (int i = 0, iSize = v.length; i < iSize; i++) {
- for (int j = i + 1, jSize = v.length; j < jSize; j++) {
- if (v[i] == v[j])
- counts[i]++;
- }
- }
- double maxv = 0;
- int maxc = 0;
- for (int i = 0, iSize = counts.length; i < iSize; i++) {
- if (counts[i] > maxc) {
- maxv = v[i];
- maxc = counts[i];
- }
- }
- if (maxc > 1) {
- return maxv;
- }
- throw new EvaluationException(ErrorEval.NA);
-
- }
-
- public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
- double result;
- try {
- List<Double> temp = new ArrayList<>();
- for (ValueEval arg : args) {
- collectValues(arg, temp);
- }
- double[] values = new double[temp.size()];
- for (int i = 0; i < values.length; i++) {
- values[i] = temp.get(i).doubleValue();
- }
- result = evaluate(values);
- } catch (EvaluationException e) {
- return e.getErrorEval();
- }
- return new NumberEval(result);
- }
-
- private static void collectValues(ValueEval arg, List<Double> temp) throws EvaluationException {
- 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.getValue(rrIx, rcIx);
- collectValue(ve1, temp, false);
- }
- }
- return;
- }
- if (arg instanceof RefEval) {
- RefEval re = (RefEval) arg;
- final int firstSheetIndex = re.getFirstSheetIndex();
- final int lastSheetIndex = re.getLastSheetIndex();
- for (int sIx = firstSheetIndex; sIx <= lastSheetIndex; sIx++) {
- collectValue(re.getInnerValueEval(sIx), temp, true);
- }
- return;
- }
- collectValue(arg, temp, true);
-
- }
-
- private static void collectValue(ValueEval arg, List<Double> temp, boolean mustBeNumber)
- throws EvaluationException {
- if (arg instanceof ErrorEval) {
- throw new EvaluationException((ErrorEval) arg);
- }
- if (arg == BlankEval.instance || arg instanceof BoolEval || arg instanceof StringEval) {
- if (mustBeNumber) {
- throw EvaluationException.invalidValue();
- }
- return;
- }
- if (arg instanceof NumberEval) {
- temp.add(Double.valueOf(((NumberEval) arg).getNumberValue()));
- return;
- }
- throw new RuntimeException("Unexpected value type (" + arg.getClass().getName() + ")");
- }
+ /**
+ * if v is zero length or contains no duplicates, return value is
+ * Double.NaN. Else returns the value that occurs most times and if there is
+ * a tie, returns the first such value.
+ *
+ * @param v An array of values on which the mode is computed.
+ */
+ public static double evaluate(double[] v) throws EvaluationException {
+ if (v.length < 2) {
+ throw new EvaluationException(ErrorEval.NA);
+ }
+
+ // very naive impl, may need to be optimized
+ int[] counts = new int[v.length];
+ Arrays.fill(counts, 1);
+ for (int i = 0, iSize = v.length; i < iSize; i++) {
+ for (int j = i + 1, jSize = v.length; j < jSize; j++) {
+ if (v[i] == v[j])
+ counts[i]++;
+ }
+ }
+ double maxv = 0;
+ int maxc = 0;
+ for (int i = 0, iSize = counts.length; i < iSize; i++) {
+ if (counts[i] > maxc) {
+ maxv = v[i];
+ maxc = counts[i];
+ }
+ }
+ if (maxc > 1) {
+ return maxv;
+ }
+ throw new EvaluationException(ErrorEval.NA);
+
+ }
+
+ public ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
+ double result;
+ try {
+ List<Double> temp = new ArrayList<>();
+ for (ValueEval arg : args) {
+ collectValues(arg, temp);
+ }
+ double[] values = new double[temp.size()];
+ for (int i = 0; i < values.length; i++) {
+ values[i] = temp.get(i).doubleValue();
+ }
+ result = evaluate(values);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+ return new NumberEval(result);
+ }
+
+ private static void collectValues(ValueEval arg, List<Double> temp) throws EvaluationException {
+ 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.getValue(rrIx, rcIx);
+ collectValue(ve1, temp, false);
+ }
+ }
+ return;
+ }
+ if (arg instanceof RefEval) {
+ RefEval re = (RefEval) arg;
+ final int firstSheetIndex = re.getFirstSheetIndex();
+ final int lastSheetIndex = re.getLastSheetIndex();
+ for (int sIx = firstSheetIndex; sIx <= lastSheetIndex; sIx++) {
+ collectValue(re.getInnerValueEval(sIx), temp, true);
+ }
+ return;
+ }
+ collectValue(arg, temp, true);
+
+ }
+
+ private static void collectValue(ValueEval arg, List<Double> temp, boolean mustBeNumber)
+ throws EvaluationException {
+ if (arg instanceof ErrorEval) {
+ throw new EvaluationException((ErrorEval) arg);
+ }
+ if (arg == BlankEval.instance || arg instanceof BoolEval || arg instanceof StringEval) {
+ if (mustBeNumber) {
+ throw EvaluationException.invalidValue();
+ }
+ return;
+ }
+ if (arg instanceof NumberEval) {
+ temp.add(Double.valueOf(((NumberEval) arg).getNumberValue()));
+ return;
+ }
+ throw new RuntimeException("Unexpected value type (" + arg.getClass().getName() + ")");
+ }
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Na.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Na.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Na.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Na.java Sat May 22 20:56:44 2021
@@ -24,7 +24,7 @@ import org.apache.poi.ss.formula.eval.Va
* Implementation of Excel function NA()
*/
public final class Na {
- public static ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
- return args.length != 0 ? ErrorEval.VALUE_INVALID : ErrorEval.NA;
- }
+ public static ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
+ return args.length != 0 ? ErrorEval.VALUE_INVALID : ErrorEval.NA;
+ }
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/NotImplementedFunction.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/NotImplementedFunction.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/NotImplementedFunction.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/NotImplementedFunction.java Sat May 22 20:56:44 2021
@@ -28,18 +28,18 @@ import org.apache.poi.ss.formula.eval.Va
* yet implemented.
*/
public final class NotImplementedFunction implements Function {
- private final String _functionName;
- protected NotImplementedFunction() {
- _functionName = getClass().getName();
- }
- public NotImplementedFunction(String name) {
- _functionName = name;
- }
+ private final String _functionName;
+ protected NotImplementedFunction() {
+ _functionName = getClass().getName();
+ }
+ public NotImplementedFunction(String name) {
+ _functionName = name;
+ }
- public ValueEval evaluate(ValueEval[] operands, int srcRow, int srcCol) {
- throw new NotImplementedFunctionException(_functionName);
- }
- public String getFunctionName() {
- return _functionName;
- }
+ public ValueEval evaluate(ValueEval[] operands, int srcRow, int srcCol) {
+ throw new NotImplementedFunctionException(_functionName);
+ }
+ public String getFunctionName() {
+ return _functionName;
+ }
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Now.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Now.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Now.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Now.java Sat May 22 20:56:44 2021
@@ -28,11 +28,11 @@ import org.apache.poi.ss.usermodel.DateU
* Implementation of Excel NOW() Function
*/
public final class Now {
- public static ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
- if (args.length != 0) {
- return ErrorEval.VALUE_INVALID;
- }
- Date now = new Date(System.currentTimeMillis());
- return new NumberEval(DateUtil.getExcelDate(now));
- }
+ public static ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+ if (args.length != 0) {
+ return ErrorEval.VALUE_INVALID;
+ }
+ Date now = new Date(System.currentTimeMillis());
+ return new NumberEval(DateUtil.getExcelDate(now));
+ }
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Npv.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Npv.java?rev=1890120&r1=1890119&r2=1890120&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Npv.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Npv.java Sat May 22 20:56:44 2021
@@ -33,23 +33,23 @@ import org.apache.poi.ss.formula.eval.Va
*/
public final class Npv implements Function {
- public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
- int nArgs = args.length;
- if (nArgs < 2) {
- return ErrorEval.VALUE_INVALID;
- }
+ public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+ int nArgs = args.length;
+ if (nArgs < 2) {
+ return ErrorEval.VALUE_INVALID;
+ }
try {
- double rate = NumericFunction.singleOperandEvaluate(args[0], srcRowIndex, srcColumnIndex);
+ double rate = NumericFunction.singleOperandEvaluate(args[0], srcRowIndex, srcColumnIndex);
// convert tail arguments into an array of doubles
ValueEval[] vargs = Arrays.copyOfRange(args, 1, args.length, ValueEval[].class);
double[] values = AggregateFunction.ValueCollector.collectValues(vargs);
double result = FinanceLib.npv(rate, values);
- NumericFunction.checkValue(result);
+ NumericFunction.checkValue(result);
return new NumberEval(result);
- } catch (EvaluationException e) {
- return e.getErrorEval();
- }
- }
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org