]> source.dussan.org Git - poi.git/commitdiff
[bug-49202] add PERCENTRANK.INC function
authorPJ Fanning <fanningpj@apache.org>
Sat, 7 Aug 2021 14:42:47 +0000 (14:42 +0000)
committerPJ Fanning <fanningpj@apache.org>
Sat, 7 Aug 2021 14:42:47 +0000 (14:42 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1892081 13f79535-47bb-0310-9956-ffa450edef68

poi/src/main/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java
poi/src/main/java/org/apache/poi/ss/formula/atp/PercentRankIncFunction.java [new file with mode: 0644]
poi/src/test/java/org/apache/poi/ss/formula/atp/TestPercentRankIncFunction.java [new file with mode: 0644]
poi/src/test/java/org/apache/poi/ss/formula/functions/TestPercentRank.java

index f37ac9ecfa13a1417795a30e4e28a72e69e14b11..6eb2c8b8bc08e34dd06851c68b6546ced411c291 100644 (file)
@@ -22,25 +22,7 @@ import org.apache.poi.ss.formula.eval.NotImplementedFunctionException;
 import org.apache.poi.ss.formula.eval.ValueEval;
 import org.apache.poi.ss.formula.function.FunctionMetadata;
 import org.apache.poi.ss.formula.function.FunctionMetadataRegistry;
-import org.apache.poi.ss.formula.functions.Bin2Dec;
-import org.apache.poi.ss.formula.functions.Complex;
-import org.apache.poi.ss.formula.functions.Countifs;
-import org.apache.poi.ss.formula.functions.Dec2Bin;
-import org.apache.poi.ss.formula.functions.Dec2Hex;
-import org.apache.poi.ss.formula.functions.Delta;
-import org.apache.poi.ss.formula.functions.EDate;
-import org.apache.poi.ss.formula.functions.EOMonth;
-import org.apache.poi.ss.formula.functions.FactDouble;
-import org.apache.poi.ss.formula.functions.FreeRefFunction;
-import org.apache.poi.ss.formula.functions.Hex2Dec;
-import org.apache.poi.ss.formula.functions.ImReal;
-import org.apache.poi.ss.formula.functions.Imaginary;
-import org.apache.poi.ss.formula.functions.Oct2Dec;
-import org.apache.poi.ss.formula.functions.Quotient;
-import org.apache.poi.ss.formula.functions.Single;
-import org.apache.poi.ss.formula.functions.Sumifs;
-import org.apache.poi.ss.formula.functions.TextFunction;
-import org.apache.poi.ss.formula.functions.WeekNum;
+import org.apache.poi.ss.formula.functions.*;
 import org.apache.poi.ss.formula.udf.UDFFinder;
 
 /**
@@ -173,6 +155,7 @@ public final class AnalysisToolPak implements UDFFinder {
         r(m, "ODDLPRICE", null);
         r(m, "ODDLYIELD", null);
         r(m, "PRICE", null);
+        r(m, "PERCENTRANK.INC", PercentRankIncFunction.instance);
         r(m, "PRICEDISC", null);
         r(m, "PRICEMAT", null);
         r(m, "QUOTIENT", Quotient.instance);
diff --git a/poi/src/main/java/org/apache/poi/ss/formula/atp/PercentRankIncFunction.java b/poi/src/main/java/org/apache/poi/ss/formula/atp/PercentRankIncFunction.java
new file mode 100644 (file)
index 0000000..878b2ca
--- /dev/null
@@ -0,0 +1,55 @@
+/* ====================================================================
+   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.atp;
+
+import org.apache.poi.ss.formula.OperationEvaluationContext;
+import org.apache.poi.ss.formula.eval.*;
+import org.apache.poi.ss.formula.functions.FreeRefFunction;
+import org.apache.poi.ss.formula.functions.PercentRank;
+
+/**
+ * Implementation of 'Analysis Toolpak' the Excel function PERCENTRANK.INC()
+ *
+ * <b>Syntax</b>:<br>
+ * <b>PERCENTRANK.INC</b>(<b>array</b>, <b>X</b>, <b>[significance]</b>)<p>
+ *
+ * <b>array</b>  The array or range of data with numeric values that defines relative standing.<br>
+ * <b>X</b>  The value for which you want to know the rank.<br>
+ * <b>significance</b>  Optional. A value that identifies the number of significant digits for the returned percentage value.
+ * If omitted, PERCENTRANK.INC uses three digits (0.xxx).<br>
+ * <br>
+ * Returns a number between 0 and 1 representing a percentage.
+ *
+ * @see PercentRank
+ * @since POI 5.0.1
+ */
+final class PercentRankIncFunction implements FreeRefFunction {
+
+    public static final FreeRefFunction instance = new PercentRankIncFunction(ArgumentsEvaluator.instance);
+
+    private ArgumentsEvaluator evaluator;
+
+    private PercentRankIncFunction(ArgumentsEvaluator anEvaluator) {
+        // enforces singleton
+        this.evaluator = anEvaluator;
+    }
+
+    public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
+        return PercentRank.instance.evaluate(args, ec.getRowIndex(), ec.getColumnIndex());
+    }
+}
diff --git a/poi/src/test/java/org/apache/poi/ss/formula/atp/TestPercentRankIncFunction.java b/poi/src/test/java/org/apache/poi/ss/formula/atp/TestPercentRankIncFunction.java
new file mode 100644 (file)
index 0000000..5846ccb
--- /dev/null
@@ -0,0 +1,89 @@
+
+/* ====================================================================
+   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.atp;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.CellValue;
+import org.apache.poi.ss.usermodel.FormulaError;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+import static org.apache.poi.ss.util.Utils.addRow;
+import static org.apache.poi.ss.util.Utils.assertDouble;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Testcase for function PERCENTRANK.INC()
+ */
+public class TestPercentRankIncFunction {
+
+    //https://support.microsoft.com/en-us/office/percentrank-inc-function-149592c9-00c0-49ba-86c1-c1f45b80463a
+    @Test
+    void testMicrosoftExample1() throws IOException {
+        try (HSSFWorkbook wb = initWorkbook1()) {
+            HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
+            HSSFCell cell = wb.getSheetAt(0).getRow(0).createCell(100);
+            assertDouble(fe, cell, "PERCENTRANK.INC(A2:A11,2)", 0.333);
+            assertDouble(fe, cell, "PERCENTRANK.INC(A2:A11,4)", 0.555);
+            assertDouble(fe, cell, "PERCENTRANK.INC(A2:A11,8)", 0.666);
+            assertDouble(fe, cell, "PERCENTRANK.INC(A2:A11,8,2)", 0.66);
+            assertDouble(fe, cell, "PERCENTRANK.INC(A2:A11,8,4)", 0.6666);
+            assertDouble(fe, cell, "PERCENTRANK.INC(A2:A11,5)", 0.583);
+        }
+    }
+
+    @Test
+    void testErrorCases() throws IOException {
+        try (HSSFWorkbook wb = initWorkbook1()) {
+            HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
+            HSSFCell cell = wb.getSheetAt(0).getRow(0).createCell(100);
+            confirmErrorResult(fe, cell, "PERCENTRANK.INC(A2:A11,0)", FormulaError.NA);
+            confirmErrorResult(fe, cell, "PERCENTRANK.INC(A2:A11,100)", FormulaError.NA);
+            confirmErrorResult(fe, cell, "PERCENTRANK.INC(B2:B11,100)", FormulaError.NUM);
+            confirmErrorResult(fe, cell, "PERCENTRANK.INC(A2:A11,8,0)", FormulaError.NUM);
+        }
+    }
+
+    private HSSFWorkbook initWorkbook1() {
+        HSSFWorkbook wb = new HSSFWorkbook();
+        HSSFSheet sheet = wb.createSheet();
+        addRow(sheet, 0, "Data");
+        addRow(sheet, 1, 13);
+        addRow(sheet, 2, 12);
+        addRow(sheet, 3, 11);
+        addRow(sheet, 4, 8);
+        addRow(sheet, 5, 4);
+        addRow(sheet, 6, 3);
+        addRow(sheet, 7, 2);
+        addRow(sheet, 8, 1);
+        addRow(sheet, 9, 1);
+        addRow(sheet, 10, 1);
+        return wb;
+    }
+
+    private static void confirmErrorResult(HSSFFormulaEvaluator fe, HSSFCell cell, String formulaText, FormulaError expectedResult) {
+        cell.setCellFormula(formulaText);
+        fe.notifyUpdateCell(cell);
+        CellValue result = fe.evaluate(cell);
+        assertEquals(expectedResult.getCode(), result.getErrorValue());
+    }
+}
index 3892a3eb1d284d2938d351ffb10ce84c42a4ce87..96f489431d89700d7f9fe8ea985e16cfbdca5749 100644 (file)
@@ -27,6 +27,7 @@ import org.junit.jupiter.api.Test;
 import java.io.IOException;
 
 import static org.apache.poi.ss.util.Utils.addRow;
