mirror of https://github.com/apache/poi.git
Fix for bug 45876 - allowed BoundSheetRecord to take sheet names longer than 31 chars
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@700280 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
857ead338e
commit
d14991ed02
|
@ -37,6 +37,7 @@
|
|||
|
||||
<!-- Don't forget to update status.xml too! -->
|
||||
<release version="3.2-alpha1" date="2008-??-??">
|
||||
<action dev="POI-DEVELOPERS" type="fix">45876 - fixed BoundSheetRecord to allow sheet names longer than 31 chars</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">45890 - fixed HSSFSheet.shiftRows to also update conditional formats</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">45865 modified Formula Parser/Evaluator to handle cross-worksheet formulas</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">Optimised the FormulaEvaluator to take cell dependencies into account</action>
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
<!-- Don't forget to update changes.xml too! -->
|
||||
<changes>
|
||||
<release version="3.2-alpha1" date="2008-??-??">
|
||||
<action dev="POI-DEVELOPERS" type="fix">45876 - fixed BoundSheetRecord to allow sheet names longer than 31 chars</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">45890 - fixed HSSFSheet.shiftRows to also update conditional formats</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">45865 modified Formula Parser/Evaluator to handle cross-worksheet formulas</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">Optimised the FormulaEvaluator to take cell dependencies into account</action>
|
||||
|
|
|
@ -55,6 +55,12 @@ import org.apache.poi.util.POILogger;
|
|||
* @version 1.0-pre
|
||||
*/
|
||||
public final class Workbook implements Model {
|
||||
/**
|
||||
* Excel silently truncates long sheet names to 31 chars.
|
||||
* This constant is used to ensure uniqueness in the first 31 chars
|
||||
*/
|
||||
private static final int MAX_SENSITIVE_SHEET_NAME_LEN = 31;
|
||||
|
||||
private static final int DEBUG = POILogger.DEBUG;
|
||||
|
||||
/**
|
||||
|
@ -488,32 +494,43 @@ public final class Workbook implements Model {
|
|||
|
||||
/**
|
||||
* sets the name for a given sheet. If the boundsheet record doesn't exist and
|
||||
* its only one more than we have, go ahead and create it. If its > 1 more than
|
||||
* its only one more than we have, go ahead and create it. If it's > 1 more than
|
||||
* we have, except
|
||||
*
|
||||
* @param sheetnum the sheet number (0 based)
|
||||
* @param sheetname the name for the sheet
|
||||
*/
|
||||
public void setSheetName(int sheetnum, String sheetname ) {
|
||||
public void setSheetName(int sheetnum, String sheetname) {
|
||||
checkSheets(sheetnum);
|
||||
BoundSheetRecord sheet = (BoundSheetRecord)boundsheets.get( sheetnum );
|
||||
sheet.setSheetname(sheetname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a workbook contains the provided sheet name.
|
||||
* Determines whether a workbook contains the provided sheet name. For the purpose of
|
||||
* comparison, long names are truncated to 31 chars.
|
||||
*
|
||||
* @param name the name to test (case insensitive match)
|
||||
* @param excludeSheetIdx the sheet to exclude from the check or -1 to include all sheets in the check.
|
||||
* @return true if the sheet contains the name, false otherwise.
|
||||
*/
|
||||
public boolean doesContainsSheetName( String name, int excludeSheetIdx )
|
||||
{
|
||||
for ( int i = 0; i < boundsheets.size(); i++ )
|
||||
{
|
||||
public boolean doesContainsSheetName(String name, int excludeSheetIdx) {
|
||||
String aName = name;
|
||||
if (aName.length() > MAX_SENSITIVE_SHEET_NAME_LEN) {
|
||||
aName = aName.substring(0, MAX_SENSITIVE_SHEET_NAME_LEN);
|
||||
}
|
||||
for (int i = 0; i < boundsheets.size(); i++) {
|
||||
BoundSheetRecord boundSheetRecord = getBoundSheetRec(i);
|
||||
if (excludeSheetIdx != i && name.equalsIgnoreCase(boundSheetRecord.getSheetname()))
|
||||
if (excludeSheetIdx == i) {
|
||||
continue;
|
||||
}
|
||||
String bName = boundSheetRecord.getSheetname();
|
||||
if (bName.length() > MAX_SENSITIVE_SHEET_NAME_LEN) {
|
||||
bName = bName.substring(0, MAX_SENSITIVE_SHEET_NAME_LEN);
|
||||
}
|
||||
if (aName.equalsIgnoreCase(bName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1954,9 +1971,9 @@ public final class Workbook implements Model {
|
|||
return (short)getOrCreateLinkTable().checkExternSheet(sheetNumber);
|
||||
}
|
||||
|
||||
public int getExternalSheetIndex(String workbookName, String sheetName) {
|
||||
return getOrCreateLinkTable().getExternalSheetIndex(workbookName, sheetName);
|
||||
}
|
||||
public int getExternalSheetIndex(String workbookName, String sheetName) {
|
||||
return getOrCreateLinkTable().getExternalSheetIndex(workbookName, sheetName);
|
||||
}
|
||||
|
||||
|
||||
/** gets the total number of names
|
||||
|
|
|
@ -116,9 +116,8 @@ public final class BoundSheetRecord extends Record {
|
|||
throw new IllegalArgumentException("sheetName must not be null");
|
||||
}
|
||||
int len = sheetName.length();
|
||||
if (len < 1 || len > 31) {
|
||||
throw new IllegalArgumentException("sheetName '" + sheetName
|
||||
+ "' is invalid - must be 1-30 characters long");
|
||||
if (len < 1) {
|
||||
throw new IllegalArgumentException("sheetName must not be empty string");
|
||||
}
|
||||
for (int i=0; i<len; i++) {
|
||||
char ch = sheetName.charAt(i);
|
||||
|
|
|
@ -515,15 +515,17 @@ public class HSSFWorkbook extends POIDocument
|
|||
}
|
||||
|
||||
/**
|
||||
* set the sheet name.
|
||||
* Will throw IllegalArgumentException if the name is greater than 31 chars
|
||||
* or contains /\?*[]
|
||||
* Sets the sheet name.
|
||||
* Will throw IllegalArgumentException if the name is duplicated or contains /\?*[]
|
||||
* Note - Excel allows sheet names up to 31 chars in length but other applications allow more.
|
||||
* Excel does not crash with names longer than 31 chars, but silently truncates such names to
|
||||
* 31 chars. POI enforces uniqueness on the first 31 chars.
|
||||
*
|
||||
* @param sheetIx number (0 based)
|
||||
*/
|
||||
public void setSheetName(int sheetIx, String name)
|
||||
{
|
||||
if (workbook.doesContainsSheetName( name, sheetIx )) {
|
||||
throw new IllegalArgumentException( "The workbook already contains a sheet with this name" );
|
||||
public void setSheetName(int sheetIx, String name) {
|
||||
if (workbook.doesContainsSheetName(name, sheetIx)) {
|
||||
throw new IllegalArgumentException("The workbook already contains a sheet with this name");
|
||||
}
|
||||
validateSheetIndex(sheetIx);
|
||||
workbook.setSheetName(sheetIx, name);
|
||||
|
@ -726,14 +728,14 @@ public class HSSFWorkbook extends POIDocument
|
|||
* create an HSSFSheet for this HSSFWorkbook, adds it to the sheets and
|
||||
* returns the high level representation. Use this to create new sheets.
|
||||
*
|
||||
* @param sheetname
|
||||
* sheetname to set for the sheet.
|
||||
* @param sheetname the name for the new sheet. Note - certain length limits
|
||||
* apply. See {@link #setSheetName(int, String)}.
|
||||
*
|
||||
* @return HSSFSheet representing the new sheet.
|
||||
* @throws IllegalArgumentException
|
||||
* if there is already a sheet present with a case-insensitive
|
||||
* match for the specified name.
|
||||
*/
|
||||
|
||||
public HSSFSheet createSheet(String sheetname)
|
||||
{
|
||||
if (workbook.doesContainsSheetName( sheetname, _sheets.size() ))
|
||||
|
|
|
@ -45,13 +45,6 @@ public final class TestBoundSheetRecord extends TestCase {
|
|||
public void testName() {
|
||||
BoundSheetRecord record = new BoundSheetRecord("1234567890223456789032345678904");
|
||||
|
||||
try {
|
||||
record.setSheetname("12345678902234567890323456789042");
|
||||
throw new AssertionFailedError("Should have thrown IllegalArgumentException, but didnt");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
record.setSheetname("s//*s");
|
||||
throw new AssertionFailedError("Should have thrown IllegalArgumentException, but didnt");
|
||||
|
|
|
@ -891,4 +891,23 @@ public final class TestHSSFSheet extends TestCase {
|
|||
|
||||
//TODO: check shapeId in the cloned sheet
|
||||
}
|
||||
|
||||
/**
|
||||
* POI now (Sep 2008) allows sheet names longer than 31 chars (for other apps besides Excel).
|
||||
* Since Excel silently truncates to 31, make sure that POI enforces uniqueness on the first
|
||||
* 31 chars.
|
||||
*/
|
||||
public void testLongSheetNames() {
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
final String SAME_PREFIX = "A123456789B123456789C123456789"; // 30 chars
|
||||
|
||||
wb.createSheet(SAME_PREFIX + "Dxxxx");
|
||||
try {
|
||||
wb.createSheet(SAME_PREFIX + "Dyyyy"); // identical up to the 32nd char
|
||||
throw new AssertionFailedError("Expected exception not thrown");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("The workbook already contains a sheet of this name", e.getMessage());
|
||||
}
|
||||
wb.createSheet(SAME_PREFIX + "Exxxx"); // OK - differs in the 31st char
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue