]> source.dussan.org Git - poi.git/commitdiff
Implement DMAX and DSUM functions, following the pattern from DMIN.
authorGreg Woolsey <gwoolsey@apache.org>
Wed, 27 Dec 2017 22:33:03 +0000 (22:33 +0000)
committerGreg Woolsey <gwoolsey@apache.org>
Wed, 27 Dec 2017 22:33:03 +0000 (22:33 +0000)
Refactored the D* function enum to have instances return the function implementation instances rather than using a case construct, now that Java 8 is required.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1819376 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/ss/formula/eval/FunctionEval.java
src/java/org/apache/poi/ss/formula/functions/DMax.java [new file with mode: 0644]
src/java/org/apache/poi/ss/formula/functions/DStarRunner.java
src/java/org/apache/poi/ss/formula/functions/DSum.java [new file with mode: 0644]
test-data/spreadsheet/DStar.xls

index b327f2504359d59d2de8484f2113a5a3bae7347f..a3505d448b09d81912eaa37cdbc2d9dac9f37ff0 100644 (file)
@@ -106,10 +106,10 @@ public final class FunctionEval {
         retval[38] = BooleanFunction.NOT;
         retval[39] = NumericFunction.MOD;
         // 40: DCOUNT
-        // 41: DSUM
+        retval[41] = new DStarRunner(DStarRunner.DStarAlgorithmEnum.DSUM);
         // 42: DAVERAGE
         retval[43] = new DStarRunner(DStarRunner.DStarAlgorithmEnum.DMIN);
-        // 44: DMAX
+        retval[44] = new DStarRunner(DStarRunner.DStarAlgorithmEnum.DMAX);
         // 45: DSTDEV
         retval[46] = AggregateFunction.VAR;
         // 47: DVAR
@@ -144,7 +144,6 @@ public final class FunctionEval {
         retval[FunctionID.OFFSET] = new Offset(); //nominally 78
 
         retval[82] = TextFunction.SEARCH;
-        // 83: TRANSPOSE
         retval[83] = MatrixFunction.TRANSPOSE;
 
         // 86: TYPE
diff --git a/src/java/org/apache/poi/ss/formula/functions/DMax.java b/src/java/org/apache/poi/ss/formula/functions/DMax.java
new file mode 100644 (file)
index 0000000..4d442f0
--- /dev/null
@@ -0,0 +1,60 @@
+/* ====================================================================
+   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.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;
+
+/**
+ * Implementation of the DMax function:
+ * Finds the maximum value of a column in an area with given conditions.
+ * 
+ * TODO:
+ * - wildcards ? and * in string conditions
+ * - functions as conditions
+ */
+public final class DMax implements IDStarAlgorithm {
+    private ValueEval maximumValue;
+
+    @Override
+    public boolean processMatch(ValueEval eval) {
+        if(eval instanceof NumericValueEval) {
+            if(maximumValue == null) { // First match, just set the value.
+                maximumValue = eval;
+            } else { // There was a previous match, find the new minimum.
+                double currentValue = ((NumericValueEval)eval).getNumberValue();
+                double oldValue = ((NumericValueEval)maximumValue).getNumberValue();
+                if(currentValue > oldValue) {
+                    maximumValue = eval;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    public ValueEval getResult() {
+        if(maximumValue == null) {
+            return NumberEval.ZERO;
+        } else {
+            return maximumValue;
+        }
+    }
+}
index 6a43a62047c43b6e53b3d4734ce1ac3161ea8255..a1f92e781c9f76ac93c6f2b9385bc4a917f88aff 100644 (file)
@@ -17,6 +17,8 @@
 
 package org.apache.poi.ss.formula.functions;
 
+import java.util.function.Supplier;
+
 import org.apache.poi.ss.formula.eval.AreaEval;
 import org.apache.poi.ss.formula.eval.BlankEval;
 import org.apache.poi.ss.formula.eval.ErrorEval;
@@ -39,13 +41,38 @@ import org.apache.poi.ss.util.NumberComparer;
  * - functions as conditions
  */
 public final class DStarRunner implements Function3Arg {
+    /**
+     * Enum for convenience to identify and source implementations of the D* functions
+     */
     public enum DStarAlgorithmEnum {
-        DGET,
-        DMIN,
-        // DMAX, // DMAX is not yet implemented
+        /** @see DGet */
+        DGET(DGet::new),
+        /** @see DMin */
+        DMIN(DMin::new),
+        /** @see DMax */
+        DMAX(DMax::new),
+        /** @see DSum */
+        DSUM(DSum::new),
+        ;
+        
+        private final Supplier<IDStarAlgorithm> implSupplier;
+
+        private DStarAlgorithmEnum(Supplier<IDStarAlgorithm> implSupplier) {
+            this.implSupplier = implSupplier;
+        }
+        
+        /**
+         * @return a new function implementation instance
+         */
+        public IDStarAlgorithm newInstance() {
+            return implSupplier.get();
+        }
     }
     private final DStarAlgorithmEnum algoType;
 
+    /**
+     * @param algorithm to implement
+     */
     public DStarRunner(DStarAlgorithmEnum algorithm) {
         this.algoType = algorithm;
     }
@@ -86,13 +113,7 @@ public final class DStarRunner implements Function3Arg {
         }
 
         // Create an algorithm runner.
-        IDStarAlgorithm algorithm;
-        switch(algoType) {
-            case DGET: algorithm = new DGet(); break;
-            case DMIN: algorithm = new DMin(); break;
-            default:
-                throw new IllegalStateException("Unexpected algorithm type " + algoType + " encountered.");
-        }
+        IDStarAlgorithm algorithm = algoType.newInstance();
 
         // Iterate over all DB entries.
         final int height = db.getHeight();
diff --git a/src/java/org/apache/poi/ss/formula/functions/DSum.java b/src/java/org/apache/poi/ss/formula/functions/DSum.java
new file mode 100644 (file)
index 0000000..2660467
--- /dev/null
@@ -0,0 +1,49 @@
+/* ====================================================================
+   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.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;
+
+/**
+ * Implementation of the DSum function:
+ * Finds the total value of matching values in a column in an area with given conditions.
+ * 
+ * TODO:
+ * - wildcards ? and * in string conditions
+ * - functions as conditions
+ */
+public final class DSum implements IDStarAlgorithm {
+    private double totalValue = 0;
+
+    @Override
+    public boolean processMatch(ValueEval eval) {
+        if(eval instanceof NumericValueEval) {
+            double currentValue = ((NumericValueEval)eval).getNumberValue();
+            totalValue += currentValue;
+        }
+
+        return true;
+    }
+
+    @Override
+    public ValueEval getResult() {
+        return new NumberEval(totalValue);
+    }
+}
index 0c89261426a89341c1521de4db5a393b5fa3ee9a..8a5a45d7ef399cd619b71220dfd5ac90f1e44f8b 100644 (file)
Binary files a/test-data/spreadsheet/DStar.xls and b/test-data/spreadsheet/DStar.xls differ