mirror of
https://github.com/apache/poi.git
synced 2026-02-27 20:40:08 +08:00
[github-545] Make exported sheet names compatible with Excel. Thanks to Aleksandrs Jansons. This closes #545
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1913660 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
76b1a6fee4
commit
e83987b35d
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,28 +48,18 @@ final class TestSheetNameFormatter {
|
||||
confirmFormat("A12220", "'A12220'");
|
||||
confirmFormat("TAXRETURN19980415", "TAXRETURN19980415");
|
||||
|
||||
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
|
||||
|
||||
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());
|
||||
|
||||
StringBuffer sbf = new StringBuffer();
|
||||
//noinspection deprecation
|
||||
SheetNameFormatter.appendFormat(sbf, rawSheetName);
|
||||
assertEquals(expectedSheetNameEncoding, sbf.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFormatWithWorkbookName() {
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user