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 4100b5f9c..657739f99 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java @@ -26,8 +26,11 @@ import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellValue; 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; public final class TestXSSFFormulaEvaluation extends BaseTestFormulaEvaluator { @@ -174,4 +177,70 @@ public final class TestXSSFFormulaEvaluation extends BaseTestFormulaEvaluator { public void TODOtestCachedReferencesToOtherWorkbooks() 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 + * + * DISABLED pending support, see bug #55906 + */ + public void DISABLEDtestMultiSheetReferencesHSSFandXSSF() throws Exception { + Workbook[] wbs = new Workbook[] { + HSSFTestDataSamples.openSampleWorkbook("55906-MultiSheetRefs.xls"), + XSSFTestDataSamples.openSampleWorkbook("55906-MultiSheetRefs.xlsx") + }; + for (Workbook wb : wbs) { + 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("66", 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", evaluator.evaluate(avgF).formatAsString()); + + Cell minF = s1.getRow(3).getCell(1); + assertNotNull(minF); + assertEquals("MIX(Sheet1:Sheet3!A$1)", minF.getCellFormula()); + assertEquals("11", evaluator.evaluate(minF).formatAsString()); + + Cell maxF = s1.getRow(4).getCell(1); + assertNotNull(maxF); + assertEquals("MAX(Sheet1:Sheet3!A$1)", maxF.getCellFormula()); + assertEquals("33", evaluator.evaluate(maxF).formatAsString()); + + Cell countF = s1.getRow(5).getCell(1); + assertNotNull(countF); + assertEquals("COUNT(Sheet1:Sheet3!A$1)", countF.getCellFormula()); + assertEquals("3", 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", 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", 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", evaluator.evaluate(countA_3F).formatAsString()); + } + } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java index 13bde7910..c00622793 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java @@ -18,11 +18,16 @@ package org.apache.poi.xssf.usermodel; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.formula.FormulaParseException; import org.apache.poi.ss.formula.FormulaParser; +import org.apache.poi.ss.formula.FormulaParsingWorkbook; import org.apache.poi.ss.formula.FormulaType; import org.apache.poi.ss.formula.ptg.Area3DPxg; import org.apache.poi.ss.formula.ptg.AreaPtg; @@ -35,11 +40,15 @@ import org.apache.poi.ss.formula.ptg.NameXPxg; import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.ss.formula.ptg.Ref3DPxg; import org.apache.poi.ss.formula.ptg.RefPtg; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.XSSFTestDataSamples; +import org.junit.Ignore; import org.junit.Test; public final class TestXSSFFormulaParser { - private static Ptg[] parse(XSSFEvaluationWorkbook fpb, String fmla) { + private static Ptg[] parse(FormulaParsingWorkbook fpb, String fmla) { return FormulaParser.parse(fmla, fpb, FormulaType.CELL, -1); } @@ -227,4 +236,71 @@ public final class TestXSSFFormulaParser { assertEquals("NR_Global_B2",((NameXPxg)ptgs[0]).getNameName()); assertEquals("[1]!NR_Global_B2",((NameXPxg)ptgs[0]).toFormulaString()); } + + /** + * 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 read and parse these kinds of references + * (but not evaluate - that's elsewhere in the test suite) + * + * DISABLED pending support, see bug #55906 + */ + @Test + @Ignore + public void multiSheetReferencesHSSFandXSSF() throws Exception { + Workbook[] wbs = new Workbook[] { + HSSFTestDataSamples.openSampleWorkbook("55906-MultiSheetRefs.xls"), + XSSFTestDataSamples.openSampleWorkbook("55906-MultiSheetRefs.xlsx") + }; + for (Workbook wb : wbs) { + Sheet s1 = wb.getSheetAt(0); + Ptg[] ptgs; + + // Check the contents + Cell sumF = s1.getRow(2).getCell(0); + assertNotNull(sumF); + assertEquals("SUM(Sheet1:Sheet3!A1)", sumF.getCellFormula()); + + Cell avgF = s1.getRow(2).getCell(1); + assertNotNull(avgF); + assertEquals("AVERAGE(Sheet1:Sheet3!A1)", avgF.getCellFormula()); + + Cell countAF = s1.getRow(2).getCell(2); + assertNotNull(countAF); + assertEquals("COUNTA(Sheet1:Sheet3!C1)", countAF.getCellFormula()); + + Cell maxF = s1.getRow(4).getCell(1); + assertNotNull(maxF); + assertEquals("MAX(Sheet1:Sheet3!A$1)", maxF.getCellFormula()); + + // Create a formula parser + FormulaParsingWorkbook fpb = null; + if (wb instanceof HSSFWorkbook) + fpb = HSSFEvaluationWorkbook.create((HSSFWorkbook)wb); + else + fpb = XSSFEvaluationWorkbook.create((XSSFWorkbook)wb); + + // Check things parse as expected: + + // SUM to one cell over 3 workbooks, relative reference + ptgs = parse(fpb, "SUM(Sheet1:Sheet3!A1"); + // TODO +// assertEquals(1, ptgs.length); +// assertEquals(Ref3DPxg.class, ptgs[0].getClass()); + + // MAX to one cell over 3 workbooks, absolute row reference + ptgs = parse(fpb, "MAX(Sheet1:Sheet3!A$1"); + // TODO +// assertEquals(1, ptgs.length); +// assertEquals(Ref3DPxg.class, ptgs[0].getClass()); + + // MIN to one cell over 3 workbooks, absolute reference + ptgs = parse(fpb, "MIN(Sheet1:Sheet3!$A$1"); + // TODO +// assertEquals(1, ptgs.length); +// assertEquals(Ref3DPxg.class, ptgs[0].getClass()); + } + } } diff --git a/test-data/spreadsheet/55906-MultiSheetRefs.xls b/test-data/spreadsheet/55906-MultiSheetRefs.xls new file mode 100644 index 000000000..5e471ccc8 Binary files /dev/null and b/test-data/spreadsheet/55906-MultiSheetRefs.xls differ diff --git a/test-data/spreadsheet/55906-MultiSheetRefs.xlsx b/test-data/spreadsheet/55906-MultiSheetRefs.xlsx new file mode 100644 index 000000000..eda24b21e Binary files /dev/null and b/test-data/spreadsheet/55906-MultiSheetRefs.xlsx differ