This is an automated email from the ASF dual-hosted git repository.

fanningpj pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/poi.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 9d37011683 workaround stray whitespace in sst index (#874)
9d37011683 is described below

commit 9d370116839056efd542612ca9a939d009e78575
Author: PJ Fanning <[email protected]>
AuthorDate: Tue Aug 5 12:00:54 2025 +0100

    workaround stray whitespace in sst index (#874)
    
    * tolerate whitespace in ints
    
    * try to workaround stray whitespace in sst index
    
    * Update TestAllFiles.java
---
 .../java/org/apache/poi/stress/TestAllFiles.java   |   3 ++
 .../xssf/eventusermodel/XSSFSheetXMLHandler.java   |  21 ++++++++----
 .../org/apache/poi/xssf/usermodel/XSSFCell.java    |  23 ++++++++++---
 .../eventusermodel/TestXSSFSheetXMLHandler.java    |  37 +++++++++++++++++++++
 .../apache/poi/xssf/usermodel/TestXSSFBugs.java    |  28 ++++++++++++++++
 test-data/spreadsheet/bug69769.xlsx                | Bin 0 -> 13976 bytes
 6 files changed, 100 insertions(+), 12 deletions(-)

diff --git 
a/poi-integration/src/test/java/org/apache/poi/stress/TestAllFiles.java 
b/poi-integration/src/test/java/org/apache/poi/stress/TestAllFiles.java
index 957b804ff5..8988c8a180 100644
--- a/poi-integration/src/test/java/org/apache/poi/stress/TestAllFiles.java
+++ b/poi-integration/src/test/java/org/apache/poi/stress/TestAllFiles.java
@@ -100,6 +100,9 @@ public class TestAllFiles {
         // stress docs
         "document/deep-table-cell.docx",
 
+        // invalid files
+        "spreadsheet/bug69769.xlsx",
+
         // NOTE: Expected failures should usually be added in file 
"stress.xls" instead
         // of being listed here in order to also verify the expected exception 
details!
     };
diff --git 
a/poi-ooxml/src/main/java/org/apache/poi/xssf/eventusermodel/XSSFSheetXMLHandler.java
 
b/poi-ooxml/src/main/java/org/apache/poi/xssf/eventusermodel/XSSFSheetXMLHandler.java
index dbe3bcdee6..110d343d7b 100644
--- 
a/poi-ooxml/src/main/java/org/apache/poi/xssf/eventusermodel/XSSFSheetXMLHandler.java
+++ 
b/poi-ooxml/src/main/java/org/apache/poi/xssf/eventusermodel/XSSFSheetXMLHandler.java
@@ -253,7 +253,7 @@ public class XSSFSheetXMLHandler extends DefaultHandler {
         } else if ("row".equals(localName)) {
             String rowNumStr = attributes.getValue("r");
             if (rowNumStr != null) {
-                rowNum = Integer.parseInt(rowNumStr) - 1;
+                rowNum = parseInt(rowNumStr) - 1;
             } else {
                 rowNum = nextRowNum;
             }
@@ -284,7 +284,7 @@ public class XSSFSheetXMLHandler extends DefaultHandler {
                 XSSFCellStyle style = null;
                 if (stylesTable != null) {
                     if (cellStyleStr != null) {
-                        int styleIndex = Integer.parseInt(cellStyleStr);
+                        int styleIndex = parseInt(cellStyleStr);
                         style = stylesTable.getStyleAt(styleIndex);
                     } else if (stylesTable.getNumCellStyles() > 0) {
                         style = stylesTable.getStyleAt(0);
@@ -392,7 +392,7 @@ public class XSSFSheetXMLHandler extends DefaultHandler {
                         if (this.formatString != null) {
                             try {
                                 // Try to use the value as a formattable number
-                                double d = Double.parseDouble(fv);
+                                double d = parseDouble(fv);
                                 thisStr = formatter.formatRawCellContents(d, 
this.formatIndex, this.formatString);
                             } catch (Exception e) {
                                 // Formula is a String result not a Numeric one
@@ -416,10 +416,10 @@ public class XSSFSheetXMLHandler extends DefaultHandler {
                     break;
 
                 case SST_STRING:
-                    String sstIndex = value.toString();
+                    String sstIndex = value.toString().trim();
                     if (!sstIndex.isEmpty()) {
                         try {
-                            int idx = Integer.parseInt(sstIndex);
+                            int idx = parseInt(sstIndex);
                             RichTextString rtss = 
sharedStringsTable.getItemAt(idx);
                             thisStr = rtss.toString();
                         } catch (NumberFormatException ex) {
@@ -433,7 +433,7 @@ public class XSSFSheetXMLHandler extends DefaultHandler {
                     if (this.formatString != null && !n.isEmpty()) {
                         try {
                             thisStr = formatter.formatRawCellContents(
-                                    Double.parseDouble(n), this.formatIndex, 
this.formatString);
+                                    parseDouble(n), this.formatIndex, 
this.formatString);
                         } catch (Exception e) {
                             LOG.atInfo().log(
                                     "Error formatting cell '{}' - will use its 
raw value instead (format '{}')",
@@ -515,7 +515,6 @@ public class XSSFSheetXMLHandler extends DefaultHandler {
         }
     }
 
-
     /**
      * Output an empty-cell comment.
      */
@@ -524,6 +523,14 @@ public class XSSFSheetXMLHandler extends DefaultHandler {
         output.cell(cellRef.formatAsString(), null, comment);
     }
 
+    private static int parseInt(String value) throws NumberFormatException {
+        return Integer.parseInt(value.trim());
+    }
+
+    private static double parseDouble(String value) throws 
NumberFormatException {
+        return Double.parseDouble(value.trim());
+    }
+
     private enum EmptyCellCommentsCheckType {
         CELL,
         END_OF_ROW,
diff --git 
a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFCell.java 
b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFCell.java
index 29088a5b48..d23375fda5 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFCell.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFCell.java
@@ -21,6 +21,8 @@ import java.time.LocalDateTime;
 import java.util.Calendar;
 import java.util.Date;
 
+import org.apache.logging.log4j.Logger;
+import org.apache.poi.logging.PoiLogManager;
 import org.apache.poi.ss.SpreadsheetVersion;
 import org.apache.poi.ss.formula.FormulaParser;
 import org.apache.poi.ss.formula.FormulaRenderer;
@@ -73,6 +75,7 @@ import 
org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType;
  */
 public final class XSSFCell extends CellBase {
 
+    private static final Logger LOG = PoiLogManager.getLogger(XSSFCell.class);
     private static final String FALSE_AS_STRING = "0";
     private static final String TRUE_AS_STRING  = "1";
     private static final String FALSE = "FALSE";
@@ -244,7 +247,7 @@ public final class XSSFCell extends CellBase {
                         return 0.0;
                     }
                     try {
-                        return Double.parseDouble(v);
+                        return parseDouble(v);
                     } catch(NumberFormatException e) {
                         throw typeMismatch(CellType.NUMERIC, CellType.STRING, 
false);
                     }
@@ -330,12 +333,13 @@ public final class XSSFCell extends CellBase {
         } else {
             if (_cell.isSetV()) {
                 try {
-                    int idx = Integer.parseInt(_cell.getV());
+                    int idx = parseInt(_cell.getV());
                     rt = 
(XSSFRichTextString)_sharedStringSource.getItemAt(idx);
                 } catch (Throwable t) {
                     if (ExceptionUtil.isFatal(t)) {
                         ExceptionUtil.rethrow(t);
                     }
+                    LOG.atError().withThrowable(t).log("Failed to parse SST 
index '{}'", _cell.getV());
                     rt = new XSSFRichTextString("");
                 }
             } else {
@@ -1122,12 +1126,12 @@ public final class XSSFCell extends CellBase {
             case BOOLEAN:
                 return TRUE_AS_STRING.equals(_cell.getV());
             case STRING:
-                int sstIndex = Integer.parseInt(_cell.getV());
+                int sstIndex = parseInt(_cell.getV());
                 RichTextString rt = _sharedStringSource.getItemAt(sstIndex);
                 String text = rt.getString();
                 return Boolean.parseBoolean(text);
             case NUMERIC:
-                return Double.parseDouble(_cell.getV()) != 0;
+                return parseDouble(_cell.getV()) != 0;
 
             case ERROR:
                 // fall-through
@@ -1149,13 +1153,14 @@ public final class XSSFCell extends CellBase {
                 return TRUE_AS_STRING.equals(_cell.getV()) ? TRUE : FALSE;
             case STRING:
                 try {
-                    int sstIndex = Integer.parseInt(_cell.getV());
+                    int sstIndex = parseInt(_cell.getV());
                     RichTextString rt = 
_sharedStringSource.getItemAt(sstIndex);
                     return rt.getString();
                 } catch (Throwable t) {
                     if (ExceptionUtil.isFatal(t)) {
                         ExceptionUtil.rethrow(t);
                     }
+                    LOG.atError().withThrowable(t).log("Failed to parse SST 
index '{}'", _cell.getV());
                     return "";
                 }
             case NUMERIC:
@@ -1227,4 +1232,12 @@ public final class XSSFCell extends CellBase {
         ctCell.setR(r);
     }
 
+    private static int parseInt(String value) throws NumberFormatException {
+        return Integer.parseInt(value.trim());
+    }
+
+    private static double parseDouble(String value) throws 
NumberFormatException {
+        return Double.parseDouble(value.trim());
+    }
+
 }
diff --git 
a/poi-ooxml/src/test/java/org/apache/poi/xssf/eventusermodel/TestXSSFSheetXMLHandler.java
 
b/poi-ooxml/src/test/java/org/apache/poi/xssf/eventusermodel/TestXSSFSheetXMLHandler.java
index b3f1215925..7e5a3071f2 100644
--- 
a/poi-ooxml/src/test/java/org/apache/poi/xssf/eventusermodel/TestXSSFSheetXMLHandler.java
+++ 
b/poi-ooxml/src/test/java/org/apache/poi/xssf/eventusermodel/TestXSSFSheetXMLHandler.java
@@ -26,7 +26,9 @@ import org.xml.sax.InputSource;
 import org.xml.sax.XMLReader;
 
 import java.io.InputStream;
+import java.util.HashMap;
 import java.util.Iterator;
+import java.util.Map;
 
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -100,4 +102,39 @@ class TestXSSFSheetXMLHandler {
             }
         }
     }
+
+    @Test
+    void testSstStrayWhitespace() throws Exception {
+        try (OPCPackage xlsxPackage = 
OPCPackage.open(_ssTests.openResourceAsStream("bug69769.xlsx"))) {
+            final XSSFReader reader = new XSSFReader(xlsxPackage);
+            final Iterator<InputStream> iter = reader.getSheetsData();
+            final Map<String, String> cellValues = new HashMap<>();
+
+            try (InputStream stream = iter.next()) {
+                final XMLReader sheetParser = 
XMLHelper.getSaxParserFactory().newSAXParser().getXMLReader();
+
+                sheetParser.setContentHandler(new 
XSSFSheetXMLHandler(reader.getStylesTable(),
+                        new ReadOnlySharedStringsTable(xlsxPackage), new 
SheetContentsHandler() {
+                    @Override
+                    public void startRow(final int rowNum) {
+                    }
+
+                    @Override
+                    public void endRow(final int rowNum) {
+                    }
+
+                    @Override
+                    public void cell(final String cellReference, final String 
formattedValue,
+                                     final XSSFComment comment) {
+                        cellValues.put(cellReference, formattedValue);
+                    }
+                }, false));
+
+                assertDoesNotThrow(() -> sheetParser.parse(new 
InputSource(stream)));
+
+                assertEquals(4, cellValues.size());
+                assertEquals("Mustermann", cellValues.get("B2"));
+            }
+        }
+    }
 }
diff --git 
a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFBugs.java 
b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFBugs.java
index ef8c8542a0..22a9ec10e2 100644
--- a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFBugs.java
+++ b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFBugs.java
@@ -3910,6 +3910,34 @@ public final class TestXSSFBugs extends 
BaseTestBugzillaIssues {
         }
     }
 
+    @Test
+    void testBug69769() throws Exception {
+        final int expectedCount = 3;
+        try (XSSFWorkbook wb = openSampleWorkbook("bug69769.xlsx")) {
+            SharedStringsTable sst = wb.getSharedStringSource();
+            assertNotNull(sst);
+            assertEquals(expectedCount, sst.getCount());
+            for (int i = 0; i < expectedCount; i++) {
+                assertNotNull(sst.getItemAt(i));
+            }
+            XSSFSheet ws = wb.getSheetAt(0);
+            int nRowCount = ws.getLastRowNum();
+            DataFormatter df = new DataFormatter();
+            for (int r = 0; r <= nRowCount; r++) {
+                XSSFRow row = ws.getRow(r);
+                if (row != null) {
+                    for (Cell cell : row) {
+                        String cellValue = df.formatCellValue(cell);
+                        assertNotNull(cellValue, "Cell value should not be 
null");
+                        if (cell.getRowIndex() == 1 && cell.getColumnIndex() 
== 1) {
+                            assertEquals("Mustermann", cellValue);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     private static void readByCommonsCompress(File temp_excel_poi) throws 
IOException {
         /* read by commons-compress*/
         try (ZipFile zipFile = 
ZipFile.builder().setFile(temp_excel_poi).get()) {
diff --git a/test-data/spreadsheet/bug69769.xlsx 
b/test-data/spreadsheet/bug69769.xlsx
new file mode 100644
index 0000000000..39262dfff3
Binary files /dev/null and b/test-data/spreadsheet/bug69769.xlsx differ


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to