diff --git a/src/java/org/apache/poi/ss/formula/functions/Countblank.java b/src/java/org/apache/poi/ss/formula/functions/Countblank.java index 5b83e4fd3..348a23e12 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Countblank.java +++ b/src/java/org/apache/poi/ss/formula/functions/Countblank.java @@ -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())); } }; } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java index e6b4f099d..d6e29d129 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java @@ -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(); + } } diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestCountFuncs.java b/src/testcases/org/apache/poi/ss/formula/functions/TestCountFuncs.java index 7184106df..fd3bc4b7b 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestCountFuncs.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestCountFuncs.java @@ -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)) { diff --git a/test-data/spreadsheet/59132.xlsx b/test-data/spreadsheet/59132.xlsx new file mode 100644 index 000000000..7fa2bdd41 Binary files /dev/null and b/test-data/spreadsheet/59132.xlsx differ