+import static org.apache.poi.ss.util.Utils.assertDouble;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 /**
@@ -40,12 +41,12 @@ public class TestPercentRank {
         try (HSSFWorkbook wb = initWorkbook1()) {
             HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
             HSSFCell cell = wb.getSheetAt(0).getRow(0).createCell(100);
-            confirmNumericResult(fe, cell, "PERCENTRANK(A2:A11,2)", 0.333);
-            confirmNumericResult(fe, cell, "PERCENTRANK(A2:A11,4)", 0.555);
-            confirmNumericResult(fe, cell, "PERCENTRANK(A2:A11,8)", 0.666);
-            confirmNumericResult(fe, cell, "PERCENTRANK(A2:A11,8,2)", 0.66);
-            confirmNumericResult(fe, cell, "PERCENTRANK(A2:A11,8,4)", 0.6666);
-            confirmNumericResult(fe, cell, "PERCENTRANK(A2:A11,5)", 0.583);
+            assertDouble(fe, cell, "PERCENTRANK(A2:A11,2)", 0.333);
+            assertDouble(fe, cell, "PERCENTRANK(A2:A11,4)", 0.555);
+            assertDouble(fe, cell, "PERCENTRANK(A2:A11,8)", 0.666);
+            assertDouble(fe, cell, "PERCENTRANK(A2:A11,8,2)", 0.66);
+            assertDouble(fe, cell, "PERCENTRANK(A2:A11,8,4)", 0.6666);
+            assertDouble(fe, cell, "PERCENTRANK(A2:A11,5)", 0.583);
         }
     }
 
@@ -78,14 +79,6 @@ public class TestPercentRank {
         return wb;
     }
 
-    private static void confirmNumericResult(HSSFFormulaEvaluator fe, HSSFCell cell, String formulaText, double expectedResult) {
-        cell.setCellFormula(formulaText);
-        fe.notifyUpdateCell(cell);
-        CellValue result = fe.evaluate(cell);
-        assertEquals(result.getCellType(), CellType.NUMERIC);
-        assertEquals(expectedResult, result.getNumberValue(), 0.0001);
-    }
-
     private static void confirmErrorResult(HSSFFormulaEvaluator fe, HSSFCell cell, String formulaText, FormulaError expectedResult) {
         cell.setCellFormula(formulaText);
         fe.notifyUpdateCell(cell);