Refinements to fix for bug 45126. Excel does not produce any records like 'Excel_Name_Record_Titles_*'

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@684938 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2008-08-11 21:24:19 +00:00
parent d2b3adb3cc
commit 829b2eb084
7 changed files with 980 additions and 998 deletions

View File

@ -192,14 +192,18 @@ final class LinkTable {
} }
public NameRecord getSpecificBuiltinRecord(byte name, int sheetIndex) { /**
* @param builtInCode a BUILTIN_~ constant from {@link NameRecord}
* @param sheetNumber 1-based sheet number
*/
public NameRecord getSpecificBuiltinRecord(byte builtInCode, int sheetNumber) {
Iterator iterator = _definedNames.iterator(); Iterator iterator = _definedNames.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
NameRecord record = ( NameRecord ) iterator.next(); NameRecord record = ( NameRecord ) iterator.next();
//print areas are one based //print areas are one based
if (record.getBuiltInName() == name && record.getIndexToSheet() == sheetIndex) { if (record.getBuiltInName() == builtInCode && record.getSheetNumber() == sheetNumber) {
return record; return record;
} }
} }
@ -241,31 +245,29 @@ final class LinkTable {
_definedNames.remove(namenum); _definedNames.remove(namenum);
} }
/** /**
* checks if the given name is already included in the linkTable * checks if the given name is already included in the linkTable
*/ */
public boolean nameAlreadyExists(NameRecord name) public boolean nameAlreadyExists(NameRecord name)
{ {
// Check to ensure no other names have the same case-insensitive name // Check to ensure no other names have the same case-insensitive name
for ( int i = getNumNames()-1; i >=0; i-- ) { for ( int i = getNumNames()-1; i >=0; i-- ) {
NameRecord rec = getNameRecord(i); NameRecord rec = getNameRecord(i);
if (rec != name) { if (rec != name) {
if (isDuplicatedNames(name, rec)) if (isDuplicatedNames(name, rec))
return true; return true;
} }
} }
return false; return false;
} }
private boolean isDuplicatedNames(NameRecord firstName, NameRecord lastName) private static boolean isDuplicatedNames(NameRecord firstName, NameRecord lastName) {
{ return lastName.getNameText().equalsIgnoreCase(firstName.getNameText())
return lastName.getNameText().equalsIgnoreCase(firstName.getNameText()) && isSameSheetNames(firstName, lastName);
&& isSameSheetNames(firstName, lastName); }
} private static boolean isSameSheetNames(NameRecord firstName, NameRecord lastName) {
private boolean isSameSheetNames(NameRecord firstName, NameRecord lastName) return lastName.getSheetNumber() == firstName.getSheetNumber();
{ }
return lastName.getEqualsToIndexToSheet() == firstName.getEqualsToIndexToSheet();
}
public short getIndexToSheet(short num) { public short getIndexToSheet(short num) {

View File

@ -54,18 +54,13 @@ import java.util.Locale;
* @see org.apache.poi.hssf.usermodel.HSSFWorkbook * @see org.apache.poi.hssf.usermodel.HSSFWorkbook
* @version 1.0-pre * @version 1.0-pre
*/ */
public final class Workbook implements Model {
public class Workbook implements Model private static final int DEBUG = POILogger.DEBUG;
{
private static final int DEBUG = POILogger.DEBUG;
// public static Workbook currentBook = null;
/** /**
* constant used to set the "codepage" wherever "codepage" is set in records * constant used to set the "codepage" wherever "codepage" is set in records
* (which is duplciated in more than one record) * (which is duplicated in more than one record)
*/ */
private final static short CODEPAGE = ( short ) 0x4b0; private final static short CODEPAGE = ( short ) 0x4b0;
/** /**
@ -105,8 +100,6 @@ public class Workbook implements Model
private static POILogger log = POILogFactory.getLogger(Workbook.class); private static POILogger log = POILogFactory.getLogger(Workbook.class);
protected static final String EXCEL_REPEATING_NAME_PREFIX_ = "Excel_Name_Record_Titles_";
/** /**
* Creates new Workbook with no intitialization --useless right now * Creates new Workbook with no intitialization --useless right now
* @see #createWorkbook(List) * @see #createWorkbook(List)
@ -250,9 +243,9 @@ public class Workbook implements Model
for ( ; k < recs.size(); k++) { for ( ; k < recs.size(); k++) {
Record rec = ( Record ) recs.get(k); Record rec = ( Record ) recs.get(k);
switch (rec.getSid()) { switch (rec.getSid()) {
case HyperlinkRecord.sid: case HyperlinkRecord.sid:
retval.hyperlinks.add(rec); retval.hyperlinks.add(rec);
break; break;
} }
} }
@ -358,22 +351,22 @@ public class Workbook implements Model
} }
/**Retrieves the Builtin NameRecord that matches the name and index /**Retrieves the Builtin NameRecord that matches the name and index
* There shouldn't be too many names to make the sequential search too slow * There shouldn't be too many names to make the sequential search too slow
* @param name byte representation of the builtin name to match * @param name byte representation of the builtin name to match
* @param sheetIndex Index to match * @param sheetNumber 1-based sheet number
* @return null if no builtin NameRecord matches * @return null if no builtin NameRecord matches
*/ */
public NameRecord getSpecificBuiltinRecord(byte name, int sheetIndex) public NameRecord getSpecificBuiltinRecord(byte name, int sheetNumber)
{ {
return getOrCreateLinkTable().getSpecificBuiltinRecord(name, sheetIndex); return getOrCreateLinkTable().getSpecificBuiltinRecord(name, sheetNumber);
} }
/** /**
* Removes the specified Builtin NameRecord that matches the name and index * Removes the specified Builtin NameRecord that matches the name and index
* @param name byte representation of the builtin to match * @param name byte representation of the builtin to match
* @param sheetIndex zero-based sheet reference * @param sheetIndex zero-based sheet reference
*/ */
public void removeBuiltinRecord(byte name, int sheetIndex) { public void removeBuiltinRecord(byte name, int sheetIndex) {
linkTable.removeBuiltinRecord(name, sheetIndex); linkTable.removeBuiltinRecord(name, sheetIndex);
// TODO - do we need "this.records.remove(...);" similar to that in this.removeName(int namenum) {}? // TODO - do we need "this.records.remove(...);" similar to that in this.removeName(int namenum) {}?
@ -413,18 +406,18 @@ public class Workbook implements Model
* Retrieves the index of the given font * Retrieves the index of the given font
*/ */
public int getFontIndex(FontRecord font) { public int getFontIndex(FontRecord font) {
for(int i=0; i<=numfonts; i++) { for(int i=0; i<=numfonts; i++) {
FontRecord thisFont = FontRecord thisFont =
( FontRecord ) records.get((records.getFontpos() - (numfonts - 1)) + i); ( FontRecord ) records.get((records.getFontpos() - (numfonts - 1)) + i);
if(thisFont == font) { if(thisFont == font) {
// There is no 4! // There is no 4!
if(i > 3) { if(i > 3) {
return (i+1); return (i+1);
} }
return i; return i;
} }
} }
throw new IllegalArgumentException("Could not find that font!"); throw new IllegalArgumentException("Could not find that font!");
} }
/** /**
@ -451,7 +444,7 @@ public class Workbook implements Model
* so you'll need to update those yourself! * so you'll need to update those yourself!
*/ */
public void removeFontRecord(FontRecord rec) { public void removeFontRecord(FontRecord rec) {
records.remove(rec); // this updates FontPos for us records.remove(rec); // this updates FontPos for us
numfonts--; numfonts--;
} }
@ -536,20 +529,20 @@ public class Workbook implements Model
BoundSheetRecord sheet = (BoundSheetRecord)boundsheets.get( sheetnum ); BoundSheetRecord sheet = (BoundSheetRecord)boundsheets.get( sheetnum );
sheet.setSheetname(sheetname); sheet.setSheetname(sheetname);
sheet.setSheetnameLength( (byte)sheetname.length() ); sheet.setSheetnameLength( (byte)sheetname.length() );
sheet.setCompressedUnicodeFlag( (byte)encoding ); sheet.setCompressedUnicodeFlag( (byte)encoding );
} }
/** /**
* sets the order of appearance for a given sheet. * sets the order of appearance for a given sheet.
* *
* @param sheetname the name of the sheet to reorder * @param sheetname the name of the sheet to reorder
* @param pos the position that we want to insert the sheet into (0 based) * @param pos the position that we want to insert the sheet into (0 based)
*/ */
public void setSheetOrder(String sheetname, int pos ) { public void setSheetOrder(String sheetname, int pos ) {
int sheetNumber = getSheetIndex(sheetname); int sheetNumber = getSheetIndex(sheetname);
//remove the sheet that needs to be reordered and place it in the spot we want //remove the sheet that needs to be reordered and place it in the spot we want
boundsheets.add(pos, boundsheets.remove(sheetNumber)); boundsheets.add(pos, boundsheets.remove(sheetNumber));
} }
/** /**
@ -627,11 +620,13 @@ public class Workbook implements Model
} }
} }
public void removeSheet(int sheetnum) { /**
if (boundsheets.size() > sheetnum) { * @param sheetIndex zero based sheet index
records.remove(records.getBspos() - (boundsheets.size() - 1) + sheetnum); */
// records.bspos--; public void removeSheet(int sheetIndex) {
boundsheets.remove(sheetnum); if (boundsheets.size() > sheetIndex) {
records.remove(records.getBspos() - (boundsheets.size() - 1) + sheetIndex);
boundsheets.remove(sheetIndex);
fixTabIdRecord(); fixTabIdRecord();
} }
@ -642,20 +637,18 @@ public class Workbook implements Model
// However, the sheet index must be adjusted, or // However, the sheet index must be adjusted, or
// excel will break. (Sheet index is either 0 for // excel will break. (Sheet index is either 0 for
// global, or 1 based index to sheet) // global, or 1 based index to sheet)
int sheetNum1Based = sheetnum + 1; int sheetNum1Based = sheetIndex + 1;
for(int i=0; i<getNumNames(); i++) { for(int i=0; i<getNumNames(); i++) {
NameRecord nr = getNameRecord(i); NameRecord nr = getNameRecord(i);
if(nr.getIndexToSheet() == sheetNum1Based) { if(nr.getSheetNumber() == sheetNum1Based) {
// Excel re-writes these to point to no sheet // Excel re-writes these to point to no sheet
nr.setEqualsToIndexToSheet((short)0); nr.setSheetNumber(0);
} else if(nr.getIndexToSheet() > sheetNum1Based) { } else if(nr.getSheetNumber() > sheetNum1Based) {
// Bump down by one, so still points // Bump down by one, so still points
// at the same sheet // at the same sheet
nr.setEqualsToIndexToSheet((short)( nr.setSheetNumber(nr.getSheetNumber()-1);
nr.getEqualsToIndexToSheet()-1 }
));
}
} }
} }
@ -721,7 +714,7 @@ public class Workbook implements Model
* so you'll need to update those yourself! * so you'll need to update those yourself!
*/ */
public void removeExFormatRecord(ExtendedFormatRecord rec) { public void removeExFormatRecord(ExtendedFormatRecord rec) {
records.remove(rec); // this updates XfPos for us records.remove(rec); // this updates XfPos for us
numxfs--; numxfs--;
} }
@ -813,9 +806,9 @@ public class Workbook implements Model
// //
// Record record = records.get(k); // Record record = records.get(k);
//// Let's skip RECALCID records, as they are only use for optimization //// Let's skip RECALCID records, as they are only use for optimization
// if(record.getSid() != RecalcIdRecord.sid || ((RecalcIdRecord)record).isNeeded()) { // if(record.getSid() != RecalcIdRecord.sid || ((RecalcIdRecord)record).isNeeded()) {
// pos += record.serialize(pos, retval); // rec.length; // pos += record.serialize(pos, retval); // rec.length;
// } // }
// } // }
// log.log(DEBUG, "Exiting serialize workbook"); // log.log(DEBUG, "Exiting serialize workbook");
// return retval; // return retval;
@ -1821,10 +1814,10 @@ public class Workbook implements Model
// from Russia with love ;) // from Russia with love ;)
if ( Locale.getDefault().toString().equals( "ru_RU" ) ) { if ( Locale.getDefault().toString().equals( "ru_RU" ) ) {
retval.setCurrentCountry(( short ) 7); retval.setCurrentCountry(( short ) 7);
} }
else { else {
retval.setCurrentCountry(( short ) 1); retval.setCurrentCountry(( short ) 1);
} }
return retval; return retval;
@ -1953,7 +1946,7 @@ public class Workbook implements Model
LinkTable linkTable = getOrCreateLinkTable(); LinkTable linkTable = getOrCreateLinkTable();
if(linkTable.nameAlreadyExists(name)) { if(linkTable.nameAlreadyExists(name)) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"You are trying to assign a duplicated name record: " "You are trying to assign a duplicated name record: "
+ name.getNameText()); + name.getNameText());
} }
@ -1964,27 +1957,18 @@ public class Workbook implements Model
/** /**
* Generates a NameRecord to represent a built-in region * Generates a NameRecord to represent a built-in region
* @return a new NameRecord unless the index is invalid * @return a new NameRecord
*/ */
public NameRecord createBuiltInName(byte builtInName, int index) public NameRecord createBuiltInName(byte builtInName, int sheetNumber) {
{ if (sheetNumber < 0 || sheetNumber+1 > Short.MAX_VALUE) {
if (index == -1 || index+1 > Short.MAX_VALUE) throw new IllegalArgumentException("Sheet number ["+sheetNumber+"]is not valid ");
throw new IllegalArgumentException("Index is not valid ["+index+"]"); }
NameRecord name = new NameRecord(builtInName, (short)(index)); NameRecord name = new NameRecord(builtInName, sheetNumber);
String prefix = EXCEL_REPEATING_NAME_PREFIX_ + index + "_";
int cont = 0;
while(linkTable.nameAlreadyExists(name)) { while(linkTable.nameAlreadyExists(name)) {
cont++; throw new RuntimeException("Builtin (" + builtInName
String altNameName = prefix + cont; + ") already exists for sheet (" + sheetNumber + ")");
// It would be better to set a different builtInName here.
// It does not seem possible, so we create it as a
// non built-in name from this point on
name = new NameRecord();
name.setNameText(altNameName);
name.setNameTextLength((byte)altNameName.length());
} }
addName(name); addName(name);
return name; return name;
@ -1992,16 +1976,15 @@ public class Workbook implements Model
/** removes the name /** removes the name
* @param namenum name index * @param nameIndex name index
*/ */
public void removeName(int namenum){ public void removeName(int nameIndex){
if (linkTable.getNumNames() > namenum) { if (linkTable.getNumNames() > nameIndex) {
int idx = findFirstRecordLocBySid(NameRecord.sid); int idx = findFirstRecordLocBySid(NameRecord.sid);
records.remove(idx + namenum); records.remove(idx + nameIndex);
linkTable.removeName(namenum); linkTable.removeName(nameIndex);
} }
} }
/** /**
@ -2011,19 +1994,19 @@ public class Workbook implements Model
* @return the format id of a format that matches or -1 if none found and createIfNotFound * @return the format id of a format that matches or -1 if none found and createIfNotFound
*/ */
public short getFormat(String format, boolean createIfNotFound) { public short getFormat(String format, boolean createIfNotFound) {
Iterator iterator; Iterator iterator;
for (iterator = formats.iterator(); iterator.hasNext();) { for (iterator = formats.iterator(); iterator.hasNext();) {
FormatRecord r = (FormatRecord)iterator.next(); FormatRecord r = (FormatRecord)iterator.next();
if (r.getFormatString().equals(format)) { if (r.getFormatString().equals(format)) {
return r.getIndexCode(); return r.getIndexCode();
} }
} }
if (createIfNotFound) { if (createIfNotFound) {
return createFormat(format); return createFormat(format);
} }
return -1; return -1;
} }
/** /**
@ -2031,7 +2014,7 @@ public class Workbook implements Model
* @return ArrayList of FormatRecords in the notebook * @return ArrayList of FormatRecords in the notebook
*/ */
public ArrayList getFormats() { public ArrayList getFormats() {
return formats; return formats;
} }
/** /**
@ -2043,7 +2026,7 @@ public class Workbook implements Model
*/ */
public short createFormat( String format ) public short createFormat( String format )
{ {
// ++xfpos; //These are to ensure that positions are updated properly // ++xfpos; //These are to ensure that positions are updated properly
// ++palettepos; // ++palettepos;
// ++bspos; // ++bspos;
FormatRecord rec = new FormatRecord(); FormatRecord rec = new FormatRecord();
@ -2113,7 +2096,7 @@ public class Workbook implements Model
public List getHyperlinks() public List getHyperlinks()
{ {
return hyperlinks; return hyperlinks;
} }
public List getRecords() public List getRecords()
@ -2170,54 +2153,54 @@ public class Workbook implements Model
* Finds the primary drawing group, if one already exists * Finds the primary drawing group, if one already exists
*/ */
public void findDrawingGroup() { public void findDrawingGroup() {
// Need to find a DrawingGroupRecord that // Need to find a DrawingGroupRecord that
// contains a EscherDggRecord // contains a EscherDggRecord
for(Iterator rit = records.iterator(); rit.hasNext();) { for(Iterator rit = records.iterator(); rit.hasNext();) {
Record r = (Record)rit.next(); Record r = (Record)rit.next();
if(r instanceof DrawingGroupRecord) { if(r instanceof DrawingGroupRecord) {
DrawingGroupRecord dg = (DrawingGroupRecord)r; DrawingGroupRecord dg = (DrawingGroupRecord)r;
dg.processChildRecords(); dg.processChildRecords();
EscherContainerRecord cr = EscherContainerRecord cr =
dg.getEscherContainer(); dg.getEscherContainer();
if(cr == null) { if(cr == null) {
continue; continue;
} }
EscherDggRecord dgg = null; EscherDggRecord dgg = null;
for(Iterator it = cr.getChildRecords().iterator(); it.hasNext();) { for(Iterator it = cr.getChildRecords().iterator(); it.hasNext();) {
Object er = it.next(); Object er = it.next();
if(er instanceof EscherDggRecord) { if(er instanceof EscherDggRecord) {
dgg = (EscherDggRecord)er; dgg = (EscherDggRecord)er;
} }
} }
if(dgg != null) { if(dgg != null) {
drawingManager = new DrawingManager2(dgg); drawingManager = new DrawingManager2(dgg);
return; return;
} }
} }
} }
// Look for the DrawingGroup record // Look for the DrawingGroup record
int dgLoc = findFirstRecordLocBySid(DrawingGroupRecord.sid); int dgLoc = findFirstRecordLocBySid(DrawingGroupRecord.sid);
// If there is one, does it have a EscherDggRecord? // If there is one, does it have a EscherDggRecord?
if(dgLoc != -1) { if(dgLoc != -1) {
DrawingGroupRecord dg = DrawingGroupRecord dg =
(DrawingGroupRecord)records.get(dgLoc); (DrawingGroupRecord)records.get(dgLoc);
EscherDggRecord dgg = null; EscherDggRecord dgg = null;
for(Iterator it = dg.getEscherRecords().iterator(); it.hasNext();) { for(Iterator it = dg.getEscherRecords().iterator(); it.hasNext();) {
Object er = it.next(); Object er = it.next();
if(er instanceof EscherDggRecord) { if(er instanceof EscherDggRecord) {
dgg = (EscherDggRecord)er; dgg = (EscherDggRecord)er;
} }
} }
if(dgg != null) { if(dgg != null) {
drawingManager = new DrawingManager2(dgg); drawingManager = new DrawingManager2(dgg);
} }
} }
} }
@ -2379,7 +2362,7 @@ public class Workbook implements Model
*/ */
public boolean isWriteProtected() { public boolean isWriteProtected() {
if (this.fileShare == null) { if (this.fileShare == null) {
return false; return false;
} }
FileSharingRecord frec = getFileSharing(); FileSharingRecord frec = getFileSharing();
return (frec.getReadOnly() == 1); return (frec.getReadOnly() == 1);

File diff suppressed because it is too large Load Diff

View File

@ -61,6 +61,9 @@ import java.util.Stack;
*/ */
public class HSSFWorkbook extends POIDocument public class HSSFWorkbook extends POIDocument
{ {
private static final int MAX_ROW = 0xFFFF;
private static final short MAX_COLUMN = (short)0x00FF;
private static final int DEBUG = POILogger.DEBUG; private static final int DEBUG = POILogger.DEBUG;
/** /**
@ -835,7 +838,8 @@ public class HSSFWorkbook extends POIDocument
/** /**
* Sets the repeating rows and columns for a sheet (as found in * Sets the repeating rows and columns for a sheet (as found in
* File->PageSetup->Sheet). This is function is included in the workbook * 2003:File->PageSetup->Sheet, 2007:Page Layout->Print Titles).
* This is function is included in the workbook
* because it creates/modifies name records which are stored at the * because it creates/modifies name records which are stored at the
* workbook level. * workbook level.
* <p> * <p>
@ -865,10 +869,10 @@ public class HSSFWorkbook extends POIDocument
// Check arguments // Check arguments
if (startColumn == -1 && endColumn != -1) throw new IllegalArgumentException("Invalid column range specification"); if (startColumn == -1 && endColumn != -1) throw new IllegalArgumentException("Invalid column range specification");
if (startRow == -1 && endRow != -1) throw new IllegalArgumentException("Invalid row range specification"); if (startRow == -1 && endRow != -1) throw new IllegalArgumentException("Invalid row range specification");
if (startColumn < -1 || startColumn >= 0xFF) throw new IllegalArgumentException("Invalid column range specification"); if (startColumn < -1 || startColumn >= MAX_COLUMN) throw new IllegalArgumentException("Invalid column range specification");
if (endColumn < -1 || endColumn >= 0xFF) throw new IllegalArgumentException("Invalid column range specification"); if (endColumn < -1 || endColumn >= MAX_COLUMN) throw new IllegalArgumentException("Invalid column range specification");
if (startRow < -1 || startRow > 65535) throw new IllegalArgumentException("Invalid row range specification"); if (startRow < -1 || startRow > MAX_ROW) throw new IllegalArgumentException("Invalid row range specification");
if (endRow < -1 || endRow > 65535) throw new IllegalArgumentException("Invalid row range specification"); if (endRow < -1 || endRow > MAX_ROW) throw new IllegalArgumentException("Invalid row range specification");
if (startColumn > endColumn) throw new IllegalArgumentException("Invalid column range specification"); if (startColumn > endColumn) throw new IllegalArgumentException("Invalid column range specification");
if (startRow > endRow) throw new IllegalArgumentException("Invalid row range specification"); if (startRow > endRow) throw new IllegalArgumentException("Invalid row range specification");
@ -880,50 +884,60 @@ public class HSSFWorkbook extends POIDocument
boolean removingRange = boolean removingRange =
startColumn == -1 && endColumn == -1 && startRow == -1 && endRow == -1; startColumn == -1 && endColumn == -1 && startRow == -1 && endRow == -1;
boolean isNewRecord = false; int rowColHeaderNameIndex = findExistingRowColHeaderNameRecordIdx(sheetIndex);
NameRecord nameRecord; if (removingRange) {
nameRecord = findExistingRowColHeaderNameRecord(sheetIndex); if (rowColHeaderNameIndex >= 0) {
if (removingRange ) workbook.removeName(rowColHeaderNameIndex);
{ }
if (nameRecord != null)
workbook.removeName(findExistingRowColHeaderNameRecordIdx(sheetIndex+1));
return; return;
} }
if ( nameRecord == null ) boolean isNewRecord;
{ NameRecord nameRecord;
nameRecord = workbook.createBuiltInName(NameRecord.BUILTIN_PRINT_TITLE, sheetIndex+1); if (rowColHeaderNameIndex < 0) {
//does a lot of the house keeping for builtin records, like setting lengths to zero etc //does a lot of the house keeping for builtin records, like setting lengths to zero etc
nameRecord = workbook.createBuiltInName(NameRecord.BUILTIN_PRINT_TITLE, sheetIndex+1);
isNewRecord = true; isNewRecord = true;
} else {
nameRecord = workbook.getNameRecord(rowColHeaderNameIndex);
isNewRecord = false;
} }
short definitionTextLength = settingRowAndColumn ? (short)0x001a : (short)0x000b; short definitionTextLength = settingRowAndColumn ? (short)0x001a : (short)0x000b;
nameRecord.setDefinitionTextLength(definitionTextLength); nameRecord.setDefinitionTextLength(definitionTextLength); // TODO - remove
Stack ptgs = new Stack(); Stack ptgs = new Stack();
if (settingRowAndColumn) if (settingRowAndColumn) {
{ final int exprsSize = 2 * 11 + 1; // Area3DPtg.SIZE + UnionPtg.SIZE
ptgs.add(new MemFuncPtg(23)); // TODO - where did constant '23' come from? ptgs.add(new MemFuncPtg(exprsSize));
} }
if (startColumn >= 0) if (startColumn >= 0)
{ {
Area3DPtg area3DPtg1 = new Area3DPtg(); Area3DPtg colArea = new Area3DPtg();
area3DPtg1.setExternSheetIndex(externSheetIndex); colArea.setExternSheetIndex(externSheetIndex);
area3DPtg1.setFirstColumn((short)startColumn); colArea.setFirstColumn((short)startColumn);
area3DPtg1.setLastColumn((short)endColumn); colArea.setLastColumn((short)endColumn);
area3DPtg1.setFirstRow((short)0); colArea.setFirstRow(0);
area3DPtg1.setLastRow((short)0xFFFF); colArea.setLastRow(MAX_ROW);
ptgs.add(area3DPtg1); colArea.setFirstColRelative(false);
colArea.setLastColRelative(false);
colArea.setFirstRowRelative(false);
colArea.setLastRowRelative(false);
ptgs.add(colArea);
} }
if (startRow >= 0) if (startRow >= 0)
{ {
Area3DPtg area3DPtg2 = new Area3DPtg(); Area3DPtg rowArea = new Area3DPtg();
area3DPtg2.setExternSheetIndex(externSheetIndex); rowArea.setExternSheetIndex(externSheetIndex);
area3DPtg2.setFirstColumn((short)0); rowArea.setFirstColumn((short)0);
area3DPtg2.setLastColumn((short)0x00FF); rowArea.setLastColumn(MAX_COLUMN);
area3DPtg2.setFirstRow((short)startRow); rowArea.setFirstRow(startRow);
area3DPtg2.setLastRow((short)endRow); rowArea.setLastRow(endRow);
ptgs.add(area3DPtg2); rowArea.setFirstColRelative(false);
rowArea.setLastColRelative(false);
rowArea.setFirstRowRelative(false);
rowArea.setLastRowRelative(false);
ptgs.add(rowArea);
} }
if (settingRowAndColumn) if (settingRowAndColumn)
{ {
@ -943,38 +957,31 @@ public class HSSFWorkbook extends POIDocument
sheet.setActive(true); sheet.setActive(true);
} }
private NameRecord findExistingRowColHeaderNameRecord( int sheetIndex )
{
int index = findExistingRowColHeaderNameRecordIdx(sheetIndex);
if (index == -1)
return null;
else
return (NameRecord)workbook.findNextRecordBySid(NameRecord.sid, index);
}
private int findExistingRowColHeaderNameRecordIdx( int sheetIndex ) private int findExistingRowColHeaderNameRecordIdx(int sheetIndex) {
{ for(int defNameIndex =0; defNameIndex<names.size(); defNameIndex++) {
int index = 0; NameRecord r = workbook.getNameRecord(defNameIndex);
NameRecord r = null; if (r == null) {
while ((r = (NameRecord) workbook.findNextRecordBySid(NameRecord.sid, index)) != null) throw new RuntimeException("Unable to find all defined names to iterate over");
{ }
int indexToSheet = r.getEqualsToIndexToSheet() -1; if (!isRowColHeaderRecord( r )) {
if(indexToSheet > -1) { //ignore "GLOBAL" name records continue;
int nameRecordSheetIndex = workbook.getSheetIndexFromExternSheetIndex(indexToSheet); }
if (isRowColHeaderRecord( r ) && nameRecordSheetIndex == sheetIndex) if(r.getSheetNumber() == 0) {
{ //ignore "GLOBAL" name records
return index; continue;
} }
int externIndex = r.getSheetNumber() -1;
int nameRecordSheetIndex = workbook.getSheetIndexFromExternSheetIndex(externIndex);
if (nameRecordSheetIndex == sheetIndex) {
return defNameIndex;
} }
index++;
} }
return -1; return -1;
} }
private boolean isRowColHeaderRecord( NameRecord r ) private static boolean isRowColHeaderRecord(NameRecord r) {
{ return r.isBuiltInName() && r.getBuiltInName() == NameRecord.BUILTIN_PRINT_TITLE;
return r.getOptionFlag() == 0x20 && ("" + ((char)7)).equals(r.getNameText());
} }
/** /**
@ -1068,7 +1075,7 @@ public class HSSFWorkbook extends POIDocument
* and that's not something you should normally do * and that's not something you should normally do
*/ */
protected void resetFontCache() { protected void resetFontCache() {
fonts = new Hashtable(); fonts = new Hashtable();
} }
/** /**

View File

@ -1013,7 +1013,7 @@ public final class TestBugs extends TestCase {
Workbook w = wb.getWorkbook(); Workbook w = wb.getWorkbook();
for(int i=0; i<w.getNumNames(); i++) { for(int i=0; i<w.getNumNames(); i++) {
NameRecord r = w.getNameRecord(i); NameRecord r = w.getNameRecord(i);
assertTrue(r.getIndexToSheet() <= wb.getNumberOfSheets()); assertTrue(r.getSheetNumber() <= wb.getNumberOfSheets());
List nd = r.getNameDefinition(); List nd = r.getNameDefinition();
assertEquals(1, nd.size()); assertEquals(1, nd.size());
@ -1031,7 +1031,7 @@ public final class TestBugs extends TestCase {
for(int i=0; i<w.getNumNames(); i++) { for(int i=0; i<w.getNumNames(); i++) {
NameRecord r = w.getNameRecord(i); NameRecord r = w.getNameRecord(i);
assertTrue(r.getIndexToSheet() <= wb.getNumberOfSheets()); assertTrue(r.getSheetNumber() <= wb.getNumberOfSheets());
List nd = r.getNameDefinition(); List nd = r.getNameDefinition();
assertEquals(1, nd.size()); assertEquals(1, nd.size());
@ -1048,7 +1048,7 @@ public final class TestBugs extends TestCase {
for(int i=0; i<w.getNumNames(); i++) { for(int i=0; i<w.getNumNames(); i++) {
NameRecord r = w.getNameRecord(i); NameRecord r = w.getNameRecord(i);
assertTrue(r.getIndexToSheet() <= wb.getNumberOfSheets()); assertTrue(r.getSheetNumber() <= wb.getNumberOfSheets());
List nd = r.getNameDefinition(); List nd = r.getNameDefinition();
assertEquals(1, nd.size()); assertEquals(1, nd.size());

View File

@ -50,7 +50,7 @@ public final class TestHSSFWorkbook extends TestCase {
b.createSheet(); b.createSheet();
b.setRepeatingRowsAndColumns( 2, 0,1,-1,-1 ); b.setRepeatingRowsAndColumns( 2, 0,1,-1,-1 );
NameRecord nameRecord = b.getWorkbook().getNameRecord( 0 ); NameRecord nameRecord = b.getWorkbook().getNameRecord( 0 );
assertEquals( 3, nameRecord.getIndexToSheet() ); assertEquals(3, nameRecord.getSheetNumber());
} }
public void testCaseInsensitiveNames() { public void testCaseInsensitiveNames() {
@ -411,84 +411,84 @@ public final class TestHSSFWorkbook extends TestCase {
* that point to deleted sheets * that point to deleted sheets
*/ */
public void testNamesToDeleteSheets() throws Exception { public void testNamesToDeleteSheets() throws Exception {
HSSFWorkbook b = openSample("30978-deleted.xls"); HSSFWorkbook b = openSample("30978-deleted.xls");
assertEquals(3, b.getNumberOfNames()); assertEquals(3, b.getNumberOfNames());
// Sheet 2 is deleted // Sheet 2 is deleted
assertEquals("Sheet1", b.getSheetName(0)); assertEquals("Sheet1", b.getSheetName(0));
assertEquals("Sheet3", b.getSheetName(1)); assertEquals("Sheet3", b.getSheetName(1));
Area3DPtg ptg; Area3DPtg ptg;
NameRecord nr; NameRecord nr;
HSSFName n; HSSFName n;
/* ======= Name pointing to deleted sheet ====== */ /* ======= Name pointing to deleted sheet ====== */
// First at low level // First at low level
nr = b.getWorkbook().getNameRecord(0); nr = b.getWorkbook().getNameRecord(0);
assertEquals("On2", nr.getNameText()); assertEquals("On2", nr.getNameText());
assertEquals(0, nr.getIndexToSheet()); assertEquals(0, nr.getSheetNumber());
assertEquals(1, nr.getExternSheetNumber()); assertEquals(1, nr.getExternSheetNumber());
assertEquals(1, nr.getNameDefinition().size()); assertEquals(1, nr.getNameDefinition().size());
ptg = (Area3DPtg)nr.getNameDefinition().get(0); ptg = (Area3DPtg)nr.getNameDefinition().get(0);
assertEquals(1, ptg.getExternSheetIndex()); assertEquals(1, ptg.getExternSheetIndex());
assertEquals(0, ptg.getFirstColumn()); assertEquals(0, ptg.getFirstColumn());
assertEquals(0, ptg.getFirstRow()); assertEquals(0, ptg.getFirstRow());
assertEquals(0, ptg.getLastColumn()); assertEquals(0, ptg.getLastColumn());
assertEquals(2, ptg.getLastRow()); assertEquals(2, ptg.getLastRow());
// Now at high level // Now at high level
n = b.getNameAt(0); n = b.getNameAt(0);
assertEquals("On2", n.getNameName()); assertEquals("On2", n.getNameName());
assertEquals("", n.getSheetName()); assertEquals("", n.getSheetName());
assertEquals("#REF!$A$1:$A$3", n.getReference()); assertEquals("#REF!$A$1:$A$3", n.getReference());
/* ======= Name pointing to 1st sheet ====== */ /* ======= Name pointing to 1st sheet ====== */
// First at low level // First at low level
nr = b.getWorkbook().getNameRecord(1); nr = b.getWorkbook().getNameRecord(1);
assertEquals("OnOne", nr.getNameText()); assertEquals("OnOne", nr.getNameText());
assertEquals(0, nr.getIndexToSheet()); assertEquals(0, nr.getSheetNumber());
assertEquals(0, nr.getExternSheetNumber()); assertEquals(0, nr.getExternSheetNumber());
assertEquals(1, nr.getNameDefinition().size()); assertEquals(1, nr.getNameDefinition().size());
ptg = (Area3DPtg)nr.getNameDefinition().get(0); ptg = (Area3DPtg)nr.getNameDefinition().get(0);
assertEquals(0, ptg.getExternSheetIndex()); assertEquals(0, ptg.getExternSheetIndex());
assertEquals(0, ptg.getFirstColumn()); assertEquals(0, ptg.getFirstColumn());
assertEquals(2, ptg.getFirstRow()); assertEquals(2, ptg.getFirstRow());
assertEquals(0, ptg.getLastColumn()); assertEquals(0, ptg.getLastColumn());
assertEquals(3, ptg.getLastRow()); assertEquals(3, ptg.getLastRow());
// Now at high level // Now at high level
n = b.getNameAt(1); n = b.getNameAt(1);
assertEquals("OnOne", n.getNameName()); assertEquals("OnOne", n.getNameName());
assertEquals("Sheet1", n.getSheetName()); assertEquals("Sheet1", n.getSheetName());
assertEquals("Sheet1!$A$3:$A$4", n.getReference()); assertEquals("Sheet1!$A$3:$A$4", n.getReference());
/* ======= Name pointing to 3rd sheet ====== */ /* ======= Name pointing to 3rd sheet ====== */
// First at low level // First at low level
nr = b.getWorkbook().getNameRecord(2); nr = b.getWorkbook().getNameRecord(2);
assertEquals("OnSheet3", nr.getNameText()); assertEquals("OnSheet3", nr.getNameText());
assertEquals(0, nr.getIndexToSheet()); assertEquals(0, nr.getSheetNumber());
assertEquals(2, nr.getExternSheetNumber()); assertEquals(2, nr.getExternSheetNumber());
assertEquals(1, nr.getNameDefinition().size()); assertEquals(1, nr.getNameDefinition().size());
ptg = (Area3DPtg)nr.getNameDefinition().get(0); ptg = (Area3DPtg)nr.getNameDefinition().get(0);
assertEquals(2, ptg.getExternSheetIndex()); assertEquals(2, ptg.getExternSheetIndex());
assertEquals(0, ptg.getFirstColumn()); assertEquals(0, ptg.getFirstColumn());
assertEquals(0, ptg.getFirstRow()); assertEquals(0, ptg.getFirstRow());
assertEquals(0, ptg.getLastColumn()); assertEquals(0, ptg.getLastColumn());
assertEquals(1, ptg.getLastRow()); assertEquals(1, ptg.getLastRow());
// Now at high level // Now at high level
n = b.getNameAt(2); n = b.getNameAt(2);
assertEquals("OnSheet3", n.getNameName()); assertEquals("OnSheet3", n.getNameName());
assertEquals("Sheet3", n.getSheetName()); assertEquals("Sheet3", n.getSheetName());
assertEquals("Sheet3!$A$1:$A$2", n.getReference()); assertEquals("Sheet3!$A$1:$A$2", n.getReference());
} }
/** /**
@ -519,12 +519,12 @@ public final class TestHSSFWorkbook extends TestCase {
* The sample file provided with bug 45582 seems to have one extra byte after the EOFRecord * The sample file provided with bug 45582 seems to have one extra byte after the EOFRecord
*/ */
public void testExtraDataAfterEOFRecord() { public void testExtraDataAfterEOFRecord() {
try { try {
HSSFTestDataSamples.openSampleWorkbook("ex45582-22397.xls"); HSSFTestDataSamples.openSampleWorkbook("ex45582-22397.xls");
} catch (RecordFormatException e) { } catch (RecordFormatException e) {
if (e.getCause() instanceof LittleEndian.BufferUnderrunException) { if (e.getCause() instanceof LittleEndian.BufferUnderrunException) {
throw new AssertionFailedError("Identified bug 45582"); throw new AssertionFailedError("Identified bug 45582");
} }
} }
} }
} }

View File

@ -17,17 +17,15 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.util.AreaReference; import org.apache.poi.hssf.util.AreaReference;
import org.apache.poi.hssf.util.CellReference; import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
/** /**
* *
@ -42,10 +40,6 @@ public final class TestNamedRange extends TestCase {
return HSSFTestDataSamples.openSampleWorkbook(sampleFileName); return HSSFTestDataSamples.openSampleWorkbook(sampleFileName);
} }
public static void main(String[] args) {
junit.textui.TestRunner.run(TestNamedRange.class);
}
/** Test of TestCase method, of class test.RangeTest. */ /** Test of TestCase method, of class test.RangeTest. */
public void testNamedRange() { public void testNamedRange() {
HSSFWorkbook wb = openSample("Simple.xls"); HSSFWorkbook wb = openSample("Simple.xls");
@ -411,7 +405,7 @@ public final class TestNamedRange extends TestCase {
String cellValue = "TEST Value"; String cellValue = "TEST Value";
HSSFWorkbook wb = new HSSFWorkbook(); HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet(sheetName); HSSFSheet sheet = wb.createSheet(sheetName);
sheet.createRow(0).createCell((short) 0).setCellValue(cellValue); sheet.createRow(0).createCell(0).setCellValue(new HSSFRichTextString(cellValue));
// create named range for a single cell using areareference // create named range for a single cell using areareference
HSSFName namedCell = wb.createName(); HSSFName namedCell = wb.createName();
@ -447,7 +441,7 @@ public final class TestNamedRange extends TestCase {
String sname = "TestSheet", cname = "TestName", cvalue = "TestVal"; String sname = "TestSheet", cname = "TestName", cvalue = "TestVal";
HSSFWorkbook wb = new HSSFWorkbook(); HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet(sname); HSSFSheet sheet = wb.createSheet(sname);
sheet.createRow(0).createCell((short) 0).setCellValue(cvalue); sheet.createRow(0).createCell(0).setCellValue(new HSSFRichTextString(cvalue));
// create named range for a single cell using cellreference // create named range for a single cell using cellreference
HSSFName namedCell = wb.createName(); HSSFName namedCell = wb.createName();
@ -492,56 +486,60 @@ public final class TestNamedRange extends TestCase {
} }
} }
public void testRepeatingRowsAndColumsNames() throws Exception { public void testRepeatingRowsAndColumsNames() {
// First test that setting RR&C for same sheet more than once only creates a
// single Print_Titles built-in record
HSSFWorkbook wb = new HSSFWorkbook(); HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet(); HSSFSheet sheet = wb.createSheet("FirstSheet");
for (int rowItem = 0; rowItem < 10; rowItem++) { // set repeating rows and columns twice for the first sheet
HSSFRow r = sheet.createRow(rowItem); for (int i = 0; i < 2; i++) {
for (int column = 0; column < 2; column++) { wb.setRepeatingRowsAndColumns(0, 0, 0, 0, 3-1);
HSSFCell cellItem = r.createCell((short) column); sheet.createFreezePane(0, 3);
cellItem.setCellType(HSSFCell.CELL_TYPE_STRING); }
cellItem.setCellValue(new HSSFRichTextString("Some value here")); assertEquals(1, wb.getNumberOfNames());
if (rowItem == 2) { HSSFName nr1 = wb.getNameAt(0);
wb.setRepeatingRowsAndColumns(0, 0, 0, 0, 3 - 1);
sheet.createFreezePane(0, 3); assertEquals("Print_Titles", nr1.getNameName());
} if (false) {
} // TODO - full column references not rendering properly, absolute markers not present either
assertEquals("FirstSheet!$A:$A,FirstSheet!$1:$3", nr1.getReference());
} else {
assertEquals("FirstSheet!A:A,FirstSheet!$A$1:$IV$3", nr1.getReference());
} }
assertEquals(2, wb.getNumberOfNames()); // Save and re-open
HSSFName nr1 = wb.getNameAt(0); HSSFWorkbook nwb = HSSFTestDataSamples.writeOutAndReadBack(wb);
HSSFName nr2 = wb.getNameAt(1);
assertEquals(1, nwb.getNumberOfNames());
nr1 = nwb.getNameAt(0);
assertEquals("Print_Titles", nr1.getNameName()); assertEquals("Print_Titles", nr1.getNameName());
assertEquals("Sheet0!$A$1:$A$0,Sheet0!$A$1:$IV$3", nr1.getReference()); assertEquals("FirstSheet!A:A,FirstSheet!$A$1:$IV$3", nr1.getReference());
assertEquals("Excel_Name_Record_Titles_1_1", nr2.getNameName()); // check that setting RR&C on a second sheet causes a new Print_Titles built-in
assertEquals("Sheet0!$A$1:$A$0,Sheet0!$A$1:$IV$3", nr2.getReference()); // name to be created
sheet = nwb.createSheet("SecondSheet");
// Save and re-open nwb.setRepeatingRowsAndColumns(1, 1, 2, 0, 0);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
wb.write(baos);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
HSSFWorkbook nwb = new HSSFWorkbook(new POIFSFileSystem(bais));
assertEquals(2, nwb.getNumberOfNames()); assertEquals(2, nwb.getNumberOfNames());
nr1 = nwb.getNameAt(0); HSSFName nr2 = nwb.getNameAt(1);
nr2 = nwb.getNameAt(1);
// TODO - assertEquals("Print_Titles", nr2.getNameName());
// should these references really have been corrected? assertEquals("SecondSheet!B:C,SecondSheet!$A$1:$IV$1", nr2.getReference());
// and if so, why not also above?
assertEquals("Print_Titles", nr1.getNameName());
assertEquals("Sheet0!A:A,Sheet0!$A$1:$IV$3", nr1.getReference());
assertEquals("Excel_Name_Record_Titles_1_1", nr2.getNameName()); if (false) {
assertEquals("Sheet0!A:A,Sheet0!$A$1:$IV$3", nr2.getReference()); // In case you fancy checking in excel, to ensure it
// won't complain about the file now
// In case you fancy checking in excel, to ensure it try {
// won't complain about the file now File tempFile = File.createTempFile("POI-45126-", ".xls");
FileOutputStream fout = new FileOutputStream(File.createTempFile("POI-45126-", ".xls")); FileOutputStream fout = new FileOutputStream(tempFile);
wb.write(fout); nwb.write(fout);
fout.close(); fout.close();
System.out.println("check out " + tempFile.getAbsolutePath());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
} }
} }