Permalink
Browse files

Bug 54673 - [PATCH] Simple wildcard support in HLOOKUP, VOOLKUP, MATC…

…H, COUNTIF

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1457243 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information...
1 parent 651e622 commit 76fac9786572c51ce436afb21375c74e91147172 Yegor Kozlov committed Mar 16, 2013
@@ -43,6 +43,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more
* </p>
*
* @author Josh Micich
+ * @author Cedric Walter at innoveo.com
*/
public final class Countif extends Fixed2ArgFunction {
@@ -309,7 +310,7 @@ public boolean matches(ValueEval x) {
return false;
}
}
- private static final class StringMatcher extends MatcherBase {
+ public static final class StringMatcher extends MatcherBase {
private final String _value;
private final Pattern _pattern;
@@ -378,19 +379,19 @@ public boolean matches(ValueEval x) {
* Translates Excel countif wildcard strings into java regex strings
* @return <code>null</code> if the specified value contains no special wildcard characters.
*/
- private static Pattern getWildCardPattern(String value) {
+ public static Pattern getWildCardPattern(String value) {
int len = value.length();
StringBuffer sb = new StringBuffer(len);
boolean hasWildCard = false;
for(int i=0; i<len; i++) {
char ch = value.charAt(i);
switch(ch) {
- case '?':
+ case '?': //Any single character
hasWildCard = true;
// match exactly one character
sb.append('.');
continue;
- case '*':
+ case '*': //Zero or more characters
hasWildCard = true;
// match one or more occurrences of any character
sb.append(".*");
@@ -29,10 +29,14 @@ Licensed to the Apache Software Foundation (ASF) under one or more
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.formula.TwoDEval;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
/**
* Common functionality used by VLOOKUP, HLOOKUP, LOOKUP and MATCH
*
* @author Josh Micich
+ * @author Cedric Walter at innoveo.com
*/
final class LookupUtils {
@@ -167,6 +171,14 @@ public static final CompareResult valueOf(int simpleCompareResult) {
return EQUAL;
}
+ public static final CompareResult valueOf(boolean matches) {
+ if(matches) {
+ return EQUAL ;
+ }
+ return LESS_THAN;
+ }
+
+
public boolean isTypeMismatch() {
return _isTypeMismatch;
}
@@ -243,16 +255,37 @@ public String toString() {
protected abstract String getValueAsString();
}
- private static final class StringLookupComparer extends LookupValueComparerBase {
- private String _value;
- protected StringLookupComparer(StringEval se) {
+ private static final class StringLookupComparer extends LookupValueComparerBase {
+
+ private String _value;
+ private final Pattern _wildCardPattern;
+ private boolean _matchExact;
+ private boolean _isMatchFunction;
+
+ protected StringLookupComparer(StringEval se, boolean matchExact, boolean isMatchFunction) {
super(se);
_value = se.getStringValue();
+ _wildCardPattern = Countif.StringMatcher.getWildCardPattern(_value);
+ _matchExact = matchExact;
+ _isMatchFunction = isMatchFunction;
}
+
protected CompareResult compareSameType(ValueEval other) {
- StringEval se = (StringEval) other;
- return CompareResult.valueOf(_value.compareToIgnoreCase(se.getStringValue()));
+ StringEval se = (StringEval) other;
+
+ String stringValue = se.getStringValue();
+ if (_wildCardPattern != null) {
+ Matcher matcher = _wildCardPattern.matcher(stringValue);
+ boolean matches = matcher.matches();
+
+ if (_isMatchFunction ||
+ !_matchExact) {
+ return CompareResult.valueOf(matches);
+ }
+ }
+
+ return CompareResult.valueOf(_value.compareToIgnoreCase(stringValue));
}
protected String getValueAsString() {
return _value;
@@ -423,7 +456,7 @@ public static boolean resolveRangeLookupArg(ValueEval rangeLookupArg, int srcCel
}
public static int lookupIndexOfValue(ValueEval lookupValue, ValueVector vector, boolean isRangeLookup) throws EvaluationException {
- LookupValueComparer lookupComparer = createLookupComparer(lookupValue);
+ LookupValueComparer lookupComparer = createLookupComparer(lookupValue, isRangeLookup, false);
int result;
if(isRangeLookup) {
result = performBinarySearch(vector, lookupComparer);
@@ -439,7 +472,7 @@ public static int lookupIndexOfValue(ValueEval lookupValue, ValueVector vector,
/**
* Finds first (lowest index) exact occurrence of specified value.
- * @param lookupValue the value to be found in column or row vector
+ * @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
@@ -581,7 +614,7 @@ private static int findLastIndexInRunOfEqualValues(LookupValueComparer lookupCom
return maxIx - 1;
}
- public static LookupValueComparer createLookupComparer(ValueEval lookupValue) {
+ public static LookupValueComparer createLookupComparer(ValueEval lookupValue, boolean matchExact, boolean isMatchFunction) {
if (lookupValue == BlankEval.instance) {
// blank eval translates to zero
@@ -590,7 +623,8 @@ public static LookupValueComparer createLookupComparer(ValueEval lookupValue) {
return new NumberLookupComparer(NumberEval.ZERO);
}
if (lookupValue instanceof StringEval) {
- return new StringLookupComparer((StringEval) lookupValue);
+ //TODO eventually here return a WildcardStringLookupComparer
+ return new StringLookupComparer((StringEval) lookupValue, matchExact, isMatchFunction);
}
if (lookupValue instanceof NumberEval) {
return new NumberLookupComparer((NumberEval) lookupValue);
@@ -62,6 +62,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more
*
*
* @author Josh Micich
+ * @author Cedric Walter at innoveo.com
*/
public final class Match extends Var2or3ArgFunction {
@@ -232,14 +233,7 @@ private static int findIndexOfValue(ValueEval lookupValue, ValueVector lookupRan
}
private static LookupValueComparer createLookupComparer(ValueEval lookupValue, boolean matchExact) {
- if (matchExact && lookupValue instanceof StringEval) {
- String stringValue = ((StringEval) lookupValue).getStringValue();
- if(isLookupValueWild(stringValue)) {
- throw new RuntimeException("Wildcard lookup values '" + stringValue + "' not supported yet");
- }
-
- }
- return LookupUtils.createLookupComparer(lookupValue);
+ return LookupUtils.createLookupComparer(lookupValue, matchExact, true);
}
private static boolean isLookupValueWild(String stringValue) {
@@ -38,6 +38,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more
* the lookup_value. If FALSE, only exact matches will be considered<br/>
*
* @author Josh Micich
+ * @author Cedric Walter at innoveo.com
*/
public final class Vlookup extends Var3or4ArgFunction {
private static final ValueEval DEFAULT_ARG3 = BoolEval.TRUE;
@@ -47,16 +48,16 @@ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, V
return evaluate(srcRowIndex, srcColumnIndex, arg0, arg1, arg2, DEFAULT_ARG3);
}
- public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1,
- ValueEval arg2, ValueEval arg3) {
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval lookup_value, ValueEval table_array,
+ ValueEval col_index, ValueEval range_lookup) {
try {
// 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);
- TwoDEval tableArray = LookupUtils.resolveTableArrayArg(arg1);
- boolean isRangeLookup = LookupUtils.resolveRangeLookupArg(arg3, srcRowIndex, srcColumnIndex);
+ // lookup_value , table_array, range_lookup, find lookup value, col_index, fetch result
+ ValueEval lookupValue = OperandResolver.getSingleValue(lookup_value, srcRowIndex, srcColumnIndex);
+ TwoDEval tableArray = LookupUtils.resolveTableArrayArg(table_array);
+ boolean isRangeLookup = LookupUtils.resolveRangeLookupArg(range_lookup, srcRowIndex, srcColumnIndex);
int rowIndex = LookupUtils.lookupIndexOfValue(lookupValue, LookupUtils.createColumnVector(tableArray, 0), isRangeLookup);
- int colIndex = LookupUtils.resolveRowOrColIndexArg(arg2, srcRowIndex, srcColumnIndex);
+ int colIndex = LookupUtils.resolveRowOrColIndexArg(col_index, srcRowIndex, srcColumnIndex);
ValueVector resultCol = createResultColumnVector(tableArray, colIndex);
return resultCol.getItem(rowIndex);
} catch (EvaluationException e) {
Oops, something went wrong.

0 comments on commit 76fac97

Please sign in to comment.