blob: 2ff1df501c3e4c34ab001b0407e27fe9cc661ded [file] [log] [blame]
/*
* ====================================================================
* 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 static org.junit.jupiter.api.Assertions.assertEquals;
import org.apache.poi.hssf.HSSFTestDataSamples;
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.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.junit.jupiter.api.Test;
/**
* Test for Excel function INTERCEPT()
*/
final class TestIntercept {
private static final Function INTERCEPT = new Intercept();
private static ValueEval invoke(Function function, ValueEval xArray, ValueEval yArray) {
ValueEval[] args = new ValueEval[] { xArray, yArray, };
return function.evaluate(args, -1, (short)-1);
}
private void confirm(Function function, ValueEval xArray, ValueEval yArray, double expected) {
ValueEval result = invoke(function, xArray, yArray);
assertEquals(NumberEval.class, result.getClass());
assertEquals(expected, ((NumberEval)result).getNumberValue(), 0);
}
private void confirmError(Function function, ValueEval xArray, ValueEval yArray, ErrorEval expectedError) {
ValueEval result = invoke(function, xArray, yArray);
assertEquals(ErrorEval.class, result.getClass());
assertEquals(expectedError.getErrorCode(), ((ErrorEval)result).getErrorCode());
}
private void confirmError(ValueEval xArray, ValueEval yArray, ErrorEval expectedError) {
confirmError(INTERCEPT, xArray, yArray, expectedError);
}
@Test
void testBasic() {
Double exp = Math.pow(10, 7.5);
ValueEval[] yValues = {
new NumberEval(3+exp),
new NumberEval(4+exp),
new NumberEval(2+exp),
new NumberEval(5+exp),
new NumberEval(4+exp),
new NumberEval(7+exp),
};
ValueEval areaEvalY = createAreaEval(yValues);
ValueEval[] xValues = {
new NumberEval(1),
new NumberEval(2),
new NumberEval(3),
new NumberEval(4),
new NumberEval(5),
new NumberEval(6),
};
ValueEval areaEvalX = createAreaEval(xValues);
confirm(INTERCEPT, areaEvalX, areaEvalY, -24516534.39905822);
// Excel 2010 gives -24516534.3990583
}
/**
* number of items in array is not limited to 30
*/
@Test
void testLargeArrays() {
ValueEval[] yValues = createMockNumberArray(100, 3); // [1,2,0,1,2,0,...,0,1]
yValues[0] = new NumberEval(2.0); // Changes first element to 2
ValueEval[] xValues = createMockNumberArray(100, 101); // [1,2,3,4,...,99,100]
confirm(INTERCEPT, createAreaEval(xValues), createAreaEval(yValues), 51.74384236453202);
// Excel 2010 gives 51.74384236453200
}
private ValueEval[] createMockNumberArray(int size, double value) {
ValueEval[] result = new ValueEval[size];
for (int i = 0; i < result.length; i++) {
result[i] = new NumberEval((i+1)%value);
}
return result;
}
private static ValueEval createAreaEval(ValueEval[] values) {
String refStr = "A1:A" + values.length;
return EvalFactory.createAreaEval(refStr, values);
}
@Test
void testErrors() {
ValueEval[] xValues = {
ErrorEval.REF_INVALID,
new NumberEval(2),
};
ValueEval areaEvalX = createAreaEval(xValues);
ValueEval[] yValues = {
new NumberEval(2),
ErrorEval.NULL_INTERSECTION,
};
ValueEval areaEvalY = createAreaEval(yValues);
ValueEval[] zValues = { // wrong size
new NumberEval(2),
};
ValueEval areaEvalZ = createAreaEval(zValues);
// if either arg is an error, that error propagates
confirmError(ErrorEval.REF_INVALID, ErrorEval.NAME_INVALID, ErrorEval.REF_INVALID);
confirmError(areaEvalX, ErrorEval.NAME_INVALID, ErrorEval.NAME_INVALID);
confirmError(ErrorEval.NAME_INVALID, areaEvalX, ErrorEval.NAME_INVALID);
// array sizes must match
confirmError(areaEvalX, areaEvalZ, ErrorEval.NA);
confirmError(areaEvalZ, areaEvalY, ErrorEval.NA);
// any error in an array item propagates up
confirmError(areaEvalX, areaEvalX, ErrorEval.REF_INVALID);
// search for errors array by array, not pair by pair
confirmError(areaEvalX, areaEvalY, ErrorEval.NULL_INTERSECTION);
confirmError(areaEvalY, areaEvalX, ErrorEval.REF_INVALID);
}
/**
* Example from
* http://office.microsoft.com/en-us/excel-help/intercept-function-HP010062512.aspx?CTT=5&origin=HA010277524
*/
@Test
void testFromFile() {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("intercept.xls");
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
HSSFSheet example1 = wb.getSheet("Example 1");
HSSFCell a8 = example1.getRow(7).getCell(0);
assertEquals("INTERCEPT(A2:A6,B2:B6)", a8.getCellFormula());
fe.evaluate(a8);
assertEquals(0.048387097, a8.getNumericCellValue(), 0.000000001);
}
}