]> source.dussan.org Git - poi.git/commitdiff
Bugzilla 48044 - added implementation for CountBlank function (patch from Mads Mohr...
authorJosh Micich <josh@apache.org>
Sat, 24 Oct 2009 00:41:30 +0000 (00:41 +0000)
committerJosh Micich <josh@apache.org>
Sat, 24 Oct 2009 00:41:30 +0000 (00:41 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@829293 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/hssf/record/formula/eval/FunctionEval.java
src/java/org/apache/poi/hssf/record/formula/functions/Countblank.java [new file with mode: 0644]
src/testcases/org/apache/poi/hssf/record/formula/functions/TestCountFuncs.java
test-data/spreadsheet/countblankExamples.xls [new file with mode: 0644]

index 6dac6eac444d2730be39a10ef79f852271821cc4..99d07c91f4701124bdb30e7c1fe84e96c4d30355 100644 (file)
@@ -33,6 +33,7 @@
 
     <changes>
         <release version="3.6-beta1" date="2009-??-??">
+           <action dev="POI-DEVELOPERS" type="add">48044 - added implementation for CountBlank function</action>
            <action dev="POI-DEVELOPERS" type="fix">48036 - added IntersectionEval to allow evaluation of the intersection formula operator</action>
            <action dev="POI-DEVELOPERS" type="fix">47999 - avoid un-needed call to the JVM Garbage Collector when working on OOXML OPC Packages</action>
            <action dev="POI-DEVELOPERS" type="add">47922 - added example HSMF application that converts a .msg file to text and extracts attachments</action>
index 583cf88b8ec96d721869fdf81d5f820204da8efc..dc5d6c5fe5a9fc90501aa899467547c05d504f51 100644 (file)
@@ -203,6 +203,7 @@ public final class FunctionEval implements OperationEval {
 
                retval[345] = new Sumif();
                retval[346] = new Countif();
+               retval[347] = new Countblank();
 
                retval[359] = new Hyperlink();
 
diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Countblank.java b/src/java/org/apache/poi/hssf/record/formula/functions/Countblank.java
new file mode 100644 (file)
index 0000000..f7d7538
--- /dev/null
@@ -0,0 +1,67 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.record.formula.functions;
+
+import org.apache.poi.hssf.record.formula.eval.AreaEval;
+import org.apache.poi.hssf.record.formula.eval.BlankEval;
+import org.apache.poi.hssf.record.formula.eval.ErrorEval;
+import org.apache.poi.hssf.record.formula.eval.NumberEval;
+import org.apache.poi.hssf.record.formula.eval.RefEval;
+import org.apache.poi.hssf.record.formula.eval.ValueEval;
+import org.apache.poi.hssf.record.formula.functions.CountUtils.I_MatchPredicate;
+
+/**
+ * Implementation for the function COUNTBLANK
+ * <p>
+ *  Syntax: COUNTBLANK ( range )
+ *    <table border="0" cellpadding="1" cellspacing="0" summary="Parameter descriptions">
+ *      <tr><th>range&nbsp;&nbsp;&nbsp;</th><td>is the range of cells to count blanks</td></tr>
+ *    </table>
+ * </p>
+ *
+ * @author Mads Mohr Christensen
+ */
+public final class Countblank implements Function {
+
+       public ValueEval evaluate(ValueEval[] args, int srcRowIndex, short srcColumnIndex) {
+               if (args.length != 1) {
+                       // TODO - it doesn't seem to be possible to enter COUNTBLANK() into Excel with the wrong arg count
+                       // perhaps this should be an exception
+                       return ErrorEval.VALUE_INVALID;
+               }
+
+               double result;
+               ValueEval arg0 = args[0];
+               if (arg0 instanceof RefEval) {
+                       result = CountUtils.countMatchingCell((RefEval) arg0, predicate);
+               } else if (arg0 instanceof AreaEval) {
+                       result = CountUtils.countMatchingCellsInArea((AreaEval) arg0, predicate);
+               } else {
+                       throw new IllegalArgumentException("Bad range arg type (" + arg0.getClass().getName() + ")");
+               }
+               return new NumberEval(result);
+       }
+
+       private static final I_MatchPredicate predicate = new I_MatchPredicate() {
+
+               public boolean matches(ValueEval valueEval) {
+                       // Note - only BlankEval counts
+                       return valueEval == BlankEval.INSTANCE;
+               }
+       };
+}
index e07f2c2454a3e56dd69015d8f6ac0c241958c2b3..e3ee50e0a4e3073e46d5ad7a5805337f168d96d1 100644 (file)
@@ -46,6 +46,34 @@ 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
+                               BoolEval.TRUE,
+                               BoolEval.FALSE,
+                               ErrorEval.DIV_ZERO,
+                               BlankEval.INSTANCE,
+               };
+               range = EvalFactory.createAreaEval("A1:B3", values);
+               confirmCountBlank(1, range);
+
+               values = new ValueEval[] {
+                               new NumberEval(0),
+                               new StringEval(""),     // note - does not match blank
+                               BlankEval.INSTANCE,
+                               BoolEval.FALSE,
+                               BoolEval.TRUE,
+                               BlankEval.INSTANCE,
+               };
+               range = EvalFactory.createAreaEval("A1:B3", values);
+               confirmCountBlank(2, range);
+       }
+
        public void testCountA() {
 
                ValueEval[] args;
@@ -196,6 +224,12 @@ public final class TestCountFuncs extends TestCase {
                double result = NumericFunctionInvoker.invoke(new Countif(), args);
                assertEquals(expected, result, 0);
        }
+       private static void confirmCountBlank(int expected, AreaEval range) {
+
+               ValueEval[] args = { range };
+               double result = NumericFunctionInvoker.invoke(new Countblank(), args);
+               assertEquals(expected, result, 0);
+       }
 
        private static I_MatchPredicate createCriteriaPredicate(ValueEval ev) {
                return Countif.createCriteriaPredicate(ev, 0, 0);
@@ -388,10 +422,14 @@ public final class TestCountFuncs extends TestCase {
        }
 
        public void testCountifFromSpreadsheet() {
-               final String FILE_NAME = "countifExamples.xls";
-               final int START_ROW_IX = 1;
-               final int COL_IX_ACTUAL = 2;
-               final int COL_IX_EXPECTED = 3;
+               testCountFunctionFromSpreadsheet("countifExamples.xls", 1, 2, 3, "countif");
+       }
+
+       public void testCountBlankFromSpreadsheet() {
+               testCountFunctionFromSpreadsheet("countblankExamples.xls", 1, 3, 4, "countblank");
+       }
+
+       private static void testCountFunctionFromSpreadsheet(String FILE_NAME, int START_ROW_IX, int COL_IX_ACTUAL, int COL_IX_EXPECTED, String functionName) {
 
                int failureCount = 0;
                HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook(FILE_NAME);
@@ -415,7 +453,8 @@ public final class TestCountFuncs extends TestCase {
                }
 
                if (failureCount > 0) {
-                       throw new AssertionFailedError(failureCount + " countif evaluations failed. See stderr for more details");
+                       throw new AssertionFailedError(failureCount + " " + functionName
+                                       + " evaluations failed. See stderr for more details");
                }
        }
 }
diff --git a/test-data/spreadsheet/countblankExamples.xls b/test-data/spreadsheet/countblankExamples.xls
new file mode 100644 (file)
index 0000000..19b4e17
Binary files /dev/null and b/test-data/spreadsheet/countblankExamples.xls differ