From 53d2276fdbe6d581b357c19bbc8e228952715cd5 Mon Sep 17 00:00:00 2001 From: satwik-bhardwaj Date: Wed, 10 Dec 2025 23:59:08 +0530 Subject: [PATCH 1/3] Added a log to the getSheet method to warn user for null value if sheet name exceeds 31 characters --- .../poi/hssf/usermodel/HSSFWorkbook.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index f80383b52c4..9ea09f7ae6a 100644 --- a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -1061,11 +1061,30 @@ public HSSFSheet getSheetAt(int index) { * If there are multiple matches, the first sheet from the list * of sheets is returned. * + *

+ * Note that Excel limits sheet names to 31 characters. If you try to look up + * a sheet by a name longer than that, a warning will be logged, since + * such a sheet cannot exist in Excel and the lookup will likely return {@code null}. + *

+ * * @param name of the sheet * @return HSSFSheet with the name provided or {@code null} if it does not exist */ @Override public HSSFSheet getSheet(String name) { + + if (name == null || name.isEmpty()) { + return null; + } + + if(name.length() > MAX_SENSITIVE_SHEET_NAME_LEN) { + LOGGER.atWarn().log( + "Sheet lookup requested with name '{}' which exceeds Excel's {} character limit. " + + "Sheets are stored with truncated names, so this lookup will likely return null.", + name, MAX_SENSITIVE_SHEET_NAME_LEN + ); + } + for (int k = 0; k < _sheets.size(); k++) { String sheetname = workbook.getSheetName(k); From e81222d0f7c24ee14a822597cc5952bd3b0acd20 Mon Sep 17 00:00:00 2001 From: satwik-bhardwaj Date: Wed, 10 Dec 2025 23:59:19 +0530 Subject: [PATCH 2/3] Added a test to check if exceeded 31 character sheet name returns null --- .../poi/hssf/usermodel/TestHSSFWorkbook.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java b/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java index 9d99627674c..1a18e27b756 100644 --- a/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java +++ b/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java @@ -395,6 +395,24 @@ void sheetSerializeSizeMismatch_bug45066() throws IOException { } } + @Test + void searchSheetExceed31CharactersName() throws IOException { + String sheetName = "ThisIsAVeryLongSheetNameExceeding31Chars"; + + try (HSSFWorkbook wb = new HSSFWorkbook()) { + wb.createSheet(sheetName); + + // Sheet name is truncated to 31 characters + Sheet sheetByOriginalName = wb.getSheet(sheetName); + assertNull(sheetByOriginalName, "Sheet lookup using original name >31 chars must return null"); + + // Truncated name SHOULD resolve + String truncated = sheetName.substring(0, 31); + Sheet sheetByTruncatedName = wb.getSheet(truncated); + assertNotNull(sheetByTruncatedName, "Sheet lookup using truncated name must return the sheet"); + } + } + /** * Checks that us and HSSFName play nicely with named ranges * that point to deleted sheets From 0b292f459cf9a27b7b40f48493a4dfe69ed47fc2 Mon Sep 17 00:00:00 2001 From: satwik-bhardwaj Date: Thu, 11 Dec 2025 13:56:41 +0530 Subject: [PATCH 3/3] replaced warning with exception in HSSFWorkbook and added same exception in XSSFWorkbook; and added a test to check - both for hssf and xssf - if exceeded 31 character sheet name returns null --- .../poi/xssf/usermodel/XSSFWorkbook.java | 18 ++++++++++++++ .../poi/xssf/usermodel/TestXSSFWorkbook.java | 20 ++++++++++++++++ .../poi/hssf/usermodel/HSSFWorkbook.java | 15 ++++++------ .../poi/hssf/usermodel/TestHSSFWorkbook.java | 24 ++++++++++--------- 4 files changed, 58 insertions(+), 19 deletions(-) diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java index a62bbfb7394..acfd39f562a 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java @@ -1213,11 +1213,29 @@ public String getPrintArea(int sheetIndex) { * If there are multiple matches, the first sheet from the list * of sheets is returned. * + *

+ * Note that Excel and the underlying Apache POI library limit sheet names + * to **31 characters**. This method will throw an exception if the + * provided {@code name} is longer than 31 characters, as such a sheet + * cannot exist in a valid Excel workbook. + *

+ * * @param name of the sheet * @return XSSFSheet with the name provided or {@code null} if it does not exist + * @throws IllegalArgumentException if the sheet name is longer than 31 characters */ @Override public XSSFSheet getSheet(String name) { + + if (name == null || name.isEmpty()) { + return null; + } + + if(name.length() > MAX_SENSITIVE_SHEET_NAME_LEN) { + throw new IllegalArgumentException("Sheet name must not be longer than " + + MAX_SENSITIVE_SHEET_NAME_LEN + " characters. Otherwise it cannot exist in Excel."); + } + for (XSSFSheet sheet : sheets) { if (name.equalsIgnoreCase(sheet.getSheetName())) { return sheet; diff --git a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java index 6a162273357..482f98ed688 100644 --- a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java +++ b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java @@ -1245,6 +1245,26 @@ void testRightToLeft() throws IOException { } } + /** + * Getting a sheet by name that exceeds 31 characters should throw + * an IllegalArgumentException + */ + @Test + void testGetSheetWithNameExceeding31Characters() throws IOException { + try (XSSFWorkbook wb = new XSSFWorkbook()) { + + // Attempting to GET a sheet with a name > 31 chars should throw + String sheetName = "ThisIsAVeryLongSheetNameExceeding31Chars"; + IllegalArgumentException exception = assertThrows( + IllegalArgumentException.class, + () -> wb.getSheet(sheetName), + "getSheet() should reject names longer than 31 characters" + ); + + assertTrue(exception.getMessage().contains("31 characters")); + } + } + @Test void test501RC1Failure() throws Exception { String filename = "0-www-crossref-org.lib.rivier.edu_education-files_suffix-generator.xlsm"; diff --git a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index 9ea09f7ae6a..e81d902e1e5 100644 --- a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -1062,13 +1062,15 @@ public HSSFSheet getSheetAt(int index) { * of sheets is returned. * *

- * Note that Excel limits sheet names to 31 characters. If you try to look up - * a sheet by a name longer than that, a warning will be logged, since - * such a sheet cannot exist in Excel and the lookup will likely return {@code null}. + * Note that Excel and the underlying Apache POI library limit sheet names + * to **31 characters**. This method will throw an exception if the + * provided {@code name} is longer than 31 characters, as such a sheet + * cannot exist in a valid Excel workbook. *

* * @param name of the sheet * @return HSSFSheet with the name provided or {@code null} if it does not exist + * @throws IllegalArgumentException if the sheet name is longer than 31 characters */ @Override public HSSFSheet getSheet(String name) { @@ -1078,11 +1080,8 @@ public HSSFSheet getSheet(String name) { } if(name.length() > MAX_SENSITIVE_SHEET_NAME_LEN) { - LOGGER.atWarn().log( - "Sheet lookup requested with name '{}' which exceeds Excel's {} character limit. " + - "Sheets are stored with truncated names, so this lookup will likely return null.", - name, MAX_SENSITIVE_SHEET_NAME_LEN - ); + throw new IllegalArgumentException("Sheet name must not be longer than " + + MAX_SENSITIVE_SHEET_NAME_LEN + " characters. Otherwise it cannot exist in Excel."); } for (int k = 0; k < _sheets.size(); k++) { diff --git a/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java b/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java index 1a18e27b756..b2859b1a866 100644 --- a/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java +++ b/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java @@ -395,21 +395,23 @@ void sheetSerializeSizeMismatch_bug45066() throws IOException { } } + /** + * Getting a sheet by name that exceeds 31 characters should throw + * an IllegalArgumentException + */ @Test - void searchSheetExceed31CharactersName() throws IOException { - String sheetName = "ThisIsAVeryLongSheetNameExceeding31Chars"; - + void testGetSheetWithNameExceeding31Characters() throws IOException { try (HSSFWorkbook wb = new HSSFWorkbook()) { - wb.createSheet(sheetName); - // Sheet name is truncated to 31 characters - Sheet sheetByOriginalName = wb.getSheet(sheetName); - assertNull(sheetByOriginalName, "Sheet lookup using original name >31 chars must return null"); + // Attempting to GET a sheet with a name > 31 chars should throw + String sheetName = "ThisIsAVeryLongSheetNameExceeding31Chars"; + IllegalArgumentException exception = assertThrows( + IllegalArgumentException.class, + () -> wb.getSheet(sheetName), + "getSheet() should reject names longer than 31 characters" + ); - // Truncated name SHOULD resolve - String truncated = sheetName.substring(0, 31); - Sheet sheetByTruncatedName = wb.getSheet(truncated); - assertNotNull(sheetByTruncatedName, "Sheet lookup using truncated name must return the sheet"); + assertTrue(exception.getMessage().contains("31 characters")); } }