]> source.dussan.org Git - poi.git/commitdiff
Bug 59132: Adjust implementation of COUNTBLANK to be conforming to Excel, empty strin...
authorDominik Stadler <centic@apache.org>
Tue, 29 Mar 2016 14:53:44 +0000 (14:53 +0000)
committerDominik Stadler <centic@apache.org>
Tue, 29 Mar 2016 14:53:44 +0000 (14:53 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1737009 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/ss/formula/functions/Countblank.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java
src/testcases/org/apache/poi/ss/formula/functions/TestCountFuncs.java
test-data/spreadsheet/59132.xlsx [new file with mode: 0644]

index 5b83e4fd310345bc7ac61db03dd65b6ec5c63a3a..348a23e12e6e967e57179ccc123e91e85a9628a8 100644 (file)
 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()));
                }
        };
 }
index e6b4f099db5cc0f02d3af77249d0668b23941ae0..d6e29d12939886a4bd6d6d56f2b056f26d64943a 100644 (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();
+    }
 }
index 7184106dfedcc2965ba884f5636d78b597c8cc20..fd3bc4b7b75df1fbfb8da8b90585a001fe4dbb03 100644 (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)) {
diff --git a/test-data/spreadsheet/59132.xlsx b/test-data/spreadsheet/59132.xlsx
new file mode 100644 (file)
index 0000000..7fa2bdd
Binary files /dev/null and b/test-data/spreadsheet/59132.xlsx differ