From 6ac5bb3fbd3588771ce6ea99960021f3d244f37f Mon Sep 17 00:00:00 2001 From: Dominik Stadler Date: Sun, 31 Aug 2014 21:46:48 +0000 Subject: [PATCH] Bug 48195: Formulas: Fix incorrect evaluation of IF() with ROW()/COLUMN() as else-result git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1621641 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/ss/formula/WorkbookEvaluator.java | 8 +- .../usermodel/TestXSSFFormulaEvaluation.java | 249 +++++++++++++++--- 2 files changed, 213 insertions(+), 44 deletions(-) diff --git a/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java b/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java index 8a32c9c8b..7cc140877 100644 --- a/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java +++ b/src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java @@ -39,6 +39,7 @@ import org.apache.poi.ss.formula.eval.NumberEval; import org.apache.poi.ss.formula.eval.OperandResolver; import org.apache.poi.ss.formula.eval.StringEval; import org.apache.poi.ss.formula.eval.ValueEval; +import org.apache.poi.ss.formula.function.FunctionMetadataRegistry; import org.apache.poi.ss.formula.functions.Choose; import org.apache.poi.ss.formula.functions.FreeRefFunction; import org.apache.poi.ss.formula.functions.Function; @@ -486,12 +487,15 @@ public final class WorkbookEvaluator { continue; } if (evaluatedPredicate) { - // nothing to skip - true param folows + // nothing to skip - true param follows } else { int dist = attrPtg.getData(); i+= countTokensToBeSkipped(ptgs, i, dist); Ptg nextPtg = ptgs[i+1]; - if (ptgs[i] instanceof AttrPtg && nextPtg instanceof FuncVarPtg) { + if (ptgs[i] instanceof AttrPtg && nextPtg instanceof FuncVarPtg && + // in order to verify that there is no third param, we need to check + // if we really have the IF next or some other FuncVarPtg as third param, e.g. ROW()/COLUMN()! + ((FuncVarPtg)nextPtg).getFunctionIndex() == FunctionMetadataRegistry.FUNCTION_INDEX_IF) { // this is an if statement without a false param (as opposed to MissingArgPtg as the false param) i++; stack.push(BoolEval.FALSE); diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java index e5cf432fb..a813bce81 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java @@ -17,6 +17,7 @@ package org.apache.poi.xssf.usermodel; +import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -288,48 +289,212 @@ public final class TestXSSFFormulaEvaluation extends BaseTestFormulaEvaluator { } } - public void testMultisheetFormulaEval() { + public void testMultisheetFormulaEval() throws IOException { XSSFWorkbook wb = new XSSFWorkbook(); - XSSFSheet sheet1 = wb.createSheet("Sheet1"); - XSSFSheet sheet2 = wb.createSheet("Sheet2"); - XSSFSheet sheet3 = wb.createSheet("Sheet3"); - - // sheet1 A1 - XSSFCell cell = sheet1.createRow(0).createCell(0); - cell.setCellType(Cell.CELL_TYPE_NUMERIC); - cell.setCellValue(1.0); - - // sheet2 A1 - cell = sheet2.createRow(0).createCell(0); - cell.setCellType(Cell.CELL_TYPE_NUMERIC); - cell.setCellValue(1.0); - - // sheet2 B1 - cell = sheet2.getRow(0).createCell(1); - cell.setCellType(Cell.CELL_TYPE_NUMERIC); - cell.setCellValue(1.0); - - // sheet3 A1 - cell = sheet3.createRow(0).createCell(0); - cell.setCellType(Cell.CELL_TYPE_NUMERIC); - cell.setCellValue(1.0); - - // sheet1 A2 formulae - cell = sheet1.createRow(1).createCell(0); - cell.setCellType(Cell.CELL_TYPE_FORMULA); - cell.setCellFormula("SUM(Sheet1:Sheet3!A1)"); - - // sheet1 A3 formulae - cell = sheet1.createRow(2).createCell(0); - cell.setCellType(Cell.CELL_TYPE_FORMULA); - cell.setCellFormula("SUM(Sheet1:Sheet3!A1:B1)"); - - wb.getCreationHelper().createFormulaEvaluator().evaluateAll(); - - cell = sheet1.getRow(1).getCell(0); - assertEquals(3.0, cell.getNumericCellValue()); - - cell = sheet1.getRow(2).getCell(0); - assertEquals(4.0, cell.getNumericCellValue()); + try { + XSSFSheet sheet1 = wb.createSheet("Sheet1"); + XSSFSheet sheet2 = wb.createSheet("Sheet2"); + XSSFSheet sheet3 = wb.createSheet("Sheet3"); + + // sheet1 A1 + XSSFCell cell = sheet1.createRow(0).createCell(0); + cell.setCellType(Cell.CELL_TYPE_NUMERIC); + cell.setCellValue(1.0); + + // sheet2 A1 + cell = sheet2.createRow(0).createCell(0); + cell.setCellType(Cell.CELL_TYPE_NUMERIC); + cell.setCellValue(1.0); + + // sheet2 B1 + cell = sheet2.getRow(0).createCell(1); + cell.setCellType(Cell.CELL_TYPE_NUMERIC); + cell.setCellValue(1.0); + + // sheet3 A1 + cell = sheet3.createRow(0).createCell(0); + cell.setCellType(Cell.CELL_TYPE_NUMERIC); + cell.setCellValue(1.0); + + // sheet1 A2 formulae + cell = sheet1.createRow(1).createCell(0); + cell.setCellType(Cell.CELL_TYPE_FORMULA); + cell.setCellFormula("SUM(Sheet1:Sheet3!A1)"); + + // sheet1 A3 formulae + cell = sheet1.createRow(2).createCell(0); + cell.setCellType(Cell.CELL_TYPE_FORMULA); + cell.setCellFormula("SUM(Sheet1:Sheet3!A1:B1)"); + + wb.getCreationHelper().createFormulaEvaluator().evaluateAll(); + + cell = sheet1.getRow(1).getCell(0); + assertEquals(3.0, cell.getNumericCellValue()); + + cell = sheet1.getRow(2).getCell(0); + assertEquals(4.0, cell.getNumericCellValue()); + } finally { + wb.close(); + } } + + public void testBug55843() throws IOException { + XSSFWorkbook wb = new XSSFWorkbook(); + try { + XSSFSheet sheet = wb.createSheet("test"); + XSSFRow row = sheet.createRow(0); + XSSFRow row2 = sheet.createRow(1); + XSSFCell cellA2 = row2.createCell(0, Cell.CELL_TYPE_FORMULA); + XSSFCell cellB1 = row.createCell(1, Cell.CELL_TYPE_NUMERIC); + cellB1.setCellValue(10); + XSSFFormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator(); + cellA2.setCellFormula("IF(B1=0,\"\",((ROW()-ROW(A$1))*12))"); + CellValue evaluate = formulaEvaluator.evaluate(cellA2); + System.out.println(evaluate); + assertEquals("12.0", evaluate.formatAsString()); + + cellA2.setCellFormula("IF(NOT(B1=0),((ROW()-ROW(A$1))*12),\"\")"); + CellValue evaluateN = formulaEvaluator.evaluate(cellA2); + System.out.println(evaluateN); + + assertEquals(evaluate.toString(), evaluateN.toString()); + assertEquals("12.0", evaluateN.formatAsString()); + } finally { + wb.close(); + } + } + + public void testBug55843a() throws IOException { + XSSFWorkbook wb = new XSSFWorkbook(); + try { + XSSFSheet sheet = wb.createSheet("test"); + XSSFRow row = sheet.createRow(0); + XSSFRow row2 = sheet.createRow(1); + XSSFCell cellA2 = row2.createCell(0, Cell.CELL_TYPE_FORMULA); + XSSFCell cellB1 = row.createCell(1, Cell.CELL_TYPE_NUMERIC); + cellB1.setCellValue(10); + XSSFFormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator(); + cellA2.setCellFormula("IF(B1=0,\"\",((ROW(A$1))))"); + CellValue evaluate = formulaEvaluator.evaluate(cellA2); + System.out.println(evaluate); + assertEquals("1.0", evaluate.formatAsString()); + + cellA2.setCellFormula("IF(NOT(B1=0),((ROW(A$1))),\"\")"); + CellValue evaluateN = formulaEvaluator.evaluate(cellA2); + System.out.println(evaluateN); + + assertEquals(evaluate.toString(), evaluateN.toString()); + assertEquals("1.0", evaluateN.formatAsString()); + } finally { + wb.close(); + } + } + + public void testBug55843b() throws IOException { + XSSFWorkbook wb = new XSSFWorkbook(); + try { + XSSFSheet sheet = wb.createSheet("test"); + XSSFRow row = sheet.createRow(0); + XSSFRow row2 = sheet.createRow(1); + XSSFCell cellA2 = row2.createCell(0, Cell.CELL_TYPE_FORMULA); + XSSFCell cellB1 = row.createCell(1, Cell.CELL_TYPE_NUMERIC); + cellB1.setCellValue(10); + XSSFFormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator(); + + cellA2.setCellFormula("IF(B1=0,\"\",((ROW())))"); + CellValue evaluate = formulaEvaluator.evaluate(cellA2); + System.out.println(evaluate); + assertEquals("2.0", evaluate.formatAsString()); + + cellA2.setCellFormula("IF(NOT(B1=0),((ROW())),\"\")"); + CellValue evaluateN = formulaEvaluator.evaluate(cellA2); + System.out.println(evaluateN); + + assertEquals(evaluate.toString(), evaluateN.toString()); + assertEquals("2.0", evaluateN.formatAsString()); + } finally { + wb.close(); + } + } + + public void testBug55843c() throws IOException { + XSSFWorkbook wb = new XSSFWorkbook(); + try { + XSSFSheet sheet = wb.createSheet("test"); + XSSFRow row = sheet.createRow(0); + XSSFRow row2 = sheet.createRow(1); + XSSFCell cellA2 = row2.createCell(0, Cell.CELL_TYPE_FORMULA); + XSSFCell cellB1 = row.createCell(1, Cell.CELL_TYPE_NUMERIC); + cellB1.setCellValue(10); + XSSFFormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator(); + + cellA2.setCellFormula("IF(NOT(B1=0),((ROW())))"); + CellValue evaluateN = formulaEvaluator.evaluate(cellA2); + System.out.println(evaluateN); + assertEquals("2.0", evaluateN.formatAsString()); + } finally { + wb.close(); + } + } + + public void testBug55843d() throws IOException { + XSSFWorkbook wb = new XSSFWorkbook(); + try { + XSSFSheet sheet = wb.createSheet("test"); + XSSFRow row = sheet.createRow(0); + XSSFRow row2 = sheet.createRow(1); + XSSFCell cellA2 = row2.createCell(0, Cell.CELL_TYPE_FORMULA); + XSSFCell cellB1 = row.createCell(1, Cell.CELL_TYPE_NUMERIC); + cellB1.setCellValue(10); + XSSFFormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator(); + + cellA2.setCellFormula("IF(NOT(B1=0),((ROW())),\"\")"); + CellValue evaluateN = formulaEvaluator.evaluate(cellA2); + System.out.println(evaluateN); + assertEquals("2.0", evaluateN.formatAsString()); + } finally { + wb.close(); + } + } + + public void testBug55843e() throws IOException { + XSSFWorkbook wb = new XSSFWorkbook(); + try { + XSSFSheet sheet = wb.createSheet("test"); + XSSFRow row = sheet.createRow(0); + XSSFRow row2 = sheet.createRow(1); + XSSFCell cellA2 = row2.createCell(0, Cell.CELL_TYPE_FORMULA); + XSSFCell cellB1 = row.createCell(1, Cell.CELL_TYPE_NUMERIC); + cellB1.setCellValue(10); + XSSFFormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator(); + + cellA2.setCellFormula("IF(B1=0,\"\",((ROW())))"); + CellValue evaluate = formulaEvaluator.evaluate(cellA2); + System.out.println(evaluate); + assertEquals("2.0", evaluate.formatAsString()); + } finally { + wb.close(); + } + } + + + public void testBug55843f() throws IOException { + XSSFWorkbook wb = new XSSFWorkbook(); + try { + XSSFSheet sheet = wb.createSheet("test"); + XSSFRow row = sheet.createRow(0); + XSSFRow row2 = sheet.createRow(1); + XSSFCell cellA2 = row2.createCell(0, Cell.CELL_TYPE_FORMULA); + XSSFCell cellB1 = row.createCell(1, Cell.CELL_TYPE_NUMERIC); + cellB1.setCellValue(10); + XSSFFormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator(); + + cellA2.setCellFormula("IF(B1=0,\"\",IF(B1=10,3,4))"); + CellValue evaluate = formulaEvaluator.evaluate(cellA2); + System.out.println(evaluate); + assertEquals("3.0", evaluate.formatAsString()); + } finally { + wb.close(); + } + } }