| /* ==================================================================== |
| 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.xssf.usermodel; |
| |
| import static org.junit.Assert.*; |
| |
| import java.io.IOException; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import org.apache.poi.hssf.HSSFTestDataSamples; |
| import org.apache.poi.ss.usermodel.BaseTestFormulaEvaluator; |
| 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.FormulaError; |
| import org.apache.poi.ss.usermodel.FormulaEvaluator; |
| import org.apache.poi.ss.usermodel.Row; |
| import org.apache.poi.ss.usermodel.Sheet; |
| import org.apache.poi.ss.usermodel.Workbook; |
| import org.apache.poi.ss.util.CellReference; |
| import org.apache.poi.xssf.XSSFITestDataProvider; |
| import org.apache.poi.xssf.XSSFTestDataSamples; |
| import org.junit.Ignore; |
| import org.junit.Test; |
| |
| public final class TestXSSFFormulaEvaluation extends BaseTestFormulaEvaluator { |
| |
| public TestXSSFFormulaEvaluation() { |
| super(XSSFITestDataProvider.instance); |
| } |
| |
| @Test |
| public void testSharedFormulas() throws IOException { |
| baseTestSharedFormulas("shared_formulas.xlsx"); |
| } |
| |
| @Test |
| public void testSharedFormulas_evaluateInCell() throws IOException { |
| XSSFWorkbook wb = (XSSFWorkbook)_testDataProvider.openSampleWorkbook("49872.xlsx"); |
| FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator(); |
| XSSFSheet sheet = wb.getSheetAt(0); |
| |
| double result = 3.0; |
| |
| // B3 is a master shared formula, C3 and D3 don't have the formula written in their f element. |
| // Instead, the attribute si for a particular cell is used to figure what the formula expression |
| // should be based on the cell's relative location to the master formula, e.g. |
| // B3: <f t="shared" ref="B3:D3" si="0">B1+B2</f> |
| // C3 and D3: <f t="shared" si="0"/> |
| |
| // get B3 and evaluate it in the cell |
| XSSFCell b3 = sheet.getRow(2).getCell(1); |
| assertEquals(result, evaluator.evaluateInCell(b3).getNumericCellValue(), 0); |
| |
| //at this point the master formula is gone, but we are still able to evaluate dependent cells |
| XSSFCell c3 = sheet.getRow(2).getCell(2); |
| assertEquals(result, evaluator.evaluateInCell(c3).getNumericCellValue(), 0); |
| |
| XSSFCell d3 = sheet.getRow(2).getCell(3); |
| assertEquals(result, evaluator.evaluateInCell(d3).getNumericCellValue(), 0); |
| |
| wb.close(); |
| } |
| |
| /** |
| * Evaluation of cell references with column indexes greater than 255. See bugzilla 50096 |
| */ |
| @Test |
| public void testEvaluateColumnGreaterThan255() throws IOException { |
| XSSFWorkbook wb = (XSSFWorkbook) _testDataProvider.openSampleWorkbook("50096.xlsx"); |
| XSSFFormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator(); |
| |
| /** |
| * The first row simply contains the numbers 1 - 300. |
| * The second row simply refers to the cell value above in the first row by a simple formula. |
| */ |
| for (int i = 245; i < 265; i++) { |
| XSSFCell cell_noformula = wb.getSheetAt(0).getRow(0).getCell(i); |
| XSSFCell cell_formula = wb.getSheetAt(0).getRow(1).getCell(i); |
| |
| CellReference ref_noformula = new CellReference(cell_noformula.getRowIndex(), cell_noformula.getColumnIndex()); |
| CellReference ref_formula = new CellReference(cell_noformula.getRowIndex(), cell_noformula.getColumnIndex()); |
| String fmla = cell_formula.getCellFormula(); |
| // assure that the formula refers to the cell above. |
| // the check below is 'deep' and involves conversion of the shared formula: |
| // in the sample file a shared formula in GN1 is spanned in the range GN2:IY2, |
| assertEquals(ref_noformula.formatAsString(), fmla); |
| |
| CellValue cv_noformula = evaluator.evaluate(cell_noformula); |
| CellValue cv_formula = evaluator.evaluate(cell_formula); |
| assertEquals("Wrong evaluation result in " + ref_formula.formatAsString(), |
| cv_noformula.getNumberValue(), cv_formula.getNumberValue(), 0); |
| } |
| |
| wb.close(); |
| } |
| |
| /** |
| * Related to bugs #56737 and #56752 - XSSF workbooks which have |
| * formulas that refer to cells and named ranges in multiple other |
| * workbooks, both HSSF and XSSF ones |
| */ |
| @Test |
| public void testReferencesToOtherWorkbooks() throws Exception { |
| XSSFWorkbook wb = (XSSFWorkbook) _testDataProvider.openSampleWorkbook("ref2-56737.xlsx"); |
| XSSFFormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator(); |
| XSSFSheet s = wb.getSheetAt(0); |
| |
| // References to a .xlsx file |
| Row rXSLX = s.getRow(2); |
| Cell cXSLX_cell = rXSLX.getCell(4); |
| Cell cXSLX_sNR = rXSLX.getCell(6); |
| Cell cXSLX_gNR = rXSLX.getCell(8); |
| assertEquals("[1]Uses!$A$1", cXSLX_cell.getCellFormula()); |
| assertEquals("[1]Defines!NR_To_A1", cXSLX_sNR.getCellFormula()); |
| assertEquals("[1]!NR_Global_B2", cXSLX_gNR.getCellFormula()); |
| |
| assertEquals("Hello!", cXSLX_cell.getStringCellValue()); |
| assertEquals("Test A1", cXSLX_sNR.getStringCellValue()); |
| assertEquals(142.0, cXSLX_gNR.getNumericCellValue(), 0); |
| |
| // References to a .xls file |
| Row rXSL = s.getRow(4); |
| Cell cXSL_cell = rXSL.getCell(4); |
| Cell cXSL_sNR = rXSL.getCell(6); |
| Cell cXSL_gNR = rXSL.getCell(8); |
| assertEquals("[2]Uses!$C$1", cXSL_cell.getCellFormula()); |
| assertEquals("[2]Defines!NR_To_A1", cXSL_sNR.getCellFormula()); |
| assertEquals("[2]!NR_Global_B2", cXSL_gNR.getCellFormula()); |
| |
| assertEquals("Hello!", cXSL_cell.getStringCellValue()); |
| assertEquals("Test A1", cXSL_sNR.getStringCellValue()); |
| assertEquals(142.0, cXSL_gNR.getNumericCellValue(), 0); |
| |
| // Try to evaluate without references, won't work |
| // (At least, not unit we fix bug #56752 that is) |
| try { |
| evaluator.evaluate(cXSL_cell); |
| fail("Without a fix for #56752, shouldn't be able to evaluate a " + |
| "reference to a non-provided linked workbook"); |
| } catch(Exception e) { |
| // expected here |
| } |
| |
| // Setup the environment |
| Map<String,FormulaEvaluator> evaluators = new HashMap<String, FormulaEvaluator>(); |
| evaluators.put("ref2-56737.xlsx", evaluator); |
| evaluators.put("56737.xlsx", |
| _testDataProvider.openSampleWorkbook("56737.xlsx").getCreationHelper().createFormulaEvaluator()); |
| evaluators.put("56737.xls", |
| HSSFTestDataSamples.openSampleWorkbook("56737.xls").getCreationHelper().createFormulaEvaluator()); |
| evaluator.setupReferencedWorkbooks(evaluators); |
| |
| // Try evaluating all of them, ensure we don't blow up |
| for(Row r : s) { |
| for (Cell c : r) { |
| evaluator.evaluate(c); |
| } |
| } |
| // And evaluate the other way too |
| evaluator.evaluateAll(); |
| |
| // Static evaluator won't work, as no references passed in |
| try { |
| XSSFFormulaEvaluator.evaluateAllFormulaCells(wb); |
| fail("Static method lacks references, shouldn't work"); |
| } catch(Exception e) { |
| // expected here |
| } |
| |
| |
| // Evaluate specific cells and check results |
| assertEquals("\"Hello!\"", evaluator.evaluate(cXSLX_cell).formatAsString()); |
| assertEquals("\"Test A1\"", evaluator.evaluate(cXSLX_sNR).formatAsString()); |
| assertEquals("142.0", evaluator.evaluate(cXSLX_gNR).formatAsString()); |
| |
| assertEquals("\"Hello!\"", evaluator.evaluate(cXSL_cell).formatAsString()); |
| assertEquals("\"Test A1\"", evaluator.evaluate(cXSL_sNR).formatAsString()); |
| assertEquals("142.0", evaluator.evaluate(cXSL_gNR).formatAsString()); |
| |
| |
| // Add another formula referencing these workbooks |
| Cell cXSL_cell2 = rXSL.createCell(40); |
| cXSL_cell2.setCellFormula("[56737.xls]Uses!$C$1"); |
| // TODO Shouldn't it become [2] like the others? |
| assertEquals("[56737.xls]Uses!$C$1", cXSL_cell2.getCellFormula()); |
| assertEquals("\"Hello!\"", evaluator.evaluate(cXSL_cell2).formatAsString()); |
| |
| |
| // Now add a formula that refers to yet another (different) workbook |
| // Won't work without the workbook being linked |
| Cell cXSLX_nw_cell = rXSLX.createCell(42); |
| try { |
| cXSLX_nw_cell.setCellFormula("[alt.xlsx]Sheet1!$A$1"); |
| fail("New workbook not linked, shouldn't be able to add"); |
| } catch (Exception e) { |
| // expected here |
| } |
| |
| // Link and re-try |
| Workbook alt = new XSSFWorkbook(); |
| try { |
| alt.createSheet().createRow(0).createCell(0).setCellValue("In another workbook"); |
| // TODO Implement the rest of this, see bug #57184 |
| /* |
| wb.linkExternalWorkbook("alt.xlsx", alt); |
| |
| cXSLX_nw_cell.setCellFormula("[alt.xlsx]Sheet1!$A$1"); |
| // Check it - TODO Is this correct? Or should it become [3]Sheet1!$A$1 ? |
| assertEquals("[alt.xlsx]Sheet1!$A$1", cXSLX_nw_cell.getCellFormula()); |
| |
| // Evaluate it, without a link to that workbook |
| try { |
| evaluator.evaluate(cXSLX_nw_cell); |
| fail("No cached value and no link to workbook, shouldn't evaluate"); |
| } catch(Exception e) {} |
| |
| // Add a link, check it does |
| evaluators.put("alt.xlsx", alt.getCreationHelper().createFormulaEvaluator()); |
| evaluator.setupReferencedWorkbooks(evaluators); |
| |
| evaluator.evaluate(cXSLX_nw_cell); |
| assertEquals("In another workbook", cXSLX_nw_cell.getStringCellValue()); |
| */ |
| } finally { |
| alt.close(); |
| } |
| |
| wb.close(); |
| } |
| |
| /** |
| * If a formula references cells or named ranges in another workbook, |
| * but that isn't available at evaluation time, the cached values |
| * should be used instead |
| * TODO Add the support then add a unit test |
| * See bug #56752 |
| */ |
| @Test |
| @Ignore |
| public void testCachedReferencesToOtherWorkbooks() throws Exception { |
| // TODO |
| } |
| |
| /** |
| * A handful of functions (such as SUM, COUNTA, MIN) support |
| * multi-sheet references (eg Sheet1:Sheet3!A1 = Cell A1 from |
| * Sheets 1 through Sheet 3). |
| * This test, based on common test files for HSSF and XSSF, checks |
| * that we can correctly evaluate these |
| */ |
| @Test |
| public void testMultiSheetReferencesHSSFandXSSF() throws Exception { |
| Workbook wb1 = HSSFTestDataSamples.openSampleWorkbook("55906-MultiSheetRefs.xls"); |
| Workbook wb2 = XSSFTestDataSamples.openSampleWorkbook("55906-MultiSheetRefs.xlsx"); |
| |
| for (Workbook wb : new Workbook[] {wb1,wb2}) { |
| FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator(); |
| Sheet s1 = wb.getSheetAt(0); |
| |
| |
| // Simple SUM over numbers |
| Cell sumF = s1.getRow(2).getCell(0); |
| assertNotNull(sumF); |
| assertEquals("SUM(Sheet1:Sheet3!A1)", sumF.getCellFormula()); |
| assertEquals("Failed for " + wb.getClass(), "66.0", evaluator.evaluate(sumF).formatAsString()); |
| |
| |
| // Various Stats formulas on numbers |
| Cell avgF = s1.getRow(2).getCell(1); |
| assertNotNull(avgF); |
| assertEquals("AVERAGE(Sheet1:Sheet3!A1)", avgF.getCellFormula()); |
| assertEquals("22.0", evaluator.evaluate(avgF).formatAsString()); |
| |
| Cell minF = s1.getRow(3).getCell(1); |
| assertNotNull(minF); |
| assertEquals("MIN(Sheet1:Sheet3!A$1)", minF.getCellFormula()); |
| assertEquals("11.0", evaluator.evaluate(minF).formatAsString()); |
| |
| Cell maxF = s1.getRow(4).getCell(1); |
| assertNotNull(maxF); |
| assertEquals("MAX(Sheet1:Sheet3!A$1)", maxF.getCellFormula()); |
| assertEquals("33.0", evaluator.evaluate(maxF).formatAsString()); |
| |
| Cell countF = s1.getRow(5).getCell(1); |
| assertNotNull(countF); |
| assertEquals("COUNT(Sheet1:Sheet3!A$1)", countF.getCellFormula()); |
| assertEquals("3.0", evaluator.evaluate(countF).formatAsString()); |
| |
| |
| // Various CountAs on Strings |
| Cell countA_1F = s1.getRow(2).getCell(2); |
| assertNotNull(countA_1F); |
| assertEquals("COUNTA(Sheet1:Sheet3!C1)", countA_1F.getCellFormula()); |
| assertEquals("3.0", evaluator.evaluate(countA_1F).formatAsString()); |
| |
| Cell countA_2F = s1.getRow(2).getCell(3); |
| assertNotNull(countA_2F); |
| assertEquals("COUNTA(Sheet1:Sheet3!D1)", countA_2F.getCellFormula()); |
| assertEquals("0.0", evaluator.evaluate(countA_2F).formatAsString()); |
| |
| Cell countA_3F = s1.getRow(2).getCell(4); |
| assertNotNull(countA_3F); |
| assertEquals("COUNTA(Sheet1:Sheet3!E1)", countA_3F.getCellFormula()); |
| assertEquals("3.0", evaluator.evaluate(countA_3F).formatAsString()); |
| } |
| |
| wb2.close(); |
| wb1.close(); |
| } |
| |
| /** |
| * A handful of functions (such as SUM, COUNTA, MIN) support |
| * multi-sheet areas (eg Sheet1:Sheet3!A1:B2 = Cell A1 to Cell B2, |
| * from Sheets 1 through Sheet 3). |
| * This test, based on common test files for HSSF and XSSF, checks |
| * that we can correctly evaluate these |
| */ |
| @Test |
| public void testMultiSheetAreasHSSFandXSSF() throws IOException { |
| Workbook wb1 = HSSFTestDataSamples.openSampleWorkbook("55906-MultiSheetRefs.xls"); |
| Workbook wb2 = XSSFTestDataSamples.openSampleWorkbook("55906-MultiSheetRefs.xlsx"); |
| |
| for (Workbook wb : new Workbook[]{wb1,wb2}) { |
| FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator(); |
| Sheet s1 = wb.getSheetAt(0); |
| |
| |
| // SUM over a range |
| Cell sumFA = s1.getRow(2).getCell(7); |
| assertNotNull(sumFA); |
| assertEquals("SUM(Sheet1:Sheet3!A1:B2)", sumFA.getCellFormula()); |
| assertEquals("Failed for " + wb.getClass(), "110.0", evaluator.evaluate(sumFA).formatAsString()); |
| |
| |
| // Various Stats formulas on ranges of numbers |
| Cell avgFA = s1.getRow(2).getCell(8); |
| assertNotNull(avgFA); |
| assertEquals("AVERAGE(Sheet1:Sheet3!A1:B2)", avgFA.getCellFormula()); |
| assertEquals("27.5", evaluator.evaluate(avgFA).formatAsString()); |
| |
| Cell minFA = s1.getRow(3).getCell(8); |
| assertNotNull(minFA); |
| assertEquals("MIN(Sheet1:Sheet3!A$1:B$2)", minFA.getCellFormula()); |
| assertEquals("11.0", evaluator.evaluate(minFA).formatAsString()); |
| |
| Cell maxFA = s1.getRow(4).getCell(8); |
| assertNotNull(maxFA); |
| assertEquals("MAX(Sheet1:Sheet3!A$1:B$2)", maxFA.getCellFormula()); |
| assertEquals("44.0", evaluator.evaluate(maxFA).formatAsString()); |
| |
| Cell countFA = s1.getRow(5).getCell(8); |
| assertNotNull(countFA); |
| assertEquals("COUNT(Sheet1:Sheet3!$A$1:$B$2)", countFA.getCellFormula()); |
| assertEquals("4.0", evaluator.evaluate(countFA).formatAsString()); |
| } |
| |
| wb2.close(); |
| wb1.close(); |
| } |
| |
| @Test |
| public void testMultisheetFormulaEval() throws IOException { |
| XSSFWorkbook wb = new XSSFWorkbook(); |
| 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(CellType.NUMERIC); |
| cell.setCellValue(1.0); |
| |
| // sheet2 A1 |
| cell = sheet2.createRow(0).createCell(0); |
| cell.setCellType(CellType.NUMERIC); |
| cell.setCellValue(1.0); |
| |
| // sheet2 B1 |
| cell = sheet2.getRow(0).createCell(1); |
| cell.setCellType(CellType.NUMERIC); |
| cell.setCellValue(1.0); |
| |
| // sheet3 A1 |
| cell = sheet3.createRow(0).createCell(0); |
| cell.setCellType(CellType.NUMERIC); |
| cell.setCellValue(1.0); |
| |
| // sheet1 A2 formulae |
| cell = sheet1.createRow(1).createCell(0); |
| cell.setCellType(CellType.FORMULA); |
| cell.setCellFormula("SUM(Sheet1:Sheet3!A1)"); |
| |
| // sheet1 A3 formulae |
| cell = sheet1.createRow(2).createCell(0); |
| cell.setCellType(CellType.FORMULA); |
| cell.setCellFormula("SUM(Sheet1:Sheet3!A1:B1)"); |
| |
| wb.getCreationHelper().createFormulaEvaluator().evaluateAll(); |
| |
| cell = sheet1.getRow(1).getCell(0); |
| assertEquals(3.0, cell.getNumericCellValue(), 0); |
| |
| cell = sheet1.getRow(2).getCell(0); |
| assertEquals(4.0, cell.getNumericCellValue(), 0); |
| } finally { |
| wb.close(); |
| } |
| } |
| |
| @Test |
| 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, CellType.FORMULA); |
| XSSFCell cellB1 = row.createCell(1, CellType.NUMERIC); |
| cellB1.setCellValue(10); |
| XSSFFormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator(); |
| cellA2.setCellFormula("IF(B1=0,\"\",((ROW()-ROW(A$1))*12))"); |
| CellValue evaluate = formulaEvaluator.evaluate(cellA2); |
| assertEquals("12.0", evaluate.formatAsString()); |
| |
| cellA2.setCellFormula("IF(NOT(B1=0),((ROW()-ROW(A$1))*12),\"\")"); |
| CellValue evaluateN = formulaEvaluator.evaluate(cellA2); |
| |
| assertEquals(evaluate.toString(), evaluateN.toString()); |
| assertEquals("12.0", evaluateN.formatAsString()); |
| } finally { |
| wb.close(); |
| } |
| } |
| |
| @Test |
| 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, CellType.FORMULA); |
| XSSFCell cellB1 = row.createCell(1, CellType.NUMERIC); |
| cellB1.setCellValue(10); |
| XSSFFormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator(); |
| cellA2.setCellFormula("IF(B1=0,\"\",((ROW(A$1))))"); |
| CellValue evaluate = formulaEvaluator.evaluate(cellA2); |
| assertEquals("1.0", evaluate.formatAsString()); |
| |
| cellA2.setCellFormula("IF(NOT(B1=0),((ROW(A$1))),\"\")"); |
| CellValue evaluateN = formulaEvaluator.evaluate(cellA2); |
| |
| assertEquals(evaluate.toString(), evaluateN.toString()); |
| assertEquals("1.0", evaluateN.formatAsString()); |
| } finally { |
| wb.close(); |
| } |
| } |
| |
| @Test |
| 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, CellType.FORMULA); |
| XSSFCell cellB1 = row.createCell(1, CellType.NUMERIC); |
| cellB1.setCellValue(10); |
| XSSFFormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator(); |
| |
| cellA2.setCellFormula("IF(B1=0,\"\",((ROW())))"); |
| CellValue evaluate = formulaEvaluator.evaluate(cellA2); |
| assertEquals("2.0", evaluate.formatAsString()); |
| |
| cellA2.setCellFormula("IF(NOT(B1=0),((ROW())),\"\")"); |
| CellValue evaluateN = formulaEvaluator.evaluate(cellA2); |
| |
| assertEquals(evaluate.toString(), evaluateN.toString()); |
| assertEquals("2.0", evaluateN.formatAsString()); |
| } finally { |
| wb.close(); |
| } |
| } |
| |
| @Test |
| 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, CellType.FORMULA); |
| XSSFCell cellB1 = row.createCell(1, CellType.NUMERIC); |
| cellB1.setCellValue(10); |
| XSSFFormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator(); |
| |
| cellA2.setCellFormula("IF(NOT(B1=0),((ROW())))"); |
| CellValue evaluateN = formulaEvaluator.evaluate(cellA2); |
| assertEquals("2.0", evaluateN.formatAsString()); |
| } finally { |
| wb.close(); |
| } |
| } |
| |
| @Test |
| 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, CellType.FORMULA); |
| XSSFCell cellB1 = row.createCell(1, CellType.NUMERIC); |
| cellB1.setCellValue(10); |
| XSSFFormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator(); |
| |
| cellA2.setCellFormula("IF(NOT(B1=0),((ROW())),\"\")"); |
| CellValue evaluateN = formulaEvaluator.evaluate(cellA2); |
| assertEquals("2.0", evaluateN.formatAsString()); |
| } finally { |
| wb.close(); |
| } |
| } |
| |
| @Test |
| 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, CellType.FORMULA); |
| XSSFCell cellB1 = row.createCell(1, CellType.NUMERIC); |
| cellB1.setCellValue(10); |
| XSSFFormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator(); |
| |
| cellA2.setCellFormula("IF(B1=0,\"\",((ROW())))"); |
| CellValue evaluate = formulaEvaluator.evaluate(cellA2); |
| assertEquals("2.0", evaluate.formatAsString()); |
| } finally { |
| wb.close(); |
| } |
| } |
| |
| @Test |
| 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, CellType.FORMULA); |
| XSSFCell cellB1 = row.createCell(1, CellType.NUMERIC); |
| cellB1.setCellValue(10); |
| XSSFFormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator(); |
| |
| cellA2.setCellFormula("IF(B1=0,\"\",IF(B1=10,3,4))"); |
| CellValue evaluate = formulaEvaluator.evaluate(cellA2); |
| assertEquals("3.0", evaluate.formatAsString()); |
| } finally { |
| wb.close(); |
| } |
| } |
| |
| @Test |
| public void testBug56655() throws IOException { |
| Workbook wb = new XSSFWorkbook(); |
| Sheet sheet = wb.createSheet(); |
| |
| setCellFormula(sheet, 0, 0, "#VALUE!"); |
| setCellFormula(sheet, 0, 1, "SUMIFS(A:A,A:A,#VALUE!)"); |
| |
| wb.getCreationHelper().createFormulaEvaluator().evaluateAll(); |
| |
| assertEquals(CellType.ERROR, getCell(sheet, 0,0).getCachedFormulaResultTypeEnum()); |
| assertEquals(FormulaError.VALUE.getCode(), getCell(sheet, 0,0).getErrorCellValue()); |
| assertEquals(CellType.ERROR, getCell(sheet, 0,1).getCachedFormulaResultTypeEnum()); |
| assertEquals(FormulaError.VALUE.getCode(), getCell(sheet, 0,1).getErrorCellValue()); |
| |
| wb.close(); |
| } |
| |
| @Test |
| public void testBug56655a() throws IOException { |
| Workbook wb = new XSSFWorkbook(); |
| Sheet sheet = wb.createSheet(); |
| |
| setCellFormula(sheet, 0, 0, "B1*C1"); |
| sheet.getRow(0).createCell(1).setCellValue("A"); |
| setCellFormula(sheet, 1, 0, "B1*C1"); |
| sheet.getRow(1).createCell(1).setCellValue("A"); |
| setCellFormula(sheet, 0, 3, "SUMIFS(A:A,A:A,A2)"); |
| |
| wb.getCreationHelper().createFormulaEvaluator().evaluateAll(); |
| |
| assertEquals(CellType.ERROR, getCell(sheet, 0, 0).getCachedFormulaResultTypeEnum()); |
| assertEquals(FormulaError.VALUE.getCode(), getCell(sheet, 0, 0).getErrorCellValue()); |
| assertEquals(CellType.ERROR, getCell(sheet, 1, 0).getCachedFormulaResultTypeEnum()); |
| assertEquals(FormulaError.VALUE.getCode(), getCell(sheet, 1, 0).getErrorCellValue()); |
| assertEquals(CellType.ERROR, getCell(sheet, 0, 3).getCachedFormulaResultTypeEnum()); |
| assertEquals(FormulaError.VALUE.getCode(), getCell(sheet, 0, 3).getErrorCellValue()); |
| |
| wb.close(); |
| } |
| |
| // bug 57721 |
| @Test |
| public void structuredReferences() throws IOException { |
| verifyAllFormulasInWorkbookCanBeEvaluated("evaluate_formula_with_structured_table_references.xlsx"); |
| } |
| |
| // bug 57840 |
| @Ignore("Takes over a minute to evaluate all formulas in this large workbook. Run this test when profiling for formula evaluation speed.") |
| @Test |
| public void testLotsOfFormulasWithStructuredReferencesToCalculatedTableColumns() throws IOException { |
| verifyAllFormulasInWorkbookCanBeEvaluated("StructuredRefs-lots-with-lookups.xlsx"); |
| } |
| |
| // FIXME: use junit4 parameterization |
| private static void verifyAllFormulasInWorkbookCanBeEvaluated(String sampleWorkbook) throws IOException { |
| XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook(sampleWorkbook); |
| XSSFFormulaEvaluator.evaluateAllFormulaCells(wb); |
| wb.close(); |
| } |
| |
| /** |
| * @param row 0-based |
| * @param column 0-based |
| */ |
| private void setCellFormula(Sheet sheet, int row, int column, String formula) { |
| Row r = sheet.getRow(row); |
| if (r == null) { |
| r = sheet.createRow(row); |
| } |
| Cell cell = r.getCell(column); |
| if (cell == null) { |
| cell = r.createCell(column); |
| } |
| cell.setCellType(CellType.FORMULA); |
| cell.setCellFormula(formula); |
| } |
| |
| /** |
| * @param rowNo 0-based |
| * @param column 0-based |
| */ |
| private Cell getCell(Sheet sheet, int rowNo, int column) { |
| return sheet.getRow(rowNo).getCell(column); |
| } |
| |
| @Test |
| public void test59736() { |
| Workbook wb = XSSFTestDataSamples.openSampleWorkbook("59736.xlsx"); |
| FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator(); |
| Cell cell = wb.getSheetAt(0).getRow(0).getCell(0); |
| assertEquals(1, cell.getNumericCellValue(), 0.001); |
| |
| cell = wb.getSheetAt(0).getRow(1).getCell(0); |
| CellValue value = evaluator.evaluate(cell); |
| assertEquals(1, value.getNumberValue(), 0.001); |
| |
| cell = wb.getSheetAt(0).getRow(2).getCell(0); |
| value = evaluator.evaluate(cell); |
| assertEquals(1, value.getNumberValue(), 0.001); |
| } |
| |
| @Test |
| public void evaluateInCellReturnsSameDataType() throws IOException { |
| XSSFWorkbook wb = new XSSFWorkbook(); |
| wb.createSheet().createRow(0).createCell(0); |
| XSSFFormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator(); |
| XSSFCell cell = wb.getSheetAt(0).getRow(0).getCell(0); |
| XSSFCell same = evaluator.evaluateInCell(cell); |
| assertSame(cell, same); |
| wb.close(); |
| } |
| } |