]> source.dussan.org Git - poi.git/commitdiff
[bug-65879] add WORKDAY.INTL function
authorPJ Fanning <fanningpj@apache.org>
Fri, 11 Feb 2022 00:12:51 +0000 (00:12 +0000)
committerPJ Fanning <fanningpj@apache.org>
Fri, 11 Feb 2022 00:12:51 +0000 (00:12 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1897953 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/WorkdayCalculator.java
poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayFunction.java
poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayIntlFunction.java [new file with mode: 0644]

index 5dcb5720ddfe3628c6cdba238bddcfc7618ac4f3..eaaf1845769bea6bb0a084328d9e1277c2602a76 100644 (file)
@@ -184,6 +184,7 @@ public final class AnalysisToolPak implements UDFFinder {
         r(m, "TEXTJOIN", TextJoinFunction.instance);
         r(m, "WEEKNUM", WeekNum.instance);
         r(m, "WORKDAY", WorkdayFunction.instance);
+        r(m, "WORKDAY.INTL", WorkdayIntlFunction.instance);
         r(m, "XIRR", null);
         r(m, "XLOOKUP", XLookupFunction.instance);
         r(m, "XMATCH", XMatchFunction.instance);
index a0aa551f9b0d0b9eb23fe388bc71e788b1364729..c9cdcb2853b53e90486bff044ea11edf75036a5c 100644 (file)
@@ -89,6 +89,10 @@ public class WorkdayCalculator {
         // enforcing singleton
     }
 
+    public Set<Integer> getValidWeekendTypes() {
+        return weekendTypeMap.keySet();
+    }
+
     /**
      * Calculate how many workdays are there between a start and an end date, as excel representations, considering a range of holidays.
      *
index 83cba232595be39eac31dee0ecd477d75d44edc9..3793bd7d3652af1b4df66601714b406afa82d3d4 100644 (file)
@@ -46,8 +46,8 @@ final class WorkdayFunction implements FreeRefFunction {
     }
 
     /**
-     * Evaluate for WORKDAY. Given a date, a number of days and a optional date or interval of holidays, determines which date it is past
-     * number of parametrized workdays.
+     * Evaluate for WORKDAY. Given a date, a number of days and an optional date or interval of holidays, determines which date it is past
+     * number of parameterized workdays.
      *
      * @return {@link ValueEval} with date as its value.
      */
diff --git a/poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayIntlFunction.java b/poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayIntlFunction.java
new file mode 100644 (file)
index 0000000..5a5ab70
--- /dev/null
@@ -0,0 +1,86 @@
+/* ====================================================================
+   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.ErrorEval;
+import org.apache.poi.ss.formula.eval.EvaluationException;
+import org.apache.poi.ss.formula.eval.NumberEval;
+import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.functions.FreeRefFunction;
+import org.apache.poi.ss.usermodel.DateUtil;
+
+/**
+ * Implementation of Excel 'Analysis ToolPak' function WORKDAY.INTL()<br>
+ * Returns the date past a number of workdays beginning at a start date, considering an interval of holidays. A workday is any non
+ * saturday/sunday date.
+ * <p>
+ * <b>Syntax</b><br>
+ * <b>WORKDAY</b>(<b>startDate</b>, <b>days</b>, weekendType, holidays)
+ * <p>
+ * https://support.microsoft.com/en-us/office/workday-intl-function-a378391c-9ba7-4678-8a39-39611a9bf81d
+ */
+final class WorkdayIntlFunction implements FreeRefFunction {
+
+    public static final FreeRefFunction instance = new WorkdayIntlFunction(ArgumentsEvaluator.instance);
+
+    private ArgumentsEvaluator evaluator;
+
+    private WorkdayIntlFunction(ArgumentsEvaluator anEvaluator) {
+        // enforces singleton
+        this.evaluator = anEvaluator;
+    }
+
+    /**
+     * Evaluate for WORKDAY.INTL. Given a date, a number of days, an optional weekend type
+     * and an optional date or interval of holidays, determines which date it is past
+     * number of parameterized workdays.
+     *
+     * @return {@link ValueEval} with date as its value.
+     */
+    public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
+        if (args.length < 2 || args.length > 4) {
+            return ErrorEval.VALUE_INVALID;
+        }
+
+        int srcCellRow = ec.getRowIndex();
+        int srcCellCol = ec.getColumnIndex();
+
+        double start;
+        int days;
+        int weekendType = 1;
+        double[] holidays;
+        try {
+            start = this.evaluator.evaluateDateArg(args[0], srcCellRow, srcCellCol);
+            days = (int) Math.floor(this.evaluator.evaluateNumberArg(args[1], srcCellRow, srcCellCol));
+            if (args.length >= 3) {
+                weekendType = (int) this.evaluator.evaluateNumberArg(args[2], srcCellRow, srcCellCol);
+                if (!WorkdayCalculator.instance.getValidWeekendTypes().contains(weekendType)) {
+                   return ErrorEval.NUM_ERROR;
+                }
+            }
+            ValueEval holidaysCell = args.length >= 4 ? args[3] : null;
+            holidays = this.evaluator.evaluateDatesArg(holidaysCell, srcCellRow, srcCellCol);
+            return new NumberEval(DateUtil.getExcelDate(
+                    WorkdayCalculator.instance.calculateWorkdays(start, days, weekendType, holidays)));
+        } catch (EvaluationException e) {
+            return ErrorEval.VALUE_INVALID;
+        }
+    }
+
+}