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 77a4b1109c3..e337905d318 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 @@ -68,6 +68,10 @@ public FreeRefFunction findFunction(String name) { // case-sensitive if(name.startsWith(prefix)) name = name.substring(prefix.length()); + // Google Sheets wraps non-Excel functions with the __xludf. prefix + final String xludfPrefix = "__xludf."; + if(name.startsWith(xludfPrefix)) name = name.substring(xludfPrefix.length()); + // FIXME: inconsistent case-sensitivity return _functionsByName.get(name.toUpperCase(Locale.ROOT)); } @@ -118,6 +122,7 @@ private Map createFunctionsMap() { r(m, "DEC2OCT", null); r(m, "DELTA", Delta.instance); r(m, "DISC", null); + r(m, "DUMMYFUNCTION", DummyFunction.instance); r(m, "DOLLARDE", DollarDe.instance); r(m, "DOLLARFR", DollarFr.instance); r(m, "DURATION", null); diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/DummyFunction.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/DummyFunction.java new file mode 100644 index 00000000000..6b70a7dce16 --- /dev/null +++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/DummyFunction.java @@ -0,0 +1,39 @@ +/* ==================================================================== + 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.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.ValueEval; + +/** + * Implementation for the IFERROR __xludf.DUMMYFUNCTION + *

+ * https://support.microsoft.com/en-au/office/iferror-function-c526fd07-caeb-47b8-8bb6-63f3e417f611 + */ +public class DummyFunction implements FreeRefFunction { + public static final DummyFunction instance = new DummyFunction(); + + @Override + public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { + if (args.length < 2) { + return ErrorEval.VALUE_INVALID; + } + return args[1]; + } +} diff --git a/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDummyFunction.java b/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDummyFunction.java new file mode 100644 index 00000000000..76b4a4eac12 --- /dev/null +++ b/poi/src/test/java/org/apache/poi/ss/formula/functions/TestDummyFunction.java @@ -0,0 +1,75 @@ +/* ==================================================================== + 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.OperationEvaluationContext; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.NumberEval; +import org.apache.poi.ss.formula.eval.StringEval; +import org.apache.poi.ss.formula.eval.ValueEval; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Tests for {@link DummyFunction} + */ +final class TestDummyFunction { + + private static final OperationEvaluationContext ec = new OperationEvaluationContext(null, null, 0, 0, 0, null); + + @Test + void testReturnsCachedNumericValue() { + ValueEval[] args = { + new StringEval("QUERY(A1:D10,\"SELECT A\",1)"), + new NumberEval(42.0) + }; + ValueEval result = DummyFunction.instance.evaluate(args, ec); + assertEquals(NumberEval.class, result.getClass()); + assertEquals(42.0, ((NumberEval) result).getNumberValue(), 0.0); + } + + @Test + void testReturnsCachedStringValue() { + ValueEval[] args = { + new StringEval("GOOGLEFINANCE(\"GOOG\",\"price\")"), + new StringEval("hello") + }; + ValueEval result = DummyFunction.instance.evaluate(args, ec); + assertEquals(StringEval.class, result.getClass()); + assertEquals("hello", ((StringEval) result).getStringValue()); + } + + @Test + void testNoArgsReturnsValueInvalid() { + ValueEval[] args = {}; + ValueEval result = DummyFunction.instance.evaluate(args, ec); + assertEquals(ErrorEval.class, result.getClass()); + assertEquals(ErrorEval.VALUE_INVALID, result); + } + + @Test + void testSingleArgReturnsValueInvalid() { + ValueEval[] args = { + new StringEval("IMPORTRANGE(\"url\",\"Sheet1!A1\")") + }; + ValueEval result = DummyFunction.instance.evaluate(args, ec); + assertEquals(ErrorEval.class, result.getClass()); + assertEquals(ErrorEval.VALUE_INVALID, result); + } +}