* </p>
*
* @author Josh Micich
+ * @author Cedric Walter at innoveo.com
*/
public final class Countif extends Fixed2ArgFunction {
return false;
}
}
- private static final class StringMatcher extends MatcherBase {
+ public static final class StringMatcher extends MatcherBase {
private final String _value;
private final Pattern _pattern;
* 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(".*");
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 {
return EQUAL;
}
+ public static final CompareResult valueOf(boolean matches) {
+ if(matches) {
+ return EQUAL ;
+ }
+ return LESS_THAN;
+ }
+
+
public boolean isTypeMismatch() {
return _isTypeMismatch;
}
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;
}
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);
/**
* 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
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
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);
*
*
* @author Josh Micich
+ * @author Cedric Walter at innoveo.com
*/
public final class Match extends Var2or3ArgFunction {
}
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) {
* 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;
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) {
--- /dev/null
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.ss.formula.functions;\r
+\r
+import java.io.PrintStream;\r
+\r
+import junit.framework.Assert;\r
+import junit.framework.AssertionFailedError;\r
+import junit.framework.TestCase;\r
+\r
+import org.apache.poi.hssf.HSSFTestDataSamples;\r
+import org.apache.poi.ss.formula.eval.ErrorEval;\r
+import org.apache.poi.hssf.usermodel.HSSFCell;\r
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;\r
+import org.apache.poi.hssf.usermodel.HSSFRow;\r
+import org.apache.poi.hssf.usermodel.HSSFSheet;\r
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;\r
+import org.apache.poi.hssf.util.CellReference;\r
+import org.apache.poi.ss.usermodel.CellValue;\r
+\r
+/**\r
+ * @author Josh Micich\r
+ * @author Cedric Walter at innoveo.com\r
+ */\r
+public abstract class BaseTestFunctionsFromSpreadsheet extends TestCase {\r
+\r
+ private static final class Result {\r
+ public static final int SOME_EVALUATIONS_FAILED = -1;\r
+ public static final int ALL_EVALUATIONS_SUCCEEDED = +1;\r
+ public static final int NO_EVALUATIONS_FOUND = 0;\r
+ }\r
+\r
+ /**\r
+ * This class defines constants for navigating around the test data spreadsheet used for these tests.\r
+ */\r
+ private static final class SS {\r
+\r
+ /** Name of the test spreadsheet (found in the standard test data folder) */\r
+\r
+\r
+ /** Name of the first sheet in the spreadsheet (contains comments) */\r
+ public final static String README_SHEET_NAME = "Read Me";\r
+\r
+ /** Row (zero-based) in each sheet where the evaluation cases start. */\r
+ public static final int START_TEST_CASES_ROW_INDEX = 4; // Row '5'\r
+ /** Index of the column that contains the function names */\r
+ public static final int COLUMN_INDEX_MARKER = 0; // Column 'A'\r
+ public static final int COLUMN_INDEX_EVALUATION = 1; // Column 'B'\r
+ public static final int COLUMN_INDEX_EXPECTED_RESULT = 2; // Column 'C'\r
+ public static final int COLUMN_ROW_COMMENT = 3; // Column 'D'\r
+\r
+ /** Used to indicate when there are no more test cases on the current sheet */\r
+ public static final String TEST_CASES_END_MARKER = "<end>";\r
+ /** Used to indicate that the test on the current row should be ignored */\r
+ public static final String SKIP_CURRENT_TEST_CASE_MARKER = "<skip>";\r
+\r
+ }\r
+\r
+ // Note - multiple failures are aggregated before ending.\r
+ // If one or more functions fail, a single AssertionFailedError is thrown at the end\r
+ private int _sheetFailureCount;\r
+ private int _sheetSuccessCount;\r
+ private int _evaluationFailureCount;\r
+ private int _evaluationSuccessCount;\r
+\r
+\r
+\r
+ private static void confirmExpectedResult(String msg, HSSFCell expected, CellValue actual) {\r
+ if (expected == null) {\r
+ throw new AssertionFailedError(msg + " - Bad setup data expected value is null");\r
+ }\r
+ if(actual == null) {\r
+ throw new AssertionFailedError(msg + " - actual value was null");\r
+ }\r
+ if(expected.getCellType() == HSSFCell.CELL_TYPE_ERROR) {\r
+ confirmErrorResult(msg, expected.getErrorCellValue(), actual);\r
+ return;\r
+ }\r
+ if(actual.getCellType() == HSSFCell.CELL_TYPE_ERROR) {\r
+ throw unexpectedError(msg, expected, actual.getErrorValue());\r
+ }\r
+ if(actual.getCellType() != expected.getCellType()) {\r
+ throw wrongTypeError(msg, expected, actual);\r
+ }\r
+\r
+\r
+ switch (expected.getCellType()) {\r
+ case HSSFCell.CELL_TYPE_BOOLEAN:\r
+ assertEquals(msg, expected.getBooleanCellValue(), actual.getBooleanValue());\r
+ break;\r
+ case HSSFCell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation\r
+ throw new IllegalStateException("Cannot expect formula as result of formula evaluation: " + msg);\r
+ case HSSFCell.CELL_TYPE_NUMERIC:\r
+ assertEquals(expected.getNumericCellValue(), actual.getNumberValue(), 0.0);\r
+ break;\r
+ case HSSFCell.CELL_TYPE_STRING:\r
+ assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getStringValue());\r
+ break;\r
+ }\r
+ }\r
+\r
+\r
+ private static AssertionFailedError wrongTypeError(String msgPrefix, HSSFCell expectedCell, CellValue actualValue) {\r
+ return new AssertionFailedError(msgPrefix + " Result type mismatch. Evaluated result was "\r
+ + actualValue.formatAsString()\r
+ + " but the expected result was "\r
+ + formatValue(expectedCell)\r
+ );\r
+ }\r
+ private static AssertionFailedError unexpectedError(String msgPrefix, HSSFCell expected, int actualErrorCode) {\r
+ return new AssertionFailedError(msgPrefix + " Error code ("\r
+ + ErrorEval.getText(actualErrorCode)\r
+ + ") was evaluated, but the expected result was "\r
+ + formatValue(expected)\r
+ );\r
+ }\r
+\r
+\r
+ private static void confirmErrorResult(String msgPrefix, int expectedErrorCode, CellValue actual) {\r
+ if(actual.getCellType() != HSSFCell.CELL_TYPE_ERROR) {\r
+ throw new AssertionFailedError(msgPrefix + " Expected cell error ("\r
+ + ErrorEval.getText(expectedErrorCode) + ") but actual value was "\r
+ + actual.formatAsString());\r
+ }\r
+ if(expectedErrorCode != actual.getErrorValue()) {\r
+ throw new AssertionFailedError(msgPrefix + " Expected cell error code ("\r
+ + ErrorEval.getText(expectedErrorCode)\r
+ + ") but actual error code was ("\r
+ + ErrorEval.getText(actual.getErrorValue())\r
+ + ")");\r
+ }\r
+ }\r
+\r
+\r
+ private static String formatValue(HSSFCell expecedCell) {\r
+ switch (expecedCell.getCellType()) {\r
+ case HSSFCell.CELL_TYPE_BLANK: return "<blank>";\r
+ case HSSFCell.CELL_TYPE_BOOLEAN: return String.valueOf(expecedCell.getBooleanCellValue());\r
+ case HSSFCell.CELL_TYPE_NUMERIC: return String.valueOf(expecedCell.getNumericCellValue());\r
+ case HSSFCell.CELL_TYPE_STRING: return expecedCell.getRichStringCellValue().getString();\r
+ }\r
+ throw new RuntimeException("Unexpected cell type of expected value (" + expecedCell.getCellType() + ")");\r
+ }\r
+\r
+\r
+ protected void setUp() {\r
+ _sheetFailureCount = 0;\r
+ _sheetSuccessCount = 0;\r
+ _evaluationFailureCount = 0;\r
+ _evaluationSuccessCount = 0;\r
+ }\r
+\r
+ public void testFunctionsFromTestSpreadsheet() {\r
+ HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook(this.getFilename());\r
+\r
+ confirmReadMeSheet(workbook);\r
+ int nSheets = workbook.getNumberOfSheets();\r
+ for(int i=1; i< nSheets; i++) {\r
+ int sheetResult = processTestSheet(workbook, i, workbook.getSheetName(i));\r
+ switch(sheetResult) {\r
+ case Result.ALL_EVALUATIONS_SUCCEEDED: _sheetSuccessCount ++; break;\r
+ case Result.SOME_EVALUATIONS_FAILED: _sheetFailureCount ++; break;\r
+ }\r
+ }\r
+\r
+ // confirm results\r
+ String successMsg = "There were "\r
+ + _sheetSuccessCount + " successful sheets(s) and "\r
+ + _evaluationSuccessCount + " function(s) without error";\r
+ if(_sheetFailureCount > 0) {\r
+ String msg = _sheetFailureCount + " sheets(s) failed with "\r
+ + _evaluationFailureCount + " evaluation(s). " + successMsg;\r
+ throw new AssertionFailedError(msg);\r
+ }\r
+ if(false) { // normally no output for successful tests\r
+ System.out.println(getClass().getName() + ": " + successMsg);\r
+ }\r
+ }\r
+\r
+ protected abstract String getFilename();\r
+\r
+ private int processTestSheet(HSSFWorkbook workbook, int sheetIndex, String sheetName) {\r
+ HSSFSheet sheet = workbook.getSheetAt(sheetIndex);\r
+ HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(workbook);\r
+ int maxRows = sheet.getLastRowNum()+1;\r
+ int result = Result.NO_EVALUATIONS_FOUND; // so far\r
+\r
+ String currentGroupComment = null;\r
+ for(int rowIndex=SS.START_TEST_CASES_ROW_INDEX; rowIndex<maxRows; rowIndex++) {\r
+ HSSFRow r = sheet.getRow(rowIndex);\r
+ String newMarkerValue = getMarkerColumnValue(r);\r
+ if(r == null) {\r
+ continue;\r
+ }\r
+ if(SS.TEST_CASES_END_MARKER.equalsIgnoreCase(newMarkerValue)) {\r
+ // normal exit point\r
+ return result;\r
+ }\r
+ if(SS.SKIP_CURRENT_TEST_CASE_MARKER.equalsIgnoreCase(newMarkerValue)) {\r
+ // currently disabled test case row\r
+ continue;\r
+ }\r
+ if(newMarkerValue != null) {\r
+ currentGroupComment = newMarkerValue;\r
+ }\r
+ HSSFCell c = r.getCell(SS.COLUMN_INDEX_EVALUATION);\r
+ if (c == null || c.getCellType() != HSSFCell.CELL_TYPE_FORMULA) {\r
+ continue;\r
+ }\r
+ CellValue actualValue = evaluator.evaluate(c);\r
+ HSSFCell expectedValueCell = r.getCell(SS.COLUMN_INDEX_EXPECTED_RESULT);\r
+ String rowComment = getRowCommentColumnValue(r);\r
+\r
+ String msgPrefix = formatTestCaseDetails(sheetName, r.getRowNum(), c, currentGroupComment, rowComment);\r
+ try {\r
+ confirmExpectedResult(msgPrefix, expectedValueCell, actualValue);\r
+ _evaluationSuccessCount ++;\r
+ if(result != Result.SOME_EVALUATIONS_FAILED) {\r
+ result = Result.ALL_EVALUATIONS_SUCCEEDED;\r
+ }\r
+ } catch (RuntimeException e) {\r
+ _evaluationFailureCount ++;\r
+ printShortStackTrace(System.err, e);\r
+ result = Result.SOME_EVALUATIONS_FAILED;\r
+ } catch (AssertionFailedError e) {\r
+ _evaluationFailureCount ++;\r
+ printShortStackTrace(System.err, e);\r
+ result = Result.SOME_EVALUATIONS_FAILED;\r
+ }\r
+\r
+ }\r
+ throw new RuntimeException("Missing end marker '" + SS.TEST_CASES_END_MARKER\r
+ + "' on sheet '" + sheetName + "'");\r
+\r
+ }\r
+\r
+\r
+ private static String formatTestCaseDetails(String sheetName, int rowIndex, HSSFCell c, String currentGroupComment,\r
+ String rowComment) {\r
+\r
+ StringBuffer sb = new StringBuffer();\r
+ CellReference cr = new CellReference(sheetName, rowIndex, c.getColumnIndex(), false, false);\r
+ sb.append(cr.formatAsString());\r
+ sb.append(" {=").append(c.getCellFormula()).append("}");\r
+\r
+ if(currentGroupComment != null) {\r
+ sb.append(" '");\r
+ sb.append(currentGroupComment);\r
+ if(rowComment != null) {\r
+ sb.append(" - ");\r
+ sb.append(rowComment);\r
+ }\r
+ sb.append("' ");\r
+ } else {\r
+ if(rowComment != null) {\r
+ sb.append(" '");\r
+ sb.append(rowComment);\r
+ sb.append("' ");\r
+ }\r
+ }\r
+\r
+ return sb.toString();\r
+ }\r
+\r
+ /**\r
+ * Asserts that the 'read me' comment page exists, and has this class' name in one of the\r
+ * cells. This back-link is to make it easy to find this class if a reader encounters the\r
+ * spreadsheet first.\r
+ */\r
+ private void confirmReadMeSheet(HSSFWorkbook workbook) {\r
+ String firstSheetName = workbook.getSheetName(0);\r
+ if(!firstSheetName.equalsIgnoreCase(SS.README_SHEET_NAME)) {\r
+ throw new RuntimeException("First sheet's name was '" + firstSheetName + "' but expected '" + SS.README_SHEET_NAME + "'");\r
+ }\r
+ HSSFSheet sheet = workbook.getSheetAt(0);\r
+ String specifiedClassName = sheet.getRow(2).getCell(0).getRichStringCellValue().getString();\r
+ assertEquals("Test class name in spreadsheet comment", getClass().getName(), specifiedClassName);\r
+ }\r
+\r
+\r
+ /**\r
+ * Useful to keep output concise when expecting many failures to be reported by this test case\r
+ */\r
+ private static void printShortStackTrace(PrintStream ps, Throwable e) {\r
+ StackTraceElement[] stes = e.getStackTrace();\r
+\r
+ int startIx = 0;\r
+ // skip any top frames inside junit.framework.Assert\r
+ while(startIx<stes.length) {\r
+ if(!stes[startIx].getClassName().equals(Assert.class.getName())) {\r
+ break;\r
+ }\r
+ startIx++;\r
+ }\r
+ // skip bottom frames (part of junit framework)\r
+ int endIx = startIx+1;\r
+ while(endIx < stes.length) {\r
+ if(stes[endIx].getClassName().equals(TestCase.class.getName())) {\r
+ break;\r
+ }\r
+ endIx++;\r
+ }\r
+ if(startIx >= endIx) {\r
+ // something went wrong. just print the whole stack trace\r
+ e.printStackTrace(ps);\r
+ }\r
+ endIx -= 4; // skip 4 frames of reflection invocation\r
+ ps.println(e.toString());\r
+ for(int i=startIx; i<endIx; i++) {\r
+ ps.println("\tat " + stes[i].toString());\r
+ }\r
+\r
+ }\r
+\r
+ private static String getRowCommentColumnValue(HSSFRow r) {\r
+ return getCellTextValue(r, SS.COLUMN_ROW_COMMENT, "row comment");\r
+ }\r
+\r
+ private static String getMarkerColumnValue(HSSFRow r) {\r
+ return getCellTextValue(r, SS.COLUMN_INDEX_MARKER, "marker");\r
+ }\r
+\r
+ /**\r
+ * @return <code>null</code> if cell is missing, empty or blank\r
+ */\r
+ private static String getCellTextValue(HSSFRow r, int colIndex, String columnName) {\r
+ if(r == null) {\r
+ return null;\r
+ }\r
+ HSSFCell cell = r.getCell(colIndex);\r
+ if(cell == null) {\r
+ return null;\r
+ }\r
+ if(cell.getCellType() == HSSFCell.CELL_TYPE_BLANK) {\r
+ return null;\r
+ }\r
+ if(cell.getCellType() == HSSFCell.CELL_TYPE_STRING) {\r
+ return cell.getRichStringCellValue().getString();\r
+ }\r
+\r
+ throw new RuntimeException("Bad cell type for '" + columnName + "' column: ("\r
+ + cell.getCellType() + ") row (" + (r.getRowNum() +1) + ")");\r
+ }\r
+\r
+}\r
* Test cases for COUNT(), COUNTA() COUNTIF(), COUNTBLANK()
*
* @author Josh Micich
+ * @author Cedric Walter at innoveo.com
*/
public final class TestCountFuncs extends TestCase {
package org.apache.poi.ss.formula.functions;
-import java.io.PrintStream;
-
-import junit.framework.Assert;
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.ss.formula.eval.ErrorEval;
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.util.CellReference;
-import org.apache.poi.ss.usermodel.CellValue;
-
/**
* Tests INDEX() as loaded from a test data spreadsheet.<p/>
*
* @author Josh Micich
+ * @author Cedric Walter at innoveo.com
*/
-public final class TestIndexFunctionFromSpreadsheet extends TestCase {
-
- private static final class Result {
- public static final int SOME_EVALUATIONS_FAILED = -1;
- public static final int ALL_EVALUATIONS_SUCCEEDED = +1;
- public static final int NO_EVALUATIONS_FOUND = 0;
- }
-
- /**
- * This class defines constants for navigating around the test data spreadsheet used for these tests.
- */
- private static final class SS {
-
- /** Name of the test spreadsheet (found in the standard test data folder) */
- public final static String FILENAME = "IndexFunctionTestCaseData.xls";
-
- public static final int COLUMN_INDEX_EVALUATION = 2; // Column 'C'
- public static final int COLUMN_INDEX_EXPECTED_RESULT = 3; // Column 'D'
-
- }
-
- // Note - multiple failures are aggregated before ending.
- // If one or more functions fail, a single AssertionFailedError is thrown at the end
- private int _evaluationFailureCount;
- private int _evaluationSuccessCount;
-
-
-
- private static void confirmExpectedResult(String msg, HSSFCell expected, CellValue actual) {
- if (expected == null) {
- throw new AssertionFailedError(msg + " - Bad setup data expected value is null");
- }
- if(actual == null) {
- throw new AssertionFailedError(msg + " - actual value was null");
- }
- if(expected.getCellType() == HSSFCell.CELL_TYPE_ERROR) {
- confirmErrorResult(msg, expected.getErrorCellValue(), actual);
- return;
- }
- if(actual.getCellType() == HSSFCell.CELL_TYPE_ERROR) {
- throw unexpectedError(msg, expected, actual.getErrorValue());
- }
- if(actual.getCellType() != expected.getCellType()) {
- throw wrongTypeError(msg, expected, actual);
- }
-
-
- switch (expected.getCellType()) {
- case HSSFCell.CELL_TYPE_BOOLEAN:
- assertEquals(msg, expected.getBooleanCellValue(), actual.getBooleanValue());
- break;
- case HSSFCell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation
- throw new AssertionFailedError("Cannot expect formula as result of formula evaluation: " + msg);
- case HSSFCell.CELL_TYPE_NUMERIC:
- assertEquals(msg, expected.getNumericCellValue(), actual.getNumberValue(), 0.0);
- break;
- case HSSFCell.CELL_TYPE_STRING:
- assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getStringValue());
- break;
- }
- }
-
-
- private static AssertionFailedError wrongTypeError(String msgPrefix, HSSFCell expectedCell, CellValue actualValue) {
- return new AssertionFailedError(msgPrefix + " Result type mismatch. Evaluated result was "
- + actualValue.formatAsString()
- + " but the expected result was "
- + formatValue(expectedCell)
- );
- }
- private static AssertionFailedError unexpectedError(String msgPrefix, HSSFCell expected, int actualErrorCode) {
- return new AssertionFailedError(msgPrefix + " Error code ("
- + ErrorEval.getText(actualErrorCode)
- + ") was evaluated, but the expected result was "
- + formatValue(expected)
- );
- }
-
-
- private static void confirmErrorResult(String msgPrefix, int expectedErrorCode, CellValue actual) {
- if(actual.getCellType() != HSSFCell.CELL_TYPE_ERROR) {
- throw new AssertionFailedError(msgPrefix + " Expected cell error ("
- + ErrorEval.getText(expectedErrorCode) + ") but actual value was "
- + actual.formatAsString());
- }
- if(expectedErrorCode != actual.getErrorValue()) {
- throw new AssertionFailedError(msgPrefix + " Expected cell error code ("
- + ErrorEval.getText(expectedErrorCode)
- + ") but actual error code was ("
- + ErrorEval.getText(actual.getErrorValue())
- + ")");
- }
- }
-
-
- private static String formatValue(HSSFCell expecedCell) {
- switch (expecedCell.getCellType()) {
- case HSSFCell.CELL_TYPE_BLANK: return "<blank>";
- case HSSFCell.CELL_TYPE_BOOLEAN: return String.valueOf(expecedCell.getBooleanCellValue());
- case HSSFCell.CELL_TYPE_NUMERIC: return String.valueOf(expecedCell.getNumericCellValue());
- case HSSFCell.CELL_TYPE_STRING: return expecedCell.getRichStringCellValue().getString();
- }
- throw new RuntimeException("Unexpected cell type of expected value (" + expecedCell.getCellType() + ")");
- }
-
-
- protected void setUp() {
- _evaluationFailureCount = 0;
- _evaluationSuccessCount = 0;
- }
-
- public void testFunctionsFromTestSpreadsheet() {
- HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook(SS.FILENAME);
-
- processTestSheet(workbook, workbook.getSheetName(0));
-
- // confirm results
- String successMsg = "There were "
- + _evaluationSuccessCount + " function(s) without error";
- if(_evaluationFailureCount > 0) {
- String msg = _evaluationFailureCount + " evaluation(s) failed. " + successMsg;
- throw new AssertionFailedError(msg);
- }
- if(false) { // normally no output for successful tests
- System.out.println(getClass().getName() + ": " + successMsg);
- }
- }
-
- private void processTestSheet(HSSFWorkbook workbook, String sheetName) {
- HSSFSheet sheet = workbook.getSheetAt(0);
- HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(workbook);
- int maxRows = sheet.getLastRowNum()+1;
- int result = Result.NO_EVALUATIONS_FOUND; // so far
-
- for(int rowIndex=0; rowIndex<maxRows; rowIndex++) {
- HSSFRow r = sheet.getRow(rowIndex);
- if(r == null) {
- continue;
- }
- HSSFCell c = r.getCell(SS.COLUMN_INDEX_EVALUATION);
- if (c == null || c.getCellType() != HSSFCell.CELL_TYPE_FORMULA) {
- continue;
- }
- HSSFCell expectedValueCell = r.getCell(SS.COLUMN_INDEX_EXPECTED_RESULT);
-
- String msgPrefix = formatTestCaseDetails(sheetName, r.getRowNum(), c);
- try {
- CellValue actualValue = evaluator.evaluate(c);
- confirmExpectedResult(msgPrefix, expectedValueCell, actualValue);
- _evaluationSuccessCount ++;
- if(result != Result.SOME_EVALUATIONS_FAILED) {
- result = Result.ALL_EVALUATIONS_SUCCEEDED;
- }
- } catch (RuntimeException e) {
- _evaluationFailureCount ++;
- printShortStackTrace(System.err, e, msgPrefix);
- result = Result.SOME_EVALUATIONS_FAILED;
- } catch (AssertionFailedError e) {
- _evaluationFailureCount ++;
- printShortStackTrace(System.err, e, msgPrefix);
- result = Result.SOME_EVALUATIONS_FAILED;
- }
- }
- }
-
-
- private static String formatTestCaseDetails(String sheetName, int rowIndex, HSSFCell c) {
-
- StringBuffer sb = new StringBuffer();
- CellReference cr = new CellReference(sheetName, rowIndex, c.getColumnIndex(), false, false);
- sb.append(cr.formatAsString());
- sb.append(" [formula: ").append(c.getCellFormula()).append(" ]");
- return sb.toString();
- }
-
- /**
- * Useful to keep output concise when expecting many failures to be reported by this test case
- */
- private static void printShortStackTrace(PrintStream ps, Throwable e, String msgPrefix) {
- System.err.println("Problem with " + msgPrefix);
- StackTraceElement[] stes = e.getStackTrace();
-
- int startIx = 0;
- // skip any top frames inside junit.framework.Assert
- while(startIx<stes.length) {
- if(!stes[startIx].getClassName().equals(Assert.class.getName())) {
- break;
- }
- startIx++;
- }
- // skip bottom frames (part of junit framework)
- int endIx = startIx+1;
- while(endIx < stes.length) {
- if(stes[endIx].getClassName().equals(TestCase.class.getName())) {
- break;
- }
- endIx++;
- }
- if(startIx >= endIx) {
- // something went wrong. just print the whole stack trace
- e.printStackTrace(ps);
- }
- endIx -= 4; // skip 4 frames of reflection invocation
- ps.println(e.toString());
- for(int i=startIx; i<endIx; i++) {
- ps.println("\tat " + stes[i].toString());
- }
- }
-}
+public final class TestIndexFunctionFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet {
+ @Override
+ protected String getFilename() {
+ return "IndexFunctionTestCaseData.xls";
+ }
+}
\ No newline at end of file
package org.apache.poi.ss.formula.functions;
-import java.io.PrintStream;
-import junit.framework.Assert;
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
-
-import org.apache.poi.hssf.HSSFTestDataSamples;
-import org.apache.poi.ss.formula.eval.ErrorEval;
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.util.CellReference;
-import org.apache.poi.ss.usermodel.CellValue;
/**
* Tests lookup functions (VLOOKUP, HLOOKUP, LOOKUP, MATCH) as loaded from a test data spreadsheet.<p/>
* more easily.
*
* @author Josh Micich
+ * @author Cedric Walter at innoveo.com
*/
-public final class TestLookupFunctionsFromSpreadsheet extends TestCase {
-
- private static final class Result {
- public static final int SOME_EVALUATIONS_FAILED = -1;
- public static final int ALL_EVALUATIONS_SUCCEEDED = +1;
- public static final int NO_EVALUATIONS_FOUND = 0;
- }
-
- /**
- * This class defines constants for navigating around the test data spreadsheet used for these tests.
- */
- private static final class SS {
-
- /** Name of the test spreadsheet (found in the standard test data folder) */
- public final static String FILENAME = "LookupFunctionsTestCaseData.xls";
-
- /** Name of the first sheet in the spreadsheet (contains comments) */
- public final static String README_SHEET_NAME = "Read Me";
-
-
- /** Row (zero-based) in each sheet where the evaluation cases start. */
- public static final int START_TEST_CASES_ROW_INDEX = 4; // Row '5'
- /** Index of the column that contains the function names */
- public static final int COLUMN_INDEX_MARKER = 0; // Column 'A'
- public static final int COLUMN_INDEX_EVALUATION = 1; // Column 'B'
- public static final int COLUMN_INDEX_EXPECTED_RESULT = 2; // Column 'C'
- public static final int COLUMN_ROW_COMMENT = 3; // Column 'D'
-
- /** Used to indicate when there are no more test cases on the current sheet */
- public static final String TEST_CASES_END_MARKER = "<end>";
- /** Used to indicate that the test on the current row should be ignored */
- public static final String SKIP_CURRENT_TEST_CASE_MARKER = "<skip>";
-
- }
-
- // Note - multiple failures are aggregated before ending.
- // If one or more functions fail, a single AssertionFailedError is thrown at the end
- private int _sheetFailureCount;
- private int _sheetSuccessCount;
- private int _evaluationFailureCount;
- private int _evaluationSuccessCount;
-
-
-
- private static void confirmExpectedResult(String msg, HSSFCell expected, CellValue actual) {
- if (expected == null) {
- throw new AssertionFailedError(msg + " - Bad setup data expected value is null");
- }
- if(actual == null) {
- throw new AssertionFailedError(msg + " - actual value was null");
- }
- if(expected.getCellType() == HSSFCell.CELL_TYPE_ERROR) {
- confirmErrorResult(msg, expected.getErrorCellValue(), actual);
- return;
- }
- if(actual.getCellType() == HSSFCell.CELL_TYPE_ERROR) {
- throw unexpectedError(msg, expected, actual.getErrorValue());
- }
- if(actual.getCellType() != expected.getCellType()) {
- throw wrongTypeError(msg, expected, actual);
- }
-
-
- switch (expected.getCellType()) {
- case HSSFCell.CELL_TYPE_BOOLEAN:
- assertEquals(msg, expected.getBooleanCellValue(), actual.getBooleanValue());
- break;
- case HSSFCell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation
- throw new IllegalStateException("Cannot expect formula as result of formula evaluation: " + msg);
- case HSSFCell.CELL_TYPE_NUMERIC:
- assertEquals(expected.getNumericCellValue(), actual.getNumberValue(), 0.0);
- break;
- case HSSFCell.CELL_TYPE_STRING:
- assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getStringValue());
- break;
- }
- }
-
-
- private static AssertionFailedError wrongTypeError(String msgPrefix, HSSFCell expectedCell, CellValue actualValue) {
- return new AssertionFailedError(msgPrefix + " Result type mismatch. Evaluated result was "
- + actualValue.formatAsString()
- + " but the expected result was "
- + formatValue(expectedCell)
- );
- }
- private static AssertionFailedError unexpectedError(String msgPrefix, HSSFCell expected, int actualErrorCode) {
- return new AssertionFailedError(msgPrefix + " Error code ("
- + ErrorEval.getText(actualErrorCode)
- + ") was evaluated, but the expected result was "
- + formatValue(expected)
- );
- }
-
-
- private static void confirmErrorResult(String msgPrefix, int expectedErrorCode, CellValue actual) {
- if(actual.getCellType() != HSSFCell.CELL_TYPE_ERROR) {
- throw new AssertionFailedError(msgPrefix + " Expected cell error ("
- + ErrorEval.getText(expectedErrorCode) + ") but actual value was "
- + actual.formatAsString());
- }
- if(expectedErrorCode != actual.getErrorValue()) {
- throw new AssertionFailedError(msgPrefix + " Expected cell error code ("
- + ErrorEval.getText(expectedErrorCode)
- + ") but actual error code was ("
- + ErrorEval.getText(actual.getErrorValue())
- + ")");
- }
- }
-
-
- private static String formatValue(HSSFCell expecedCell) {
- switch (expecedCell.getCellType()) {
- case HSSFCell.CELL_TYPE_BLANK: return "<blank>";
- case HSSFCell.CELL_TYPE_BOOLEAN: return String.valueOf(expecedCell.getBooleanCellValue());
- case HSSFCell.CELL_TYPE_NUMERIC: return String.valueOf(expecedCell.getNumericCellValue());
- case HSSFCell.CELL_TYPE_STRING: return expecedCell.getRichStringCellValue().getString();
- }
- throw new RuntimeException("Unexpected cell type of expected value (" + expecedCell.getCellType() + ")");
- }
-
-
- protected void setUp() {
- _sheetFailureCount = 0;
- _sheetSuccessCount = 0;
- _evaluationFailureCount = 0;
- _evaluationSuccessCount = 0;
- }
-
- public void testFunctionsFromTestSpreadsheet() {
- HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook(SS.FILENAME);
-
- confirmReadMeSheet(workbook);
- int nSheets = workbook.getNumberOfSheets();
- for(int i=1; i< nSheets; i++) {
- int sheetResult = processTestSheet(workbook, i, workbook.getSheetName(i));
- switch(sheetResult) {
- case Result.ALL_EVALUATIONS_SUCCEEDED: _sheetSuccessCount ++; break;
- case Result.SOME_EVALUATIONS_FAILED: _sheetFailureCount ++; break;
- }
- }
-
- // confirm results
- String successMsg = "There were "
- + _sheetSuccessCount + " successful sheets(s) and "
- + _evaluationSuccessCount + " function(s) without error";
- if(_sheetFailureCount > 0) {
- String msg = _sheetFailureCount + " sheets(s) failed with "
- + _evaluationFailureCount + " evaluation(s). " + successMsg;
- throw new AssertionFailedError(msg);
- }
- if(false) { // normally no output for successful tests
- System.out.println(getClass().getName() + ": " + successMsg);
- }
- }
-
- private int processTestSheet(HSSFWorkbook workbook, int sheetIndex, String sheetName) {
- HSSFSheet sheet = workbook.getSheetAt(sheetIndex);
- HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(workbook);
- int maxRows = sheet.getLastRowNum()+1;
- int result = Result.NO_EVALUATIONS_FOUND; // so far
-
- String currentGroupComment = null;
- for(int rowIndex=SS.START_TEST_CASES_ROW_INDEX; rowIndex<maxRows; rowIndex++) {
- HSSFRow r = sheet.getRow(rowIndex);
- String newMarkerValue = getMarkerColumnValue(r);
- if(r == null) {
- continue;
- }
- if(SS.TEST_CASES_END_MARKER.equalsIgnoreCase(newMarkerValue)) {
- // normal exit point
- return result;
- }
- if(SS.SKIP_CURRENT_TEST_CASE_MARKER.equalsIgnoreCase(newMarkerValue)) {
- // currently disabled test case row
- continue;
- }
- if(newMarkerValue != null) {
- currentGroupComment = newMarkerValue;
- }
- HSSFCell c = r.getCell(SS.COLUMN_INDEX_EVALUATION);
- if (c == null || c.getCellType() != HSSFCell.CELL_TYPE_FORMULA) {
- continue;
- }
- CellValue actualValue = evaluator.evaluate(c);
- HSSFCell expectedValueCell = r.getCell(SS.COLUMN_INDEX_EXPECTED_RESULT);
- String rowComment = getRowCommentColumnValue(r);
-
- String msgPrefix = formatTestCaseDetails(sheetName, r.getRowNum(), c, currentGroupComment, rowComment);
- try {
- confirmExpectedResult(msgPrefix, expectedValueCell, actualValue);
- _evaluationSuccessCount ++;
- if(result != Result.SOME_EVALUATIONS_FAILED) {
- result = Result.ALL_EVALUATIONS_SUCCEEDED;
- }
- } catch (RuntimeException e) {
- _evaluationFailureCount ++;
- printShortStackTrace(System.err, e);
- result = Result.SOME_EVALUATIONS_FAILED;
- } catch (AssertionFailedError e) {
- _evaluationFailureCount ++;
- printShortStackTrace(System.err, e);
- result = Result.SOME_EVALUATIONS_FAILED;
- }
-
- }
- throw new RuntimeException("Missing end marker '" + SS.TEST_CASES_END_MARKER
- + "' on sheet '" + sheetName + "'");
-
- }
-
-
- private static String formatTestCaseDetails(String sheetName, int rowIndex, HSSFCell c, String currentGroupComment,
- String rowComment) {
-
- StringBuffer sb = new StringBuffer();
- CellReference cr = new CellReference(sheetName, rowIndex, c.getColumnIndex(), false, false);
- sb.append(cr.formatAsString());
- sb.append(" {=").append(c.getCellFormula()).append("}");
-
- if(currentGroupComment != null) {
- sb.append(" '");
- sb.append(currentGroupComment);
- if(rowComment != null) {
- sb.append(" - ");
- sb.append(rowComment);
- }
- sb.append("' ");
- } else {
- if(rowComment != null) {
- sb.append(" '");
- sb.append(rowComment);
- sb.append("' ");
- }
- }
-
- return sb.toString();
- }
-
- /**
- * Asserts that the 'read me' comment page exists, and has this class' name in one of the
- * cells. This back-link is to make it easy to find this class if a reader encounters the
- * spreadsheet first.
- */
- private void confirmReadMeSheet(HSSFWorkbook workbook) {
- String firstSheetName = workbook.getSheetName(0);
- if(!firstSheetName.equalsIgnoreCase(SS.README_SHEET_NAME)) {
- throw new RuntimeException("First sheet's name was '" + firstSheetName + "' but expected '" + SS.README_SHEET_NAME + "'");
- }
- HSSFSheet sheet = workbook.getSheetAt(0);
- String specifiedClassName = sheet.getRow(2).getCell(0).getRichStringCellValue().getString();
- assertEquals("Test class name in spreadsheet comment", getClass().getName(), specifiedClassName);
- }
-
-
- /**
- * Useful to keep output concise when expecting many failures to be reported by this test case
- */
- private static void printShortStackTrace(PrintStream ps, Throwable e) {
- StackTraceElement[] stes = e.getStackTrace();
-
- int startIx = 0;
- // skip any top frames inside junit.framework.Assert
- while(startIx<stes.length) {
- if(!stes[startIx].getClassName().equals(Assert.class.getName())) {
- break;
- }
- startIx++;
- }
- // skip bottom frames (part of junit framework)
- int endIx = startIx+1;
- while(endIx < stes.length) {
- if(stes[endIx].getClassName().equals(TestCase.class.getName())) {
- break;
- }
- endIx++;
- }
- if(startIx >= endIx) {
- // something went wrong. just print the whole stack trace
- e.printStackTrace(ps);
- }
- endIx -= 4; // skip 4 frames of reflection invocation
- ps.println(e.toString());
- for(int i=startIx; i<endIx; i++) {
- ps.println("\tat " + stes[i].toString());
- }
-
- }
-
- private static String getRowCommentColumnValue(HSSFRow r) {
- return getCellTextValue(r, SS.COLUMN_ROW_COMMENT, "row comment");
- }
-
- private static String getMarkerColumnValue(HSSFRow r) {
- return getCellTextValue(r, SS.COLUMN_INDEX_MARKER, "marker");
- }
-
- /**
- * @return <code>null</code> if cell is missing, empty or blank
- */
- private static String getCellTextValue(HSSFRow r, int colIndex, String columnName) {
- if(r == null) {
- return null;
- }
- HSSFCell cell = r.getCell(colIndex);
- if(cell == null) {
- return null;
- }
- if(cell.getCellType() == HSSFCell.CELL_TYPE_BLANK) {
- return null;
- }
- if(cell.getCellType() == HSSFCell.CELL_TYPE_STRING) {
- return cell.getRichStringCellValue().getString();
- }
+public final class TestLookupFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet {
- throw new RuntimeException("Bad cell type for '" + columnName + "' column: ("
- + cell.getCellType() + ") row (" + (r.getRowNum() +1) + ")");
- }
+ @Override
+ protected String getFilename() {
+ return "LookupFunctionsTestCaseData.xls";
+ }
}
import junit.framework.TestCase;
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.formula.eval.AreaEval;
import org.apache.poi.ss.formula.eval.BoolEval;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.NumericValueEval;
import org.apache.poi.ss.formula.eval.StringEval;
import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.usermodel.CellValue;
/**
* Test cases for MATCH()
*
* @author Josh Micich
+ * @author Cedric Walter at innoveo.com
*/
public final class TestMatch extends TestCase {
/** less than or equal to */
}
public void testSimpleString() {
-
+ // Arrange
ValueEval[] values = {
new StringEval("Albert"),
new StringEval("Charles"),
confirmInt(3, invokeMatch(new StringEval("eD"), ae, MATCH_LARGEST_LTE));
confirmInt(3, invokeMatch(new StringEval("Ed"), ae, MATCH_EXACT));
confirmInt(3, invokeMatch(new StringEval("ed"), ae, MATCH_EXACT));
- confirmInt(4, invokeMatch(new StringEval("Hugh"), ae, MATCH_LARGEST_LTE));
+
assertEquals(ErrorEval.NA, invokeMatch(new StringEval("Hugh"), ae, MATCH_EXACT));
}
+ public void testSimpleWildcardValuesString() {
+ // Arrange
+ ValueEval[] values = {
+ new StringEval("Albert"),
+ new StringEval("Charles"),
+ new StringEval("Ed"),
+ new StringEval("Greg"),
+ new StringEval("Ian"),
+ };
+
+ AreaEval ae = EvalFactory.createAreaEval("A1:A5", values);
+
+ // Note String comparisons are case insensitive
+ confirmInt(3, invokeMatch(new StringEval("e*"), ae, MATCH_EXACT));
+ confirmInt(3, invokeMatch(new StringEval("*d"), ae, MATCH_EXACT));
+
+ confirmInt(1, invokeMatch(new StringEval("Al*"), ae, MATCH_EXACT));
+ confirmInt(2, invokeMatch(new StringEval("Char*"), ae, MATCH_EXACT));
+
+ confirmInt(4, invokeMatch(new StringEval("*eg"), ae, MATCH_EXACT));
+ confirmInt(4, invokeMatch(new StringEval("G?eg"), ae, MATCH_EXACT));
+ confirmInt(4, invokeMatch(new StringEval("??eg"), ae, MATCH_EXACT));
+ confirmInt(4, invokeMatch(new StringEval("G*?eg"), ae, MATCH_EXACT));
+ confirmInt(4, invokeMatch(new StringEval("Hugh"), ae, MATCH_LARGEST_LTE));
+
+ confirmInt(5, invokeMatch(new StringEval("*Ian*"), ae, MATCH_EXACT));
+ confirmInt(5, invokeMatch(new StringEval("*Ian*"), ae, MATCH_LARGEST_LTE));
+ }
+
+ public void testTildeString() {
+
+ ValueEval[] values = {
+ new StringEval("what?"),
+ new StringEval("all*")
+ };
+
+ AreaEval ae = EvalFactory.createAreaEval("A1:A2", values);
+
+ confirmInt(1, invokeMatch(new StringEval("what~?"), ae, MATCH_EXACT));
+ confirmInt(2, invokeMatch(new StringEval("all~*"), ae, MATCH_EXACT));
+ }
+
public void testSimpleBoolean() {
ValueEval[] values = {
confirmInt(3, invokeMatch(new NumberEval(5), ae, MATCH_EXACT));
confirmInt(8, invokeMatch(new StringEval("CHARLES"), ae, MATCH_EXACT));
+ //wildcard values
+ confirmInt(8, invokeMatch(new StringEval("CHAR*"), ae, MATCH_EXACT));
+ confirmInt(8, invokeMatch(new StringEval("*CHARLES"), ae, MATCH_EXACT));
confirmInt(4, invokeMatch(new StringEval("Ben"), ae, MATCH_LARGEST_LTE));
confirmInt(13, invokeMatch(new StringEval("ED"), ae, MATCH_LARGEST_LTE));
+ confirmInt(13, invokeMatch(new StringEval("ED*"), ae, MATCH_LARGEST_LTE));
+ confirmInt(13, invokeMatch(new StringEval("*ED"), ae, MATCH_LARGEST_LTE));
confirmInt(9, invokeMatch(new StringEval("ED"), ae, MATCH_EXACT));
+ confirmInt(9, invokeMatch(new StringEval("ED*"), ae, MATCH_EXACT));
confirmInt(13, invokeMatch(new StringEval("Hugh"), ae, MATCH_LARGEST_LTE));
assertEquals(ErrorEval.NA, invokeMatch(new StringEval("Hugh"), ae, MATCH_EXACT));
--- /dev/null
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.ss.formula.functions;\r
+\r
+\r
+\r
+/**\r
+ * Tests lookup functions (VLOOKUP, HLOOKUP, LOOKUP, MATCH) as loaded from a test data spreadsheet.<p/>\r
+ * These tests have been separated from the common function and operator tests because the lookup\r
+ * functions have more complex test cases and test data setup.\r
+ *\r
+ * Tests for bug fixes and specific/tricky behaviour can be found in the corresponding test class\r
+ * (<tt>TestXxxx</tt>) of the target (<tt>Xxxx</tt>) implementor, where execution can be observed\r
+ * more easily.\r
+ *\r
+ * @author Josh Micich\r
+ * @author Cedric Walter at innoveo.com\r
+ */\r
+public final class TestMatchFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet {\r
+\r
+ @Override\r
+ protected String getFilename() {\r
+ return "MatchFunctionTestCaseData.xls";\r
+ }\r
+}\r