]> source.dussan.org Git - poi.git/commitdiff
support empty param for DCount
authorPJ Fanning <fanningpj@apache.org>
Wed, 25 May 2022 14:53:42 +0000 (14:53 +0000)
committerPJ Fanning <fanningpj@apache.org>
Wed, 25 May 2022 14:53:42 +0000 (14:53 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1901242 13f79535-47bb-0310-9956-ffa450edef68

poi/src/main/java/org/apache/poi/ss/formula/functions/DCount.java
poi/src/main/java/org/apache/poi/ss/formula/functions/DGet.java
poi/src/main/java/org/apache/poi/ss/formula/functions/DMax.java
poi/src/main/java/org/apache/poi/ss/formula/functions/DMin.java
poi/src/main/java/org/apache/poi/ss/formula/functions/DStarRunner.java
poi/src/main/java/org/apache/poi/ss/formula/functions/DSum.java
poi/src/main/java/org/apache/poi/ss/formula/functions/IDStarAlgorithm.java
poi/src/test/java/org/apache/poi/ss/formula/functions/TestDCount.java

index a8c2ca22e15270f00028ca4231c915348f8fb14f..c925652e7fba57d59e1aa2f21a024e750be720a0 100644 (file)
@@ -18,6 +18,7 @@
 package org.apache.poi.ss.formula.functions;
 
 import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.NumericValueEval;
 import org.apache.poi.ss.formula.eval.ValueEval;
 
 /**
@@ -28,8 +29,10 @@ public final class DCount implements IDStarAlgorithm {
     private int count;
 
     @Override
-    public boolean processMatch(ValueEval eval) {
-        count++;
+    public boolean processMatch(ValueEval eval, String field) {
+        if (field == null || eval instanceof NumericValueEval) {
+            count++;
+        }
         return true;
     }
 
@@ -37,4 +40,9 @@ public final class DCount implements IDStarAlgorithm {
     public ValueEval getResult() {
         return new NumberEval(count);
     }
+
+    @Override
+    public boolean allowEmptyMatchField() {
+        return true;
+    }
 }
index 78b1b9235ee87e547a81a6f610abc7273e53fa3a..606e13d7cfecff42d6030395d6aab5467386f75c 100644 (file)
@@ -31,7 +31,7 @@ public final class DGet implements IDStarAlgorithm {
     private ValueEval result;
 
     @Override
-    public boolean processMatch(ValueEval eval) {
+    public boolean processMatch(ValueEval eval, String field) {
         if(result == null) // First match, just set the value.
         {
             result = eval;
index 4d442f041512df6ee27c0dfe834de0ebf79f6fdc..0960e8c667f0040199e8514a3a201d200715607d 100644 (file)
@@ -33,7 +33,7 @@ public final class DMax implements IDStarAlgorithm {
     private ValueEval maximumValue;
 
     @Override
-    public boolean processMatch(ValueEval eval) {
+    public boolean processMatch(ValueEval eval, String field) {
         if(eval instanceof NumericValueEval) {
             if(maximumValue == null) { // First match, just set the value.
                 maximumValue = eval;
index 61b75768c7116ef5bf3ea5851a0244dd62451bcf..8919dc9426e92dbb2b8184aba85733f8934c6d5d 100644 (file)
@@ -33,7 +33,7 @@ public final class DMin implements IDStarAlgorithm {
     private ValueEval minimumValue;
 
     @Override
-    public boolean processMatch(ValueEval eval) {
+    public boolean processMatch(ValueEval eval, String field) {
         if(eval instanceof NumericValueEval) {
             if(minimumValue == null) { // First match, just set the value.
                 minimumValue = eval;
index 369288d1fbf27cc439655b34ecc31693398c3aa1..fc2e61b01a57e1a3e6d0966a614ffd51b9e42943 100644 (file)
@@ -80,7 +80,7 @@ public final class DStarRunner implements Function3Arg {
         this.algoType = algorithm;
     }
 
-    public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+    public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
         if(args.length == 3) {
             return evaluate(srcRowIndex, srcColumnIndex, args[0], args[1], args[2]);
         }
@@ -98,25 +98,31 @@ public final class DStarRunner implements Function3Arg {
         AreaEval db = (AreaEval)database;
         AreaEval cdb = (AreaEval)conditionDatabase;
 
-        try {
-            filterColumn = OperandResolver.getSingleValue(filterColumn, srcRowIndex, srcColumnIndex);
-        } catch (EvaluationException e) {
-            return e.getErrorEval();
-        }
+        // Create an algorithm runner.
+        final IDStarAlgorithm algorithm = algoType.newInstance();
 
-        int fc;
+        int fc = -1;
+        String field = null;
         try {
+            filterColumn = OperandResolver.getSingleValue(filterColumn, srcRowIndex, srcColumnIndex);
             fc = getColumnForName(filterColumn, db);
-        }
-        catch (EvaluationException e) {
-            return ErrorEval.VALUE_INVALID;
-        }
-        if(fc == -1) { // column not found
-            return ErrorEval.VALUE_INVALID;
+            if (filterColumn instanceof StringEval) {
+                field = ((StringEval)filterColumn).getStringValue();
+            }
+            if(fc == -1 && !algorithm.allowEmptyMatchField()) {
+                // column not found
+                return ErrorEval.VALUE_INVALID;
+            }
+        } catch (EvaluationException e) {
+            if (!algorithm.allowEmptyMatchField()) {
+                return e.getErrorEval();
+            }
+        } catch (Exception e) {
+            if (!algorithm.allowEmptyMatchField()) {
+                return ErrorEval.VALUE_INVALID;
+            }
         }
 
-        // Create an algorithm runner.
-        IDStarAlgorithm algorithm = algoType.newInstance();
 
         // Iterate over all DB entries.
         final int height = db.getHeight();
@@ -132,7 +138,7 @@ public final class DStarRunner implements Function3Arg {
             if(matches) {
                 ValueEval currentValueEval = resolveReference(db, row, fc);
                 // Pass the match to the algorithm and conditionally abort the search.
-                boolean shouldContinue = algorithm.processMatch(currentValueEval);
+                boolean shouldContinue = algorithm.processMatch(currentValueEval, field);
                 if(! shouldContinue) {
                     break;
                 }
index 26604677deddc3232470e4e6227e9f133b14bfc5..df60f7063a572e9ff787a75a82e1aaa6cdacede8 100644 (file)
@@ -33,7 +33,7 @@ public final class DSum implements IDStarAlgorithm {
     private double totalValue = 0;
 
     @Override
-    public boolean processMatch(ValueEval eval) {
+    public boolean processMatch(ValueEval eval, String field) {
         if(eval instanceof NumericValueEval) {
             double currentValue = ((NumericValueEval)eval).getNumberValue();
             totalValue += currentValue;
index 111964a4c47bae40eceda6ce94a09456a5e88456..e9fbd6c7be035d9372ac3343c3a951c73b4adf2e 100644 (file)
@@ -27,13 +27,24 @@ public interface IDStarAlgorithm {
     /**
      * Process a match that is found during a run through a database.
      * @param eval ValueEval of the cell in the matching row. References will already be resolved.
+     * @param field the field name (added in POI 5.2.3)
      * @return Whether we should continue iterating through the database.
      */
-    boolean processMatch(ValueEval eval);
+    boolean processMatch(ValueEval eval, String field);
+
     /**
      * Return a result ValueEval that will be the result of the calculation.
      * This is always called at the end of a run through the database.
      * @return a ValueEval
      */
     ValueEval getResult();
+
+    /**
+     * Whether the field value (the 2nd param in DCOUNT, DGET, etc.) can evaluate to empty. It
+     * is allowed to evaluate to empty for DCOUNT.
+     * @return whether the field value can evaluate to empty
+     */
+    default boolean allowEmptyMatchField() {
+        return false;
+    }
 }
index 65af098221af0d14444a9bc557ff03b9849614f0..c970db1638abf2c28f73826b2f5aa8cbc474e590 100644 (file)
@@ -39,7 +39,8 @@ public class TestDCount {
         try (HSSFWorkbook wb = initWorkbook1()) {
             HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
             HSSFCell cell = wb.getSheetAt(0).getRow(0).createCell(100);
-            assertDouble(fe, cell, "DCOUNT(A5:E11, \"Age\", A1:A2)", 3);
+            assertDouble(fe, cell, "DCOUNT(A5:E11,,A1:A2)", 3);
+            assertDouble(fe, cell, "DCOUNT(A5:E11, \"Age\", A1:A2)", 2);
             //next one returns 0 in error
             //assertDouble(fe, cell, "DCOUNT(A5:E11, \"Age\", A1:F2)", 1);
         }