From ca681fd7061f8db6af0749646ee5e1a7ba8ce447 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Tue, 12 Sep 2023 10:36:14 +0000 Subject: [PATCH] [bug-63934] Fix parsing of structure references. Thanks to Matthias Raschhofer. This closes #514 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1912263 13f79535-47bb-0310-9956-ffa450edef68 --- .../usermodel/TestXSSFFormulaEvaluation.java | 18 +++++++++++++ .../xssf/usermodel/TestXSSFFormulaParser.java | 10 +++++++- .../apache/poi/ss/formula/FormulaParser.java | 24 ++++++++++++++++++ test-data/spreadsheet/63934.xlsx | Bin 0 -> 13740 bytes 4 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 test-data/spreadsheet/63934.xlsx diff --git a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java index 887e23ae11d..9f66adffcc6 100644 --- a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java +++ b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java @@ -24,6 +24,10 @@ Licensed to the Apache Software Foundation (ASF) under one or more import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; +import java.text.DecimalFormat; import java.util.HashMap; import java.util.Map; import java.util.function.Function; @@ -32,6 +36,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more import org.apache.poi.ss.usermodel.BaseTestFormulaEvaluator; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellValue; +import org.apache.poi.ss.usermodel.DataFormatter; import org.apache.poi.ss.usermodel.FormulaEvaluator; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; @@ -444,4 +449,17 @@ void testBug62834() throws IOException { assertEquals("another value", value.getStringCellValue(), "wrong value A5"); } } + + @Test + void testBug63934() throws IOException { + try (Workbook wb = XSSFTestDataSamples.openSampleWorkbook("63934.xlsx")) { + + final Cell cell = wb.getSheetAt(0).getRow(1).getCell(1); + assertNotNull(cell); + + final FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator(); + final CellValue value = evaluator.evaluate(cell); + assertEquals("Male", value.getStringValue()); + } + } } diff --git a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java index fc4a9c60321..b312ab70f9a 100644 --- a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java +++ b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java @@ -655,6 +655,7 @@ The following cases are tested (copied from FormulaParser.parseStructuredReferen 16 Table1[[#Headers],[#Data],[col2]] 17 Table1[[#This Row], [col1]] 18 Table1[ [col1]:[col2] ] + 19 Table1[] */ final String tbl = "\\_Prime.1"; @@ -697,7 +698,7 @@ The following cases are tested (copied from FormulaParser.parseStructuredReferen assertEquals(1, ptgs.length); assertEquals("Table!A1:C7", ptgs[0].toFormulaString(), "Table1[#All]"); - ////// Case 5: Evaluate "Table1[#Data]" (excludes Header and Data rows) //////// + ////// Case 5: Evaluate "Table1[#Data]" (excludes Header and Total rows) //////// ptgs = parse(fpb, tbl+"[#Data]"); assertEquals(1, ptgs.length); assertEquals("Table!A2:C7", ptgs[0].toFormulaString(), "Table1[#Data]"); @@ -790,6 +791,13 @@ The following cases are tested (copied from FormulaParser.parseStructuredReferen assertEquals(1, ptgs.length); assertEquals("Table!B2:C7", ptgs[0].toFormulaString(), "Table1[[col]:[col2]]"); + ////// Case 19: Evaluate "Table1[]" //////// + // Excludes Header and Total rows, equivalent to Table1[#Data] (see case 5). + // This is the only case where [] is allowed. + ptgs = parse(fpb, tbl+"[]"); + assertEquals(1, ptgs.length); + assertEquals("Table!A2:C7", ptgs[0].toFormulaString(), "Table1[]"); + wb.close(); } } diff --git a/poi/src/main/java/org/apache/poi/ss/formula/FormulaParser.java b/poi/src/main/java/org/apache/poi/ss/formula/FormulaParser.java index 28d13bfbc8c..3203120f523 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/FormulaParser.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/FormulaParser.java @@ -595,6 +595,7 @@ private ParseNode parseRangeable() { * Parses a structured reference, returns it as area reference. * Examples: *
+     * Table1[]
      * Table1[col]
      * Table1[[#Totals],[col]]
      * Table1[#Totals]
@@ -637,6 +638,29 @@ private ParseNode parseStructuredReference(String tableName) {
         int savePtr0 = _pointer;
         nextChar();
 
+        // Special case: Table1[] is equivalent to Table1[#Data]
+        if (look == ']') {
+
+            // Consume the ']' character
+            nextChar();
+
+            // Skip header and total rows if available
+            int actualStartRow = startRow;
+            if (tbl.getHeaderRowCount() > 0) {
+                actualStartRow = startRow + 1;
+            }
+            int actualEndRow = endRow;
+            if (tbl.getTotalsRowCount() > 0) {
+                actualEndRow = endRow - 1;
+            }
+
+            final CellReference topLeft = new CellReference(actualStartRow, startCol);
+            final CellReference bottomRight = new CellReference(actualEndRow, endCol);
+            final SheetIdentifier sheetIden = new SheetIdentifier( null, new NameIdentifier(sheetName, true));
+            final Ptg ptg = _book.get3DReferencePtg(new AreaReference(topLeft, bottomRight, _ssVersion), sheetIden);
+            return new ParseNode(ptg);
+        }
+
         boolean isTotalsSpec = false;
         boolean isThisRowSpec = false;
         boolean isDataSpec = false;
diff --git a/test-data/spreadsheet/63934.xlsx b/test-data/spreadsheet/63934.xlsx
new file mode 100644
index 0000000000000000000000000000000000000000..d8aa43c4a639bcccb6ba8222613c3c5d702916bc
GIT binary patch
literal 13740
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

literal 0
HcmV?d00001