From 02b29ea698d518cc2c696afb69a157d4c11d5cbd Mon Sep 17 00:00:00 2001 From: Dominik Stadler Date: Tue, 29 Mar 2016 14:53:44 +0000 Subject: [PATCH] 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 --- .../poi/ss/formula/functions/Countblank.java | 10 +-- .../poi/xssf/usermodel/TestXSSFBugs.java | 74 ++++++++++++++---- .../ss/formula/functions/TestCountFuncs.java | 12 ++- test-data/spreadsheet/59132.xlsx | Bin 0 -> 9064 bytes 4 files changed, 68 insertions(+), 28 deletions(-) create mode 100644 test-data/spreadsheet/59132.xlsx 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 0000000000000000000000000000000000000000..7fa2bdd4163aa370f1e7cbb4e7d0571ffb6fbb6f GIT binary patch literal 9064 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 literal 0 HcmV?d00001