mirror of https://github.com/apache/poi.git
fixed evaluation of blank cells in COUNTIF, see Bugzilla 51498
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1243054 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
5b291578bc
commit
1d8365e7a3
|
@ -34,6 +34,7 @@
|
|||
|
||||
<changes>
|
||||
<release version="3.8-beta6" date="2012-??-??">
|
||||
<action dev="poi-developers" type="fix">51498 - fixed evaluation of blank cells in COUNTIF</action>
|
||||
<action dev="poi-developers" type="add">52576 - support changing external file references in HSSFWorkbook</action>
|
||||
<action dev="poi-developers" type="add">49896 - support external references in FormulaRenderer</action>
|
||||
<action dev="poi-developers" type="fix">52527 - avoid exception when matching shared formula records in HSSF</action>
|
||||
|
|
|
@ -217,6 +217,14 @@ public final class Countif extends Fixed2ArgFunction {
|
|||
} else if((x instanceof NumberEval)) {
|
||||
NumberEval ne = (NumberEval) x;
|
||||
testValue = ne.getNumberValue();
|
||||
} else if((x instanceof BlankEval)) {
|
||||
switch (getCode()) {
|
||||
case CmpOp.NE:
|
||||
// Excel counts blank values in range as not equal to any value. See Bugzilla 51498
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -258,6 +266,22 @@ public final class Countif extends Fixed2ArgFunction {
|
|||
} else if((x instanceof BoolEval)) {
|
||||
BoolEval be = (BoolEval) x;
|
||||
testValue = boolToInt(be.getBooleanValue());
|
||||
} else if((x instanceof BlankEval)) {
|
||||
switch (getCode()) {
|
||||
case CmpOp.NE:
|
||||
// Excel counts blank values in range as not equal to any value. See Bugzilla 51498
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else if((x instanceof NumberEval)) {
|
||||
switch (getCode()) {
|
||||
case CmpOp.NE:
|
||||
// not-equals comparison of a number to boolean always returnes false
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -318,6 +342,10 @@ public final class Countif extends Fixed2ArgFunction {
|
|||
case CmpOp.NONE:
|
||||
case CmpOp.EQ:
|
||||
return _value.length() == 0;
|
||||
case CmpOp.NE:
|
||||
// pred '<>' matches empty string but not blank cell
|
||||
// pred '<>ABC' matches blank and 'not ABC'
|
||||
return _value.length() != 0;
|
||||
}
|
||||
// no other criteria matches a blank cell
|
||||
return false;
|
||||
|
@ -342,7 +370,9 @@ public final class Countif extends Fixed2ArgFunction {
|
|||
if (_pattern != null) {
|
||||
return evaluate(_pattern.matcher(testedValue).matches());
|
||||
}
|
||||
return evaluate(testedValue.compareTo(_value));
|
||||
// String criteria in COUNTIF are case insensitive:
|
||||
// for example, the string "apples" and the string "APPLES" will match the same cells.
|
||||
return evaluate(testedValue.compareToIgnoreCase(_value));
|
||||
}
|
||||
/**
|
||||
* Translates Excel countif wildcard strings into java regex strings
|
||||
|
@ -394,7 +424,7 @@ public final class Countif extends Fixed2ArgFunction {
|
|||
sb.append(ch);
|
||||
}
|
||||
if (hasWildCard) {
|
||||
return Pattern.compile(sb.toString());
|
||||
return Pattern.compile(sb.toString(), Pattern.CASE_INSENSITIVE);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -2220,7 +2220,9 @@ if(1==2) {
|
|||
public void test49896() {
|
||||
HSSFWorkbook wb = openSample("49896.xls");
|
||||
HSSFCell cell = wb.getSheetAt(0).getRow(1).getCell(1);
|
||||
assertEquals("VLOOKUP(A2,'[C:Documents and Settings/Yegor/My Documents/csco.xls]Sheet1'!$A$2:$B$3,2,FALSE)",
|
||||
String PATH_SEPARATOR = System.getProperty("file.separator");
|
||||
assertEquals("VLOOKUP(A2,'[C:Documents and Settings" + PATH_SEPARATOR+"Yegor"+PATH_SEPARATOR
|
||||
+"My Documents"+PATH_SEPARATOR+"csco.xls]Sheet1'!$A$2:$B$3,2,FALSE)",
|
||||
cell.getCellFormula());
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.apache.poi.hssf.usermodel.HSSFSheet;
|
|||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.CellValue;
|
||||
import org.apache.poi.ss.usermodel.FormulaEvaluator;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
|
||||
/**
|
||||
* Test cases for COUNT(), COUNTA() COUNTIF(), COUNTBLANK()
|
||||
|
@ -196,6 +197,27 @@ public final class TestCountFuncs extends TestCase {
|
|||
confirmCountIf(4, range, new StringEval("<>111"));
|
||||
}
|
||||
|
||||
/**
|
||||
* String criteria in COUNTIF are case insensitive;
|
||||
* for example, the string "apples" and the string "APPLES" will match the same cells.
|
||||
*/
|
||||
public void testCaseInsensitiveStringComparison() {
|
||||
AreaEval range;
|
||||
ValueEval[] values;
|
||||
|
||||
values = new ValueEval[] {
|
||||
new StringEval("no"),
|
||||
new StringEval("NO"),
|
||||
new StringEval("No"),
|
||||
new StringEval("Yes")
|
||||
};
|
||||
|
||||
range = EvalFactory.createAreaEval("A1:A4", values);
|
||||
confirmCountIf(3, range, new StringEval("no"));
|
||||
confirmCountIf(3, range, new StringEval("NO"));
|
||||
confirmCountIf(3, range, new StringEval("No"));
|
||||
}
|
||||
|
||||
/**
|
||||
* special case where the criteria argument is a cell reference
|
||||
*/
|
||||
|
@ -365,27 +387,48 @@ public final class TestCountFuncs extends TestCase {
|
|||
* Bug #51498 - Check that CountIf behaves correctly for GTE, LTE
|
||||
* and NEQ cases
|
||||
*/
|
||||
public void testCountifLTEGTE() throws Exception {
|
||||
public void testCountifBug51498() throws Exception {
|
||||
final int REF_COL = 4;
|
||||
final int EVAL_COL = 3;
|
||||
|
||||
// Note - POI currently agrees with OpenOffice on certain blank cell cases,
|
||||
// while Excel can differ. This is the list of checks to skip
|
||||
List<Integer> skipRowsPendingExcelVsOpenOffice = Arrays.asList(
|
||||
new Integer[] {3});
|
||||
|
||||
HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook("51498.xls");
|
||||
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
|
||||
HSSFSheet sheet = workbook.getSheetAt(0);
|
||||
|
||||
// numeric criteria
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (skipRowsPendingExcelVsOpenOffice.contains(i)) {
|
||||
// Skip the check for now
|
||||
continue;
|
||||
}
|
||||
CellValue expected = evaluator.evaluate(sheet.getRow(i).getCell(REF_COL));
|
||||
CellValue actual = evaluator.evaluate(sheet.getRow(i).getCell(EVAL_COL));
|
||||
assertEquals(expected.formatAsString(), actual.formatAsString());
|
||||
}
|
||||
|
||||
// boolean criteria
|
||||
for (int i = 0; i < 8; i++) {
|
||||
HSSFCell cellFmla = sheet.getRow(i).getCell(8);
|
||||
HSSFCell cellRef = sheet.getRow(i).getCell(9);
|
||||
|
||||
double expectedValue = cellRef.getNumericCellValue();
|
||||
double actualValue = evaluator.evaluate(cellFmla).getNumberValue();
|
||||
|
||||
assertEquals(
|
||||
"Problem with a formula at " +
|
||||
new CellReference(cellFmla).formatAsString() + "[" + cellFmla.getCellFormula()+"] ",
|
||||
expectedValue, actualValue, 0.0001);
|
||||
}
|
||||
|
||||
// string criteria
|
||||
for (int i = 1; i < 9; i++) {
|
||||
HSSFCell cellFmla = sheet.getRow(i).getCell(13);
|
||||
HSSFCell cellRef = sheet.getRow(i).getCell(14);
|
||||
|
||||
double expectedValue = cellRef.getNumericCellValue();
|
||||
double actualValue = evaluator.evaluate(cellFmla).getNumberValue();
|
||||
|
||||
assertEquals(
|
||||
"Problem with a formula at " +
|
||||
new CellReference(cellFmla).formatAsString() + "[" + cellFmla.getCellFormula()+"] ",
|
||||
expectedValue, actualValue, 0.0001);
|
||||
}
|
||||
}
|
||||
|
||||
public void testWildCards() {
|
||||
|
@ -456,6 +499,53 @@ public final class TestCountFuncs extends TestCase {
|
|||
testCountFunctionFromSpreadsheet("countifExamples.xls", 1, 2, 3, "countif");
|
||||
}
|
||||
|
||||
/**
|
||||
* Two COUNTIF examples taken from
|
||||
* http://office.microsoft.com/en-us/excel-help/countif-function-HP010069840.aspx?CTT=5&origin=HA010277524
|
||||
*/
|
||||
public void testCountifExamples() {
|
||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("countifExamples.xls");
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||
|
||||
HSSFSheet sheet1 = wb.getSheet("MSDN Example 1");
|
||||
for (int rowIx=7; rowIx<=12; rowIx++) {
|
||||
HSSFRow row = sheet1.getRow(rowIx-1);
|
||||
HSSFCell cellA = row.getCell(0); // cell containing a formula with COUNTIF
|
||||
assertEquals(HSSFCell.CELL_TYPE_FORMULA, cellA.getCellType());
|
||||
HSSFCell cellC = row.getCell(2); // cell with a reference value
|
||||
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cellC.getCellType());
|
||||
|
||||
CellValue cv = fe.evaluate(cellA);
|
||||
double actualValue = cv.getNumberValue();
|
||||
double expectedValue = cellC.getNumericCellValue();
|
||||
assertEquals(
|
||||
"Problem with a formula at " + new CellReference(cellA).formatAsString()
|
||||
+ ": " + cellA.getCellFormula() + " :"
|
||||
+ "Expected = (" + expectedValue + ") Actual=(" + actualValue + ") ",
|
||||
expectedValue, actualValue, 0.0001);
|
||||
}
|
||||
|
||||
HSSFSheet sheet2 = wb.getSheet("MSDN Example 2");
|
||||
for (int rowIx=9; rowIx<=14; rowIx++) {
|
||||
HSSFRow row = sheet2.getRow(rowIx-1);
|
||||
HSSFCell cellA = row.getCell(0); // cell containing a formula with COUNTIF
|
||||
assertEquals(HSSFCell.CELL_TYPE_FORMULA, cellA.getCellType());
|
||||
HSSFCell cellC = row.getCell(2); // cell with a reference value
|
||||
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cellC.getCellType());
|
||||
|
||||
CellValue cv = fe.evaluate(cellA);
|
||||
double actualValue = cv.getNumberValue();
|
||||
double expectedValue = cellC.getNumericCellValue();
|
||||
|
||||
assertEquals(
|
||||
"Problem with a formula at " +
|
||||
new CellReference(cellA).formatAsString() + "[" + cellA.getCellFormula()+"]: "
|
||||
+ "Expected = (" + expectedValue + ") Actual=(" + actualValue + ") ",
|
||||
expectedValue, actualValue, 0.0001);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void testCountBlankFromSpreadsheet() {
|
||||
testCountFunctionFromSpreadsheet("countblankExamples.xls", 1, 3, 4, "countblank");
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue