}
private Map<String, FreeRefFunction> createFunctionsMap() {
- Map<String, FreeRefFunction> m = new HashMap<>(108);
+ Map<String, FreeRefFunction> m = new HashMap<>(127);
r(m, "ACCRINT", null);
r(m, "ACCRINTM", null);
r(m, "HEX2DEC", Hex2Dec.instance);
r(m, "HEX2OCT", null);
r(m, "IFERROR", IfError.instance);
+ r(m, "IFNA", IfNa.instance);
r(m, "IFS", Ifs.instance);
r(m, "IMABS", null);
r(m, "IMAGINARY", Imaginary.instance);
FunctionMetadata metaData = FunctionMetadataRegistry.getFunctionByName(name);
if(metaData != null) {
throw new IllegalArgumentException(name + " is a built-in Excel function. " +
- "Use FunctoinEval.registerFunction(String name, Function func) instead.");
+ "Use FunctionEval.registerFunction(String name, Function func) instead.");
}
throw new IllegalArgumentException(name + " is not a function from the Excel Analysis Toolpack.");
--- /dev/null
+/* ====================================================================
+ 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.OperandResolver;
+import org.apache.poi.ss.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.functions.FreeRefFunction;
+
+/**
+ * Implementation of 'Analysis Toolpak' the Excel function IFNA()
+ *
+ * <b>Syntax</b>:<br>
+ * <b>IFNA</b>(<b>test_value</b>,<b>default_value</b>)<p>
+ *
+ * <b>test_value</b> The value to be tested<br>
+ * <b>default_value</b> The value to be tested<br>
+ * <br>
+ * Returns {@code default_value} if {@code test_value} is '#N/A', {@code test_value} otherwise.
+ */
+public final class IfNa implements FreeRefFunction {
+
+ public static final FreeRefFunction instance = new IfNa();
+
+ private IfNa() {
+ // Enforce singleton
+ }
+
+ public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
+ if (args.length != 2) {
+ return ErrorEval.VALUE_INVALID;
+ }
+
+ try {
+ return OperandResolver.getSingleValue(args[0], ec.getRowIndex(), ec.getColumnIndex());
+ } catch (EvaluationException e) {
+ ValueEval error = e.getErrorEval();
+ if (error != ErrorEval.NA) {
+ return error;
+ }
+ }
+ try {
+ return OperandResolver.getSingleValue(args[1], ec.getRowIndex(), ec.getColumnIndex());
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+ }
+}
() -> AnalysisToolPak.registerFunction("SUM", TestFunctionRegistry::atpFunc)
);
assertEquals("SUM is a built-in Excel function. " +
- "Use FunctoinEval.registerFunction(String name, Function func) instead.",
+ "Use FunctionEval.registerFunction(String name, Function func) instead.",
ex.getMessage());
}
}
--- /dev/null
+/* ====================================================================
+ 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 static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.formula.eval.ErrorEval;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.CellValue;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.BeforeEach;
+
+
+/**
+ * IfNa unit tests.
+ */
+class TestIfna {
+
+ HSSFWorkbook wb;
+ HSSFCell cell;
+ HSSFFormulaEvaluator fe;
+
+ @BeforeEach
+ void setup() {
+ wb = new HSSFWorkbook();
+ cell = wb.createSheet().createRow(0).createCell(0);
+ fe = new HSSFFormulaEvaluator(wb);
+ }
+
+ @Test
+ void testNumbericArgsWorkCorrectly() {
+ confirmResult(fe, cell, "IFNA(-1,42)", new CellValue(-1.0));
+ confirmResult(fe, cell, "IFNA(NA(),42)", new CellValue(42.0));
+ }
+
+ @Test
+ void testStringArgsWorkCorrectly() {
+ confirmResult(fe, cell, "IFNA(\"a1\",\"a2\")", new CellValue("a1"));
+ confirmResult(fe, cell, "IFNA(NA(),\"a2\")", new CellValue("a2"));
+ }
+
+ @Test
+ void testUsageErrorsThrowErrors() {
+ confirmError(fe, cell, "IFNA(1)", ErrorEval.VALUE_INVALID);
+ confirmError(fe, cell, "IFNA(1,2,3)", ErrorEval.VALUE_INVALID);
+ }
+
+ @Test
+ void testErrorInArgSelectsNAResult() {
+ confirmError(fe, cell, "IFNA(1/0,42)", ErrorEval.DIV_ZERO);
+ }
+
+ @Test
+ void testErrorFromNAArgPassesThrough() {
+ confirmError(fe, cell, "IFNA(NA(),1/0)", ErrorEval.DIV_ZERO);
+ }
+
+ @Test
+ void testNaArgNotEvaledIfUnneeded() {
+ confirmResult(fe, cell, "IFNA(42,1/0)", new CellValue(42.0));
+ }
+
+ private static void confirmResult(HSSFFormulaEvaluator fe, HSSFCell cell, String formulaText,
+ CellValue expectedResult) {
+ fe.setDebugEvaluationOutputForNextEval(true);
+ cell.setCellFormula(formulaText);
+ fe.notifyUpdateCell(cell);
+ CellValue result = fe.evaluate(cell);
+ assertEquals(expectedResult.getCellType(), result.getCellType(), "Testing result type for: " + formulaText);
+ assertEquals(expectedResult.formatAsString(), result.formatAsString(), "Testing result for: " + formulaText);
+ }
+
+ private static void confirmError(HSSFFormulaEvaluator fe, HSSFCell cell, String formulaText,
+ ErrorEval expectedError) {
+ fe.setDebugEvaluationOutputForNextEval(true);
+ cell.setCellFormula(formulaText);
+ fe.notifyUpdateCell(cell);
+ CellValue result = fe.evaluate(cell);
+ assertEquals(CellType.ERROR, result.getCellType(), "Testing result type for: " + formulaText);
+ assertEquals(expectedError.getErrorString(), result.formatAsString(), "Testing error type for: " + formulaText);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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 java.util.stream.Stream;
+
+import org.junit.jupiter.params.provider.Arguments;
+
+/**
+ * Tests for IFNA function as loaded from a test data spreadsheet.<p>
+ */
+class TestIfnaFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet {
+
+ public static Stream<Arguments> data() throws Exception {
+ return data(TestIfnaFromSpreadsheet.class, "IfNaTestCaseData.xls");
+ }
+}