]> source.dussan.org Git - poi.git/commitdiff
[github-545] Make exported sheet names compatible with Excel. Thanks to Aleksandrs...
authorPJ Fanning <fanningpj@apache.org>
Tue, 7 Nov 2023 21:50:12 +0000 (21:50 +0000)
committerPJ Fanning <fanningpj@apache.org>
Tue, 7 Nov 2023 21:50:12 +0000 (21:50 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1913660 13f79535-47bb-0310-9956-ffa450edef68

poi/src/main/java/org/apache/poi/ss/formula/SheetNameFormatter.java
poi/src/test/java/org/apache/poi/ss/formula/TestSheetNameFormatter.java

index 26eca119c149bff6431f7746f4dc3bfe56309a48..c6b5e82a9583b0907e66e00c5016cfaa24a6a22f 100644 (file)
@@ -164,6 +164,9 @@ public final class SheetNameFormatter {
         if (nameLooksLikeBooleanLiteral(rawSheetName)) {
             return true;
         }
+        if (nameStartsWithR1C1CellReference(rawSheetName)) {
+            return true;
+        }
         // Error constant literals all contain '#' and other special characters
         // so they don't get this far
         return false;
@@ -264,4 +267,39 @@ public final class SheetNameFormatter {
         String numbersSuffix = matcher.group(2);
         return cellReferenceIsWithinRange(lettersPrefix, numbersSuffix);
     }
+
+    /**
+     * Checks if the sheet name starts with R1C1 style cell reference.
+     * If this is the case Excel requires the sheet name to be enclosed in single quotes.
+     * @return {@code true} if the specified rawSheetName starts with R1C1 style cell reference
+     */
+    static boolean nameStartsWithR1C1CellReference(String rawSheetName) {
+        int len = rawSheetName.length();
+        char firstChar = rawSheetName.charAt(0);
+        if (firstChar == 'R' || firstChar == 'r') {
+            if (len > 1) {
+                char secondChar = rawSheetName.charAt(1);
+                if (secondChar == 'C' || secondChar == 'c') {
+                    if (len > 2) {
+                        char thirdChar = rawSheetName.charAt(2);
+                        return Character.isDigit(thirdChar);
+                    } else {
+                        return true;
+                    }
+                } else {
+                    return Character.isDigit(secondChar);
+                }
+            } else {
+                return true;
+            }
+        } else if (firstChar == 'C' || firstChar == 'c') {
+            if (len > 1) {
+                char secondChar = rawSheetName.charAt(1);
+                return Character.isDigit(secondChar);
+            } else {
+                return true;
+            }
+        }
+        return false;
+    }
 }
index bfd2c054923ab92c9337c0ff5cb63f9b1cff08ef..3bc0595469150bdd2979ff10346d7571c28913a7 100644 (file)
@@ -48,26 +48,16 @@ final class TestSheetNameFormatter {
         confirmFormat("A12220", "'A12220'");
         confirmFormat("TAXRETURN19980415", "TAXRETURN19980415");
 
-        confirmFormat(null, "#REF");
-    }
-
-    private static void confirmFormat(String rawSheetName, String expectedSheetNameEncoding) {
-        // test all variants
-
-        assertEquals(expectedSheetNameEncoding, SheetNameFormatter.format(rawSheetName));
-
-        StringBuilder sb = new StringBuilder();
-        SheetNameFormatter.appendFormat(sb, rawSheetName);
-        assertEquals(expectedSheetNameEncoding, sb.toString());
-
-        sb = new StringBuilder();
-        SheetNameFormatter.appendFormat((Appendable)sb, rawSheetName);
-        assertEquals(expectedSheetNameEncoding, sb.toString());
+        confirmFormat("RC9Sheet", "'RC9Sheet'"); // starts with R1C1 style ref ('RC9')
+        confirmFormat("r", "'r'"); // R1C1 style ref
+        confirmFormat("rc", "'rc'"); // R1C1 style ref
+        confirmFormat("C", "'C'"); // R1C1 style ref
+        confirmFormat("rCsheet", "rCsheet"); // 'rc' + character is not qualified as R1C1 style ref
+        confirmFormat("ra", "ra"); // 'r' + character is not qualified as R1C1 style ref
+        confirmFormat("r1a", "'r1a'"); // 'r1' is R1C1 style ref
+        confirmFormat("Rc1sheet", "'Rc1sheet'"); // 'rc1' is R1C1 style ref
 
-        StringBuffer sbf = new StringBuffer();
-        //noinspection deprecation
-        SheetNameFormatter.appendFormat(sbf, rawSheetName);
-        assertEquals(expectedSheetNameEncoding, sbf.toString());
+        confirmFormat(null, "#REF");
     }
 
     @Test
@@ -92,23 +82,6 @@ final class TestSheetNameFormatter {
         confirmFormat(null, null, "[#REF]#REF");
     }
 
-    private static void confirmFormat(String workbookName, String rawSheetName, String expectedSheetNameEncoding) {
-        // test all variants
-
-        StringBuilder sb = new StringBuilder();
-        SheetNameFormatter.appendFormat(sb, workbookName, rawSheetName);
-        assertEquals(expectedSheetNameEncoding, sb.toString());
-
-        sb = new StringBuilder();
-        SheetNameFormatter.appendFormat((Appendable)sb, workbookName, rawSheetName);
-        assertEquals(expectedSheetNameEncoding, sb.toString());
-
-        StringBuffer sbf = new StringBuffer();
-        //noinspection deprecation
-        SheetNameFormatter.appendFormat(sbf, workbookName, rawSheetName);
-        assertEquals(expectedSheetNameEncoding, sbf.toString());
-    }
-
     @Test
     void testFormatException() {
         Appendable mock = new Appendable() {
@@ -143,10 +116,6 @@ final class TestSheetNameFormatter {
         confirmFormat("No", "No");
     }
 
-    private static void confirmCellNameMatch(String rawSheetName, boolean expected) {
-        assertEquals(expected, SheetNameFormatter.nameLooksLikePlainCellReference(rawSheetName));
-    }
-
     /**
      * Tests functionality to determine whether a sheet name containing only letters and digits
      * would look (to Excel) like a cell name.
@@ -164,12 +133,6 @@ final class TestSheetNameFormatter {
         confirmCellNameMatch("SALES20080101", false); // out of range
     }
 
-    private static void confirmCellRange(String text, int numberOfPrefixLetters, boolean expected) {
-        String prefix = text.substring(0, numberOfPrefixLetters);
-        String suffix = text.substring(numberOfPrefixLetters);
-        assertEquals(expected, SheetNameFormatter.cellReferenceIsWithinRange(prefix, suffix));
-    }
-
     /**
      * Tests exact boundaries for names that look very close to cell names (i.e. contain 1 or more
      * letters followed by one or more digits).
@@ -188,4 +151,50 @@ final class TestSheetNameFormatter {
         confirmCellRange("iV65536", 2, true);  // max cell in Excel 97-2003
         confirmCellRange("IW65537", 2, false);
     }
+
+    private static void confirmCellNameMatch(String rawSheetName, boolean expected) {
+        assertEquals(expected, SheetNameFormatter.nameLooksLikePlainCellReference(rawSheetName));
+    }
+
+    private static void confirmCellRange(String text, int numberOfPrefixLetters, boolean expected) {
+        String prefix = text.substring(0, numberOfPrefixLetters);
+        String suffix = text.substring(numberOfPrefixLetters);
+        assertEquals(expected, SheetNameFormatter.cellReferenceIsWithinRange(prefix, suffix));
+    }
+
+    private static void confirmFormat(String workbookName, String rawSheetName, String expectedSheetNameEncoding) {
+        // test all variants
+
+        StringBuilder sb = new StringBuilder();
+        SheetNameFormatter.appendFormat(sb, workbookName, rawSheetName);
+        assertEquals(expectedSheetNameEncoding, sb.toString());
+
+        sb = new StringBuilder();
+        SheetNameFormatter.appendFormat((Appendable)sb, workbookName, rawSheetName);
+        assertEquals(expectedSheetNameEncoding, sb.toString());
+
+        StringBuffer sbf = new StringBuffer();
+        //noinspection deprecation
+        SheetNameFormatter.appendFormat(sbf, workbookName, rawSheetName);
+        assertEquals(expectedSheetNameEncoding, sbf.toString());
+    }
+
+    private static void confirmFormat(String rawSheetName, String expectedSheetNameEncoding) {
+        // test all variants
+
+        assertEquals(expectedSheetNameEncoding, SheetNameFormatter.format(rawSheetName));
+
+        StringBuilder sb = new StringBuilder();
+        SheetNameFormatter.appendFormat(sb, rawSheetName);
+        assertEquals(expectedSheetNameEncoding, sb.toString());
+
+        sb = new StringBuilder();
+        SheetNameFormatter.appendFormat((Appendable)sb, rawSheetName);
+        assertEquals(expectedSheetNameEncoding, sb.toString());
+
+        StringBuffer sbf = new StringBuffer();
+        //noinspection deprecation
+        SheetNameFormatter.appendFormat(sbf, rawSheetName);
+        assertEquals(expectedSheetNameEncoding, sbf.toString());
+    }
 }