Bug 59132: Adjust implementation of COUNTBLANK to be conforming to Excel, empty strings are counted as blank as well

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1737009 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Dominik Stadler 2016-03-29 14:53:44 +00:00
parent 4eeffd0532
commit 02b29ea698
4 changed files with 68 additions and 28 deletions

View File

@ -18,10 +18,7 @@
package org.apache.poi.ss.formula.functions;
import org.apache.poi.ss.formula.ThreeDEval;
import org.apache.poi.ss.formula.eval.BlankEval;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.RefEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.formula.eval.*;
import org.apache.poi.ss.formula.functions.CountUtils.I_MatchPredicate;
/**
@ -54,7 +51,10 @@ public final class Countblank extends Fixed1ArgFunction {
public boolean matches(ValueEval valueEval) {
// Note - only BlankEval counts
return valueEval == BlankEval.instance;
return valueEval == BlankEval.instance ||
// see https://support.office.com/en-us/article/COUNTBLANK-function-6a92d772-675c-4bee-b346-24af6bd3ac22
// "Cells with formulas that return "" (empty text) are also counted."
(valueEval instanceof StringEval && "".equals(((StringEval)valueEval).getStringValue()));
}
};
}

View File

@ -362,9 +362,11 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
assertEquals(true, cs.getCoreXf().getApplyFill());
XSSFCellFill fg = wb.getStylesSource().getFillAt(2);
assertNotNull(fg.getFillForegroundColor());
assertEquals(0, fg.getFillForegroundColor().getIndexed());
assertEquals(0.0, fg.getFillForegroundColor().getTint(), 0);
assertEquals("FFFF0000", fg.getFillForegroundColor().getARGBHex());
assertNotNull(fg.getFillBackgroundColor());
assertEquals(64, fg.getFillBackgroundColor().getIndexed());
// Now look higher up
@ -1374,6 +1376,7 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
* DISABLED As we can't currently evaluate these
*/
@Ignore
@Test
public void bug48703() throws IOException {
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("48703.xlsx");
XSSFSheet sheet = wb.getSheetAt(0);
@ -1675,16 +1678,14 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
saveAndReloadReport(wb, xlsOutput);
Row newRow = null;
Cell newCell = null;
// 2) attempt to create a new row IN PLACE of a removed row by a negative shift causes corrupted
// xlsx file with unreadable data in the negative shifted row.
// NOTE it's ok to create any other row.
newRow = testSheet.createRow(3);
Row newRow = testSheet.createRow(3);
saveAndReloadReport(wb, xlsOutput);
newCell = newRow.createCell(0);
Cell newCell = newRow.createCell(0);
saveAndReloadReport(wb, xlsOutput);
@ -1962,8 +1963,6 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
/**
* .xlsb files are not supported, but we should generate a helpful
* error message if given one
* @throws InvalidFormatException
* @throws
*/
@Test
public void bug56800_xlsb() throws IOException, InvalidFormatException {
@ -2226,11 +2225,7 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
//saveWorkbook(wb, fileName);
XSSFWorkbook wbBack = XSSFTestDataSamples.writeOutAndReadBack(wb);
try {
} finally {
wbBack.close();
}
wbBack.close();
} finally {
wb.close();
}
@ -2246,11 +2241,7 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
//saveWorkbook(wb, fileName);
XSSFWorkbook wbBack = XSSFTestDataSamples.writeOutAndReadBack(wb);
try {
} finally {
wbBack.close();
}
wbBack.close();
} finally {
wb.close();
}
@ -2511,6 +2502,7 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
// avoid OOM in gump run
File file = XSSFTestDataSamples.writeOutAndClose(wb, "bug57880");
//noinspection UnusedAssignment
wb = null;
// Garbage collection may happen here
@ -2968,4 +2960,54 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
createXls();
createXlsx();
}
@Test
public void test59132() throws IOException {
Workbook workbook = XSSFTestDataSamples.openSampleWorkbook("59132.xlsx");
Sheet worksheet = workbook.getSheet("sheet1");
// B3
Row row = worksheet.getRow(2);
Cell cell = row.getCell(1);
cell.setCellValue((String)null);
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
// B3
row = worksheet.getRow(2);
cell = row.getCell(1);
assertEquals(Cell.CELL_TYPE_BLANK, cell.getCellType());
assertEquals(-1, evaluator.evaluateFormulaCell(cell));
// A3
row = worksheet.getRow(2);
cell = row.getCell(0);
assertEquals(Cell.CELL_TYPE_FORMULA, cell.getCellType());
assertEquals("IF(ISBLANK(B3),\"\",B3)", cell.getCellFormula());
assertEquals(Cell.CELL_TYPE_STRING, evaluator.evaluateFormulaCell(cell));
CellValue value = evaluator.evaluate(cell);
assertEquals("", value.getStringValue());
// A5
row = worksheet.getRow(4);
cell = row.getCell(0);
assertEquals(Cell.CELL_TYPE_FORMULA, cell.getCellType());
assertEquals("COUNTBLANK(A1:A4)", cell.getCellFormula());
assertEquals(Cell.CELL_TYPE_NUMERIC, evaluator.evaluateFormulaCell(cell));
value = evaluator.evaluate(cell);
assertEquals(1.0, value.getNumberValue(), 0.1);
/*FileOutputStream output = new FileOutputStream("C:\\temp\\59132.xlsx");
try {
workbook.write(output);
} finally {
output.close();
}*/
workbook.close();
}
}

View File

@ -47,35 +47,33 @@ public final class TestCountFuncs extends TestCase {
private static final String NULL = null;
public void testCountBlank() {
AreaEval range;
ValueEval[] values;
values = new ValueEval[] {
new NumberEval(0),
new StringEval(""), // note - does not match blank
new StringEval(""), // note - does match blank
BoolEval.TRUE,
BoolEval.FALSE,
ErrorEval.DIV_ZERO,
BlankEval.instance,
};
range = EvalFactory.createAreaEval("A1:B3", values);
confirmCountBlank(1, range);
confirmCountBlank(2, range);
values = new ValueEval[] {
new NumberEval(0),
new StringEval(""), // note - does not match blank
new StringEval(""), // does match blank
BlankEval.instance,
BoolEval.FALSE,
BoolEval.TRUE,
BlankEval.instance,
};
range = EvalFactory.createAreaEval("A1:B3", values);
confirmCountBlank(2, range);
confirmCountBlank(3, range);
}
public void testCountA() {
ValueEval[] args;
args = new ValueEval[] {
@ -105,7 +103,6 @@ public final class TestCountFuncs extends TestCase {
}
public void testCountIf() {
AreaEval range;
ValueEval[] values;
@ -143,6 +140,7 @@ public final class TestCountFuncs extends TestCase {
public void testCriteriaPredicateNe_Bug46647() {
I_MatchPredicate mp = Countif.createCriteriaPredicate(new StringEval("<>aa"), 0, 0);
assertNotNull(mp);
StringEval seA = new StringEval("aa"); // this should not match the criteria '<>aa'
StringEval seB = new StringEval("bb"); // this should match
if (mp.matches(seA) && !mp.matches(seB)) {

Binary file not shown.