]> source.dussan.org Git - poi.git/commitdiff
Count implementation from ooxml branch
authorNick Burch <nick@apache.org>
Sun, 30 Mar 2008 13:39:51 +0000 (13:39 +0000)
committerNick Burch <nick@apache.org>
Sun, 30 Mar 2008 13:39:51 +0000 (13:39 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@642737 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/hssf/record/formula/functions/Count.java

index 736c37c1b7896f20fc0481cffd0fff9eaa1bbcd0..eb55fc4a421b4cd8c2773b7202d6475ce0f3297c 100644 (file)
  */
 package org.apache.poi.hssf.record.formula.functions;
 
-public class Count extends NotImplementedFunction {
+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.Eval;
+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;
 
-}
+/**
+ * Counts the number of cells that contain numeric data within
+ *  the list of arguments. 
+ *
+ * Excel Syntax
+ * COUNT(value1,value2,...)
+ * Value1, value2, ...   are 1 to 30 arguments representing the values or ranges to be counted.
+ * 
+ * TODO: Check this properly matches excel on edge cases
+ *  like formula cells, error cells etc
+ */
+public class Count implements Function {
+
+       public Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
+               int nArgs = args.length;
+               if (nArgs < 1) {
+                       // too few arguments
+                       return ErrorEval.VALUE_INVALID;
+               }
+
+               if (nArgs > 30) {
+                       // too many arguments
+                       return ErrorEval.VALUE_INVALID;
+               }
+               
+               int temp = 0;
+               
+               for(int i=0; i<nArgs; i++) {
+                       temp += countArg(args[i]);
+                       
+               }
+               return new NumberEval(temp);
+       }
+
+       private static int countArg(Eval eval) {
+        if (eval instanceof AreaEval) {
+            AreaEval ae = (AreaEval) eval;
+            return countAreaEval(ae);
+        }
+        if (eval instanceof RefEval) {
+            RefEval refEval = (RefEval)eval;
+                       return countValue(refEval.getInnerValueEval());
+        }
+        if (eval instanceof NumberEval) {
+            return 1;
+        }
+               
+               throw new RuntimeException("Unexpected eval type (" + eval.getClass().getName() + ")");
+       }
+
+       private static int countAreaEval(AreaEval ae) {
+               
+               int temp = 0;
+               ValueEval[] values = ae.getValues();
+               for (int i = 0; i < values.length; i++) {
+                       ValueEval val = values[i];
+                       if(val == null) {
+                               // seems to occur.  Really we would have expected BlankEval
+                               continue;
+                       }
+                       temp += countValue(val);
+                       
+               }
+               return temp;
+       }
+
+       private static int countValue(ValueEval valueEval) {
+               
+               if(valueEval == BlankEval.INSTANCE) {
+                       return 0;
+               }
+               
+               if(valueEval instanceof BlankEval) {
+                       // wouldn't need this if BlankEval was final
+                       return 0;
+               }
+
+               if(valueEval instanceof ErrorEval) {
+                       // note - error values not counted
+                       return 0;
+               }
+               
+               if(valueEval instanceof NumberEval)
+                       return 1;
+
+               return 0;
+       }
+}
\ No newline at end of file