diff options
author | PJ Fanning <fanningpj@apache.org> | 2022-02-11 00:12:51 +0000 |
---|---|---|
committer | PJ Fanning <fanningpj@apache.org> | 2022-02-11 00:12:51 +0000 |
commit | 1e85583580d014ba44e6debe4f92f84346d6e59e (patch) | |
tree | 8bd74b351dff0164d58d3b8f07ab4fddf107c3de /poi | |
parent | 9c55c8d45663c4c45482c9f1e98ea369be583e5d (diff) | |
download | poi-1e85583580d014ba44e6debe4f92f84346d6e59e.tar.gz poi-1e85583580d014ba44e6debe4f92f84346d6e59e.zip |
[bug-65879] add WORKDAY.INTL function
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1897953 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'poi')
4 files changed, 93 insertions, 2 deletions
diff --git a/poi/src/main/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java b/poi/src/main/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java index 5dcb5720dd..eaaf184576 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java @@ -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); diff --git a/poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayCalculator.java b/poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayCalculator.java index a0aa551f9b..c9cdcb2853 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayCalculator.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayCalculator.java @@ -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. * diff --git a/poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayFunction.java b/poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayFunction.java index 83cba23259..3793bd7d36 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayFunction.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayFunction.java @@ -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 index 0000000000..5a5ab7023b --- /dev/null +++ b/poi/src/main/java/org/apache/poi/ss/formula/atp/WorkdayIntlFunction.java @@ -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; + } + } + +} |