610 lines
24 KiB
Java
610 lines
24 KiB
Java
/* ====================================================================
|
|
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;
|
|
|
|
import static org.junit.Assert.assertEquals;
|
|
import static org.junit.Assert.assertFalse;
|
|
import static org.junit.Assert.assertSame;
|
|
import static org.junit.Assert.assertTrue;
|
|
import static org.junit.Assert.fail;
|
|
|
|
import java.io.IOException;
|
|
|
|
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.HSSFRow;
|
|
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
|
import org.apache.poi.ss.formula.eval.BlankEval;
|
|
import org.apache.poi.ss.formula.eval.ErrorEval;
|
|
import org.apache.poi.ss.formula.eval.MissingArgEval;
|
|
import org.apache.poi.ss.formula.eval.NumberEval;
|
|
import org.apache.poi.ss.formula.eval.ValueEval;
|
|
import org.apache.poi.ss.formula.ptg.AreaErrPtg;
|
|
import org.apache.poi.ss.formula.ptg.AttrPtg;
|
|
import org.apache.poi.ss.formula.ptg.DeletedArea3DPtg;
|
|
import org.apache.poi.ss.formula.ptg.DeletedRef3DPtg;
|
|
import org.apache.poi.ss.formula.ptg.IntPtg;
|
|
import org.apache.poi.ss.formula.ptg.Ptg;
|
|
import org.apache.poi.ss.formula.ptg.RefErrorPtg;
|
|
import org.apache.poi.ss.usermodel.Cell;
|
|
import org.apache.poi.ss.usermodel.CellType;
|
|
import org.apache.poi.ss.usermodel.CellValue;
|
|
import org.apache.poi.ss.usermodel.FormulaEvaluator;
|
|
import org.apache.poi.ss.usermodel.Name;
|
|
import org.apache.poi.ss.usermodel.Row;
|
|
import org.apache.poi.ss.usermodel.Sheet;
|
|
import org.apache.poi.ss.usermodel.Workbook;
|
|
import org.junit.Ignore;
|
|
import org.junit.Test;
|
|
|
|
/**
|
|
* Tests {@link WorkbookEvaluator}.
|
|
*
|
|
* @author Josh Micich
|
|
*/
|
|
public class TestWorkbookEvaluator {
|
|
|
|
private static final double EPSILON = 0.0000001;
|
|
|
|
private static ValueEval evaluateFormula(Ptg[] ptgs) {
|
|
OperationEvaluationContext ec = new OperationEvaluationContext(null, null, 0, 0, 0, null);
|
|
return new WorkbookEvaluator(null, null, null).evaluateFormula(ec, ptgs);
|
|
}
|
|
|
|
/**
|
|
* Make sure that the evaluator can directly handle tAttrSum (instead of relying on re-parsing
|
|
* the whole formula which converts tAttrSum to tFuncVar("SUM") )
|
|
*/
|
|
@Test
|
|
public void testAttrSum() {
|
|
|
|
Ptg[] ptgs = {
|
|
new IntPtg(42),
|
|
AttrPtg.SUM,
|
|
};
|
|
|
|
ValueEval result = evaluateFormula(ptgs);
|
|
assertEquals(42, ((NumberEval)result).getNumberValue(), 0.0);
|
|
}
|
|
|
|
/**
|
|
* Make sure that the evaluator can directly handle (deleted) ref error tokens
|
|
* (instead of relying on re-parsing the whole formula which converts these
|
|
* to the error constant #REF! )
|
|
*/
|
|
@Test
|
|
public void testRefErr() {
|
|
|
|
confirmRefErr(new RefErrorPtg());
|
|
confirmRefErr(new AreaErrPtg());
|
|
confirmRefErr(new DeletedRef3DPtg(0));
|
|
confirmRefErr(new DeletedArea3DPtg(0));
|
|
}
|
|
private static void confirmRefErr(Ptg ptg) {
|
|
Ptg[] ptgs = {
|
|
ptg,
|
|
};
|
|
|
|
ValueEval result = evaluateFormula(ptgs);
|
|
assertEquals(ErrorEval.REF_INVALID, result);
|
|
}
|
|
|
|
/**
|
|
* Make sure that the evaluator can directly handle tAttrSum (instead of relying on re-parsing
|
|
* the whole formula which converts tAttrSum to tFuncVar("SUM") )
|
|
*/
|
|
@Test
|
|
public void testMemFunc() {
|
|
|
|
Ptg[] ptgs = {
|
|
new IntPtg(42),
|
|
AttrPtg.SUM,
|
|
};
|
|
|
|
ValueEval result = evaluateFormula(ptgs);
|
|
assertEquals(42, ((NumberEval)result).getNumberValue(), 0.0);
|
|
}
|
|
|
|
|
|
@Test
|
|
public void testEvaluateMultipleWorkbooks() {
|
|
HSSFWorkbook wbA = HSSFTestDataSamples.openSampleWorkbook("multibookFormulaA.xls");
|
|
HSSFWorkbook wbB = HSSFTestDataSamples.openSampleWorkbook("multibookFormulaB.xls");
|
|
|
|
HSSFFormulaEvaluator evaluatorA = new HSSFFormulaEvaluator(wbA);
|
|
HSSFFormulaEvaluator evaluatorB = new HSSFFormulaEvaluator(wbB);
|
|
|
|
// Hook up the workbook evaluators to enable evaluation of formulas across books
|
|
String[] bookNames = { "multibookFormulaA.xls", "multibookFormulaB.xls", };
|
|
HSSFFormulaEvaluator[] evaluators = { evaluatorA, evaluatorB, };
|
|
HSSFFormulaEvaluator.setupEnvironment(bookNames, evaluators);
|
|
|
|
HSSFCell cell;
|
|
|
|
HSSFSheet aSheet1 = wbA.getSheetAt(0);
|
|
HSSFSheet bSheet1 = wbB.getSheetAt(0);
|
|
|
|
// Simple case - single link from wbA to wbB
|
|
confirmFormula(wbA, 0, 0, 0, "[multibookFormulaB.xls]BSheet1!B1");
|
|
cell = aSheet1.getRow(0).getCell(0);
|
|
confirmEvaluation(35, evaluatorA, cell);
|
|
|
|
|
|
// more complex case - back link into wbA
|
|
// [wbA]ASheet1!A2 references (among other things) [wbB]BSheet1!B2
|
|
confirmFormula(wbA, 0, 1, 0, "[multibookFormulaB.xls]BSheet1!$B$2+2*A3");
|
|
// [wbB]BSheet1!B2 references (among other things) [wbA]AnotherSheet!A1:B2
|
|
confirmFormula(wbB, 0, 1, 1, "SUM([multibookFormulaA.xls]AnotherSheet!$A$1:$B$2)+B3");
|
|
|
|
cell = aSheet1.getRow(1).getCell(0);
|
|
confirmEvaluation(264, evaluatorA, cell);
|
|
|
|
// change [wbB]BSheet1!B3 (from 50 to 60)
|
|
HSSFCell cellB3 = bSheet1.getRow(2).getCell(1);
|
|
cellB3.setCellValue(60);
|
|
evaluatorB.notifyUpdateCell(cellB3);
|
|
confirmEvaluation(274, evaluatorA, cell);
|
|
|
|
// change [wbA]ASheet1!A3 (from 100 to 80)
|
|
HSSFCell cellA3 = aSheet1.getRow(2).getCell(0);
|
|
cellA3.setCellValue(80);
|
|
evaluatorA.notifyUpdateCell(cellA3);
|
|
confirmEvaluation(234, evaluatorA, cell);
|
|
|
|
// change [wbA]AnotherSheet!A1 (from 2 to 3)
|
|
HSSFCell cellA1 = wbA.getSheetAt(1).getRow(0).getCell(0);
|
|
cellA1.setCellValue(3);
|
|
evaluatorA.notifyUpdateCell(cellA1);
|
|
confirmEvaluation(235, evaluatorA, cell);
|
|
}
|
|
|
|
private static void confirmEvaluation(double expectedValue, HSSFFormulaEvaluator fe, HSSFCell cell) {
|
|
assertEquals(expectedValue, fe.evaluate(cell).getNumberValue(), 0.0);
|
|
}
|
|
|
|
private static void confirmFormula(HSSFWorkbook wb, int sheetIndex, int rowIndex, int columnIndex,
|
|
String expectedFormula) {
|
|
HSSFCell cell = wb.getSheetAt(sheetIndex).getRow(rowIndex).getCell(columnIndex);
|
|
assertEquals(expectedFormula, cell.getCellFormula());
|
|
}
|
|
|
|
/**
|
|
* This test makes sure that any {@link MissingArgEval} that propagates to
|
|
* the result of a function gets translated to {@link BlankEval}.
|
|
*/
|
|
@Test
|
|
public void testMissingArg() {
|
|
HSSFWorkbook wb = new HSSFWorkbook();
|
|
HSSFSheet sheet = wb.createSheet("Sheet1");
|
|
HSSFRow row = sheet.createRow(0);
|
|
HSSFCell cell = row.createCell(0);
|
|
cell.setCellFormula("1+IF(1,,)");
|
|
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
|
CellValue cv = null;
|
|
try {
|
|
cv = fe.evaluate(cell);
|
|
} catch (RuntimeException e) {
|
|
fail("Missing arg result not being handled correctly.");
|
|
}
|
|
assertEquals(CellType.NUMERIC, cv.getCellTypeEnum());
|
|
// adding blank to 1.0 gives 1.0
|
|
assertEquals(1.0, cv.getNumberValue(), 0.0);
|
|
|
|
// check with string operand
|
|
cell.setCellFormula("\"abc\"&IF(1,,)");
|
|
fe.notifySetFormula(cell);
|
|
cv = fe.evaluate(cell);
|
|
assertEquals(CellType.STRING, cv.getCellTypeEnum());
|
|
// adding blank to "abc" gives "abc"
|
|
assertEquals("abc", cv.getStringValue());
|
|
|
|
// check CHOOSE()
|
|
cell.setCellFormula("\"abc\"&CHOOSE(2,5,,9)");
|
|
fe.notifySetFormula(cell);
|
|
cv = fe.evaluate(cell);
|
|
assertEquals(CellType.STRING, cv.getCellTypeEnum());
|
|
// adding blank to "abc" gives "abc"
|
|
assertEquals("abc", cv.getStringValue());
|
|
}
|
|
|
|
/**
|
|
* Functions like IF, INDIRECT, INDEX, OFFSET etc can return AreaEvals which
|
|
* should be dereferenced by the evaluator
|
|
* @throws IOException
|
|
*/
|
|
@Test
|
|
public void testResultOutsideRange() throws IOException {
|
|
Workbook wb = new HSSFWorkbook();
|
|
try {
|
|
Cell cell = wb.createSheet("Sheet1").createRow(0).createCell(0);
|
|
cell.setCellFormula("D2:D5"); // IF(TRUE,D2:D5,D2) or OFFSET(D2:D5,0,0) would work too
|
|
FormulaEvaluator fe = wb.getCreationHelper().createFormulaEvaluator();
|
|
CellValue cv;
|
|
try {
|
|
cv = fe.evaluate(cell);
|
|
} catch (IllegalArgumentException e) {
|
|
if ("Specified row index (0) is outside the allowed range (1..4)".equals(e.getMessage())) {
|
|
fail("Identified bug in result dereferencing");
|
|
}
|
|
throw new RuntimeException(e);
|
|
}
|
|
assertEquals(CellType.ERROR, cv.getCellTypeEnum());
|
|
assertEquals(ErrorEval.VALUE_INVALID.getErrorCode(), cv.getErrorValue());
|
|
|
|
// verify circular refs are still detected properly
|
|
fe.clearAllCachedResultValues();
|
|
cell.setCellFormula("OFFSET(A1,0,0)");
|
|
cv = fe.evaluate(cell);
|
|
assertEquals(CellType.ERROR, cv.getCellTypeEnum());
|
|
assertEquals(ErrorEval.CIRCULAR_REF_ERROR.getErrorCode(), cv.getErrorValue());
|
|
} finally {
|
|
wb.close();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* formulas with defined names.
|
|
* @throws IOException
|
|
*/
|
|
@Test
|
|
public void testNamesInFormulas() throws IOException {
|
|
Workbook wb = new HSSFWorkbook();
|
|
Sheet sheet = wb.createSheet("Sheet1");
|
|
|
|
Name name1 = wb.createName();
|
|
name1.setNameName("aConstant");
|
|
name1.setRefersToFormula("3.14");
|
|
|
|
Name name2 = wb.createName();
|
|
name2.setNameName("aFormula");
|
|
name2.setRefersToFormula("SUM(Sheet1!$A$1:$A$3)");
|
|
|
|
Name name3 = wb.createName();
|
|
name3.setNameName("aSet");
|
|
name3.setRefersToFormula("Sheet1!$A$2:$A$4");
|
|
|
|
|
|
Row row0 = sheet.createRow(0);
|
|
Row row1 = sheet.createRow(1);
|
|
Row row2 = sheet.createRow(2);
|
|
Row row3 = sheet.createRow(3);
|
|
row0.createCell(0).setCellValue(2);
|
|
row1.createCell(0).setCellValue(5);
|
|
row2.createCell(0).setCellValue(3);
|
|
row3.createCell(0).setCellValue(7);
|
|
|
|
row0.createCell(2).setCellFormula("aConstant");
|
|
row1.createCell(2).setCellFormula("aFormula");
|
|
row2.createCell(2).setCellFormula("SUM(aSet)");
|
|
row3.createCell(2).setCellFormula("aConstant+aFormula+SUM(aSet)");
|
|
|
|
FormulaEvaluator fe = wb.getCreationHelper().createFormulaEvaluator();
|
|
assertEquals(3.14, fe.evaluate(row0.getCell(2)).getNumberValue(), EPSILON);
|
|
assertEquals(10.0, fe.evaluate(row1.getCell(2)).getNumberValue(), EPSILON);
|
|
assertEquals(15.0, fe.evaluate(row2.getCell(2)).getNumberValue(), EPSILON);
|
|
assertEquals(28.14, fe.evaluate(row3.getCell(2)).getNumberValue(), EPSILON);
|
|
|
|
wb.close();
|
|
}
|
|
|
|
@Test
|
|
public void testIgnoreMissingWorkbooks() {
|
|
// TODO: update this test for meaningful functional behavior
|
|
WorkbookEvaluator evaluator = new WorkbookEvaluator(null, null, null);
|
|
assertFalse(evaluator.isIgnoreMissingWorkbooks());
|
|
|
|
evaluator.setIgnoreMissingWorkbooks(true);
|
|
assertTrue(evaluator.isIgnoreMissingWorkbooks());
|
|
|
|
evaluator.setIgnoreMissingWorkbooks(false);
|
|
assertFalse(evaluator.isIgnoreMissingWorkbooks());
|
|
}
|
|
|
|
@Test
|
|
public void testDebugEvaluationOutputForNextEval() {
|
|
// TODO: update this test for meaningful functional behavior
|
|
WorkbookEvaluator evaluator = new WorkbookEvaluator(null, null, null);
|
|
assertFalse(evaluator.isDebugEvaluationOutputForNextEval());
|
|
|
|
evaluator.setDebugEvaluationOutputForNextEval(true);
|
|
assertTrue(evaluator.isDebugEvaluationOutputForNextEval());
|
|
|
|
evaluator.setDebugEvaluationOutputForNextEval(false);
|
|
assertFalse(evaluator.isDebugEvaluationOutputForNextEval());
|
|
}
|
|
|
|
// Test IF-Equals Formula Evaluation (bug 58591)
|
|
|
|
private Workbook testIFEqualsFormulaEvaluation_setup(String formula, CellType a1CellType) {
|
|
Workbook wb = new HSSFWorkbook();
|
|
Sheet sheet = wb.createSheet("IFEquals");
|
|
Row row = sheet.createRow(0);
|
|
Cell A1 = row.createCell(0);
|
|
Cell B1 = row.createCell(1);
|
|
Cell C1 = row.createCell(2);
|
|
Cell D1 = row.createCell(3);
|
|
|
|
switch (a1CellType) {
|
|
case NUMERIC:
|
|
A1.setCellValue(1.0);
|
|
// "A1=1" should return true
|
|
break;
|
|
case STRING:
|
|
A1.setCellValue("1");
|
|
// "A1=1" should return false
|
|
// "A1=\"1\"" should return true
|
|
break;
|
|
case BOOLEAN:
|
|
A1.setCellValue(true);
|
|
// "A1=1" should return true
|
|
break;
|
|
case FORMULA:
|
|
A1.setCellFormula("1");
|
|
// "A1=1" should return true
|
|
break;
|
|
case BLANK:
|
|
A1.setCellValue((String) null);
|
|
// "A1=1" should return false
|
|
break;
|
|
default:
|
|
throw new IllegalArgumentException("unexpected cell type: " + a1CellType);
|
|
}
|
|
B1.setCellValue(2.0);
|
|
C1.setCellValue(3.0);
|
|
D1.setCellFormula(formula);
|
|
|
|
return wb;
|
|
}
|
|
|
|
private void testIFEqualsFormulaEvaluation_teardown(Workbook wb) {
|
|
try {
|
|
wb.close();
|
|
} catch (final IOException e) {
|
|
fail("Unable to close workbook");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private void testIFEqualsFormulaEvaluation_evaluate(
|
|
String formula, CellType cellType, String expectedFormula, double expectedResult) {
|
|
Workbook wb = testIFEqualsFormulaEvaluation_setup(formula, cellType);
|
|
Cell D1 = wb.getSheet("IFEquals").getRow(0).getCell(3);
|
|
|
|
FormulaEvaluator eval = wb.getCreationHelper().createFormulaEvaluator();
|
|
CellValue result = eval.evaluate(D1);
|
|
|
|
// Call should not modify the contents
|
|
assertEquals(CellType.FORMULA, D1.getCellTypeEnum());
|
|
assertEquals(expectedFormula, D1.getCellFormula());
|
|
|
|
assertEquals(CellType.NUMERIC, result.getCellTypeEnum());
|
|
assertEquals(expectedResult, result.getNumberValue(), EPSILON);
|
|
|
|
testIFEqualsFormulaEvaluation_teardown(wb);
|
|
}
|
|
|
|
private void testIFEqualsFormulaEvaluation_eval(
|
|
final String formula, final CellType cellType, final String expectedFormula, final double expectedValue) {
|
|
testIFEqualsFormulaEvaluation_evaluate(formula, cellType, expectedFormula, expectedValue);
|
|
testIFEqualsFormulaEvaluation_evaluateFormulaCell(formula, cellType, expectedFormula, expectedValue);
|
|
testIFEqualsFormulaEvaluation_evaluateInCell(formula, cellType, expectedFormula, expectedValue);
|
|
testIFEqualsFormulaEvaluation_evaluateAll(formula, cellType, expectedFormula, expectedValue);
|
|
testIFEqualsFormulaEvaluation_evaluateAllFormulaCells(formula, cellType, expectedFormula, expectedValue);
|
|
}
|
|
|
|
@Test
|
|
public void testIFEqualsFormulaEvaluation_NumericLiteral() {
|
|
final String formula = "IF(A1=1, 2, 3)";
|
|
final CellType cellType = CellType.NUMERIC;
|
|
final String expectedFormula = "IF(A1=1,2,3)";
|
|
final double expectedValue = 2.0;
|
|
testIFEqualsFormulaEvaluation_eval(formula, cellType, expectedFormula, expectedValue);
|
|
}
|
|
|
|
@Test
|
|
public void testIFEqualsFormulaEvaluation_Numeric() {
|
|
final String formula = "IF(A1=1, B1, C1)";
|
|
final CellType cellType = CellType.NUMERIC;
|
|
final String expectedFormula = "IF(A1=1,B1,C1)";
|
|
final double expectedValue = 2.0;
|
|
testIFEqualsFormulaEvaluation_eval(formula, cellType, expectedFormula, expectedValue);
|
|
}
|
|
|
|
@Test
|
|
public void testIFEqualsFormulaEvaluation_NumericCoerceToString() {
|
|
final String formula = "IF(A1&\"\"=\"1\", B1, C1)";
|
|
final CellType cellType = CellType.NUMERIC;
|
|
final String expectedFormula = "IF(A1&\"\"=\"1\",B1,C1)";
|
|
final double expectedValue = 2.0;
|
|
testIFEqualsFormulaEvaluation_eval(formula, cellType, expectedFormula, expectedValue);
|
|
}
|
|
|
|
@Test
|
|
public void testIFEqualsFormulaEvaluation_String() {
|
|
final String formula = "IF(A1=1, B1, C1)";
|
|
final CellType cellType = CellType.STRING;
|
|
final String expectedFormula = "IF(A1=1,B1,C1)";
|
|
final double expectedValue = 3.0;
|
|
testIFEqualsFormulaEvaluation_eval(formula, cellType, expectedFormula, expectedValue);
|
|
}
|
|
|
|
@Test
|
|
public void testIFEqualsFormulaEvaluation_StringCompareToString() {
|
|
final String formula = "IF(A1=\"1\", B1, C1)";
|
|
final CellType cellType = CellType.STRING;
|
|
final String expectedFormula = "IF(A1=\"1\",B1,C1)";
|
|
final double expectedValue = 2.0;
|
|
testIFEqualsFormulaEvaluation_eval(formula, cellType, expectedFormula, expectedValue);
|
|
}
|
|
|
|
@Test
|
|
public void testIFEqualsFormulaEvaluation_StringCoerceToNumeric() {
|
|
final String formula = "IF(A1+0=1, B1, C1)";
|
|
final CellType cellType = CellType.STRING;
|
|
final String expectedFormula = "IF(A1+0=1,B1,C1)";
|
|
final double expectedValue = 2.0;
|
|
testIFEqualsFormulaEvaluation_eval(formula, cellType, expectedFormula, expectedValue);
|
|
}
|
|
|
|
@Ignore("Bug 58591: this test currently fails")
|
|
@Test
|
|
public void testIFEqualsFormulaEvaluation_Boolean() {
|
|
final String formula = "IF(A1=1, B1, C1)";
|
|
final CellType cellType = CellType.BOOLEAN;
|
|
final String expectedFormula = "IF(A1=1,B1,C1)";
|
|
final double expectedValue = 2.0;
|
|
testIFEqualsFormulaEvaluation_eval(formula, cellType, expectedFormula, expectedValue);
|
|
}
|
|
|
|
@Ignore("Bug 58591: this test currently fails")
|
|
@Test
|
|
public void testIFEqualsFormulaEvaluation_BooleanSimple() {
|
|
final String formula = "3-(A1=1)";
|
|
final CellType cellType = CellType.BOOLEAN;
|
|
final String expectedFormula = "3-(A1=1)";
|
|
final double expectedValue = 2.0;
|
|
testIFEqualsFormulaEvaluation_eval(formula, cellType, expectedFormula, expectedValue);
|
|
}
|
|
|
|
@Test
|
|
public void testIFEqualsFormulaEvaluation_Formula() {
|
|
final String formula = "IF(A1=1, B1, C1)";
|
|
final CellType cellType = CellType.FORMULA;
|
|
final String expectedFormula = "IF(A1=1,B1,C1)";
|
|
final double expectedValue = 2.0;
|
|
testIFEqualsFormulaEvaluation_eval(formula, cellType, expectedFormula, expectedValue);
|
|
}
|
|
|
|
@Test
|
|
public void testIFEqualsFormulaEvaluation_Blank() {
|
|
final String formula = "IF(A1=1, B1, C1)";
|
|
final CellType cellType = CellType.BLANK;
|
|
final String expectedFormula = "IF(A1=1,B1,C1)";
|
|
final double expectedValue = 3.0;
|
|
testIFEqualsFormulaEvaluation_eval(formula, cellType, expectedFormula, expectedValue);
|
|
}
|
|
|
|
@Test
|
|
public void testIFEqualsFormulaEvaluation_BlankCompareToZero() {
|
|
final String formula = "IF(A1=0, B1, C1)";
|
|
final CellType cellType = CellType.BLANK;
|
|
final String expectedFormula = "IF(A1=0,B1,C1)";
|
|
final double expectedValue = 2.0;
|
|
testIFEqualsFormulaEvaluation_eval(formula, cellType, expectedFormula, expectedValue);
|
|
}
|
|
|
|
@Ignore("Bug 58591: this test currently fails")
|
|
@Test
|
|
public void testIFEqualsFormulaEvaluation_BlankInverted() {
|
|
final String formula = "IF(NOT(A1)=1, B1, C1)";
|
|
final CellType cellType = CellType.BLANK;
|
|
final String expectedFormula = "IF(NOT(A1)=1,B1,C1)";
|
|
final double expectedValue = 2.0;
|
|
testIFEqualsFormulaEvaluation_eval(formula, cellType, expectedFormula, expectedValue);
|
|
}
|
|
|
|
@Ignore("Bug 58591: this test currently fails")
|
|
@Test
|
|
public void testIFEqualsFormulaEvaluation_BlankInvertedSimple() {
|
|
final String formula = "3-(NOT(A1)=1)";
|
|
final CellType cellType = CellType.BLANK;
|
|
final String expectedFormula = "3-(NOT(A1)=1)";
|
|
final double expectedValue = 2.0;
|
|
testIFEqualsFormulaEvaluation_eval(formula, cellType, expectedFormula, expectedValue);
|
|
}
|
|
|
|
|
|
private void testIFEqualsFormulaEvaluation_evaluateFormulaCell(
|
|
String formula, CellType cellType, String expectedFormula, double expectedResult) {
|
|
Workbook wb = testIFEqualsFormulaEvaluation_setup(formula, cellType);
|
|
Cell D1 = wb.getSheet("IFEquals").getRow(0).getCell(3);
|
|
|
|
FormulaEvaluator eval = wb.getCreationHelper().createFormulaEvaluator();
|
|
CellType resultCellType = eval.evaluateFormulaCellEnum(D1);
|
|
|
|
// Call should modify the contents, but leave the formula intact
|
|
assertEquals(CellType.FORMULA, D1.getCellTypeEnum());
|
|
assertEquals(expectedFormula, D1.getCellFormula());
|
|
assertEquals(CellType.NUMERIC, resultCellType);
|
|
assertEquals(CellType.NUMERIC, D1.getCachedFormulaResultTypeEnum());
|
|
assertEquals(expectedResult, D1.getNumericCellValue(), EPSILON);
|
|
|
|
testIFEqualsFormulaEvaluation_teardown(wb);
|
|
}
|
|
|
|
private void testIFEqualsFormulaEvaluation_evaluateInCell(
|
|
String formula, CellType cellType, String expectedFormula, double expectedResult) {
|
|
Workbook wb = testIFEqualsFormulaEvaluation_setup(formula, cellType);
|
|
Cell D1 = wb.getSheet("IFEquals").getRow(0).getCell(3);
|
|
|
|
FormulaEvaluator eval = wb.getCreationHelper().createFormulaEvaluator();
|
|
Cell result = eval.evaluateInCell(D1);
|
|
|
|
// Call should modify the contents and replace the formula with the result
|
|
assertSame(D1, result); // returns the same cell that was provided as an argument so that calls can be chained.
|
|
try {
|
|
D1.getCellFormula();
|
|
fail("cell formula should be overwritten with formula result");
|
|
} catch (final IllegalStateException expected) { }
|
|
assertEquals(CellType.NUMERIC, D1.getCellTypeEnum());
|
|
assertEquals(expectedResult, D1.getNumericCellValue(), EPSILON);
|
|
|
|
testIFEqualsFormulaEvaluation_teardown(wb);
|
|
}
|
|
|
|
private void testIFEqualsFormulaEvaluation_evaluateAll(
|
|
String formula, CellType cellType, String expectedFormula, double expectedResult) {
|
|
Workbook wb = testIFEqualsFormulaEvaluation_setup(formula, cellType);
|
|
Cell D1 = wb.getSheet("IFEquals").getRow(0).getCell(3);
|
|
|
|
FormulaEvaluator eval = wb.getCreationHelper().createFormulaEvaluator();
|
|
eval.evaluateAll();
|
|
|
|
// Call should modify the contents
|
|
assertEquals(CellType.FORMULA, D1.getCellTypeEnum());
|
|
assertEquals(expectedFormula, D1.getCellFormula());
|
|
|
|
assertEquals(CellType.NUMERIC, D1.getCachedFormulaResultTypeEnum());
|
|
assertEquals(expectedResult, D1.getNumericCellValue(), EPSILON);
|
|
|
|
testIFEqualsFormulaEvaluation_teardown(wb);
|
|
}
|
|
|
|
private void testIFEqualsFormulaEvaluation_evaluateAllFormulaCells(
|
|
String formula, CellType cellType, String expectedFormula, double expectedResult) {
|
|
Workbook wb = testIFEqualsFormulaEvaluation_setup(formula, cellType);
|
|
Cell D1 = wb.getSheet("IFEquals").getRow(0).getCell(3);
|
|
|
|
HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
|
|
|
|
// Call should modify the contents
|
|
assertEquals(CellType.FORMULA, D1.getCellTypeEnum());
|
|
// whitespace gets deleted because formula is parsed and re-rendered
|
|
assertEquals(expectedFormula, D1.getCellFormula());
|
|
|
|
assertEquals(CellType.NUMERIC, D1.getCachedFormulaResultTypeEnum());
|
|
assertEquals(expectedResult, D1.getNumericCellValue(), EPSILON);
|
|
|
|
testIFEqualsFormulaEvaluation_teardown(wb);
|
|
}
|
|
}
|