]> source.dussan.org Git - poi.git/commitdiff
Refinements to fix for bug 45126. Excel does not produce any records like 'Excel_Nam...
authorJosh Micich <josh@apache.org>
Mon, 11 Aug 2008 21:24:19 +0000 (21:24 +0000)
committerJosh Micich <josh@apache.org>
Mon, 11 Aug 2008 21:24:19 +0000 (21:24 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@684938 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/hssf/model/LinkTable.java
src/java/org/apache/poi/hssf/model/Workbook.java
src/java/org/apache/poi/hssf/record/NameRecord.java
src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java
src/testcases/org/apache/poi/hssf/usermodel/TestNamedRange.java

index 1d8781d9713dc1e91939a031aa24b4ea88d574d3..7367d08c2a10ddc86ed0b6fc28f37dc2d177b9d7 100755 (executable)
@@ -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();
                while (iterator.hasNext()) {
                        NameRecord record = ( NameRecord ) iterator.next();
 
                        //print areas are one based
-                       if (record.getBuiltInName() == name && record.getIndexToSheet() == sheetIndex) {
+                       if (record.getBuiltInName() == builtInCode && record.getSheetNumber() == sheetNumber) {
                                return record;
                        }
                }
@@ -241,33 +245,31 @@ final class LinkTable {
                _definedNames.remove(namenum);
        }
 
-    /**
-     * checks if the given name is already included in the linkTable
-     */
-    public boolean nameAlreadyExists(NameRecord name)
-    {
-       // Check to ensure no other names have the same case-insensitive name
-       for ( int i = getNumNames()-1; i >=0; i-- ) {
-               NameRecord rec = getNameRecord(i);
-               if (rec != name) {
-                       if (isDuplicatedNames(name, rec))
-                               return true;
-               }
-       }
-       return false;
-    }
-    
-    private boolean isDuplicatedNames(NameRecord firstName, NameRecord lastName)
-    {
-       return lastName.getNameText().equalsIgnoreCase(firstName.getNameText()) 
-               && isSameSheetNames(firstName, lastName);
-    }
-    private boolean isSameSheetNames(NameRecord firstName, NameRecord lastName)
-    {
-       return lastName.getEqualsToIndexToSheet() == firstName.getEqualsToIndexToSheet();
-    }
-
-    
+       /**
+        * checks if the given name is already included in the linkTable
+        */
+       public boolean nameAlreadyExists(NameRecord name)
+       {
+               // Check to ensure no other names have the same case-insensitive name
+               for ( int i = getNumNames()-1; i >=0; i-- ) {
+                       NameRecord rec = getNameRecord(i);
+                       if (rec != name) {
+                               if (isDuplicatedNames(name, rec))
+                                       return true;
+                       }
+               }
+               return false;
+       }
+       
+       private static boolean isDuplicatedNames(NameRecord firstName, NameRecord lastName) {
+               return lastName.getNameText().equalsIgnoreCase(firstName.getNameText()) 
+                       && isSameSheetNames(firstName, lastName);
+       }
+       private static boolean isSameSheetNames(NameRecord firstName, NameRecord lastName) {
+               return lastName.getSheetNumber() == firstName.getSheetNumber();
+       }
+
+       
        public short getIndexToSheet(short num) {
                return _externSheetRecord.getREFRecordAt(num).getIndexToFirstSupBook();
        }
index f80c41661d8ad6755fa9ea523e4923417473ce80..12c5f90ec38fdb41f2ec3bf109f44dc959009963 100644 (file)
@@ -54,18 +54,13 @@ import java.util.Locale;
  * @see org.apache.poi.hssf.usermodel.HSSFWorkbook
  * @version 1.0-pre
  */
-
-public class Workbook implements Model
-{
-    private static final int   DEBUG       = POILogger.DEBUG;
-
-//    public static Workbook currentBook = null;
+public final class Workbook implements Model {
+       private static final int   DEBUG       = POILogger.DEBUG;
 
     /**
      * 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;
 
     /**
@@ -105,8 +100,6 @@ public class Workbook implements Model
 
     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
      * @see #createWorkbook(List)
@@ -250,9 +243,9 @@ public class Workbook implements Model
         for ( ; k < recs.size(); k++) {
             Record rec = ( Record ) recs.get(k);
             switch (rec.getSid()) {
-               case HyperlinkRecord.sid:
-                       retval.hyperlinks.add(rec);
-                       break;
+                case HyperlinkRecord.sid:
+                    retval.hyperlinks.add(rec);
+                    break;
             }
         }
         
@@ -358,22 +351,22 @@ public class Workbook implements Model
     }
 
 
-       /**Retrieves the Builtin NameRecord that matches the name and index
-        * 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 sheetIndex Index to match
-        * @return null if no builtin NameRecord matches
-        */
-    public NameRecord getSpecificBuiltinRecord(byte name, int sheetIndex)
+    /**Retrieves the Builtin NameRecord that matches the name and index
+     * 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 sheetNumber 1-based sheet number
+     * @return null if no builtin NameRecord matches
+     */
+    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
-        * @param name byte representation of the builtin to match
-        * @param sheetIndex zero-based sheet reference
-        */
+    /**
+     * Removes the specified Builtin NameRecord that matches the name and index
+     * @param name byte representation of the builtin to match
+     * @param sheetIndex zero-based sheet reference
+     */
     public void removeBuiltinRecord(byte name, int sheetIndex) {
         linkTable.removeBuiltinRecord(name, sheetIndex);
         // 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
      */
     public int getFontIndex(FontRecord font) {
-       for(int i=0; i<=numfonts; i++) {
+        for(int i=0; i<=numfonts; i++) {
             FontRecord thisFont =
                 ( FontRecord ) records.get((records.getFontpos() - (numfonts - 1)) + i);
             if(thisFont == font) {
-               // There is no 4!
-               if(i > 3) {
-                       return (i+1);
-               }
-               return i;
+                // There is no 4!
+                if(i > 3) {
+                    return (i+1);
+                }
+                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!
      */
     public void removeFontRecord(FontRecord rec) {
-       records.remove(rec); // this updates FontPos for us
+        records.remove(rec); // this updates FontPos for us
         numfonts--;
     }
 
@@ -536,20 +529,20 @@ public class Workbook implements Model
         BoundSheetRecord sheet = (BoundSheetRecord)boundsheets.get( sheetnum );
         sheet.setSheetname(sheetname);
         sheet.setSheetnameLength( (byte)sheetname.length() );
-               sheet.setCompressedUnicodeFlag( (byte)encoding );
+        sheet.setCompressedUnicodeFlag( (byte)encoding );
     }
     
     /**
-        * sets the order of appearance for a given sheet.
-        *
-        * @param sheetname the name of the sheet to reorder
-        * @param pos the position that we want to insert the sheet into (0 based)
-        */
+     * sets the order of appearance for a given sheet.
+     *
+     * @param sheetname the name of the sheet to reorder
+     * @param pos the position that we want to insert the sheet into (0 based)
+     */
     
     public void setSheetOrder(String sheetname, int pos ) {
-       int sheetNumber = getSheetIndex(sheetname);
-       //remove the sheet that needs to be reordered and place it in the spot we want
-       boundsheets.add(pos, boundsheets.remove(sheetNumber));  
+    int sheetNumber = getSheetIndex(sheetname);
+    //remove the sheet that needs to be reordered and place it in the spot we want
+    boundsheets.add(pos, boundsheets.remove(sheetNumber));    
     }
 
     /**
@@ -627,11 +620,13 @@ public class Workbook implements Model
         }
     }
 
-    public void removeSheet(int sheetnum) {
-        if (boundsheets.size() > sheetnum) {
-            records.remove(records.getBspos() - (boundsheets.size() - 1) + sheetnum);
-//            records.bspos--;
-            boundsheets.remove(sheetnum);
+    /**
+     * @param sheetIndex zero based sheet index
+     */
+    public void removeSheet(int sheetIndex) {
+        if (boundsheets.size() > sheetIndex) {
+            records.remove(records.getBspos() - (boundsheets.size() - 1) + sheetIndex);
+            boundsheets.remove(sheetIndex);
             fixTabIdRecord();
         }
         
@@ -642,20 +637,18 @@ public class Workbook implements Model
         // However, the sheet index must be adjusted, or
         //  excel will break. (Sheet index is either 0 for
         //  global, or 1 based index to sheet)
-        int sheetNum1Based = sheetnum + 1;
+        int sheetNum1Based = sheetIndex + 1;
         for(int i=0; i<getNumNames(); i++) {
-               NameRecord nr = getNameRecord(i);
-               
-               if(nr.getIndexToSheet() == sheetNum1Based) {
-                       // Excel re-writes these to point to no sheet
-                       nr.setEqualsToIndexToSheet((short)0);
-               } else if(nr.getIndexToSheet() > sheetNum1Based) {
-                       // Bump down by one, so still points
-                       //  at the same sheet
-                       nr.setEqualsToIndexToSheet((short)(
-                                       nr.getEqualsToIndexToSheet()-1
-                       ));
-               }
+            NameRecord nr = getNameRecord(i);
+            
+            if(nr.getSheetNumber() == sheetNum1Based) {
+                // Excel re-writes these to point to no sheet
+                nr.setSheetNumber(0);
+            } else if(nr.getSheetNumber() > sheetNum1Based) {
+                // Bump down by one, so still points
+                //  at the same sheet
+                nr.setSheetNumber(nr.getSheetNumber()-1);
+            }
         }
     }
 
@@ -721,7 +714,7 @@ public class Workbook implements Model
      *  so you'll need to update those yourself!
      */
     public void removeExFormatRecord(ExtendedFormatRecord rec) {
-       records.remove(rec); // this updates XfPos for us
+        records.remove(rec); // this updates XfPos for us
         numxfs--;
     }
 
@@ -813,9 +806,9 @@ public class Workbook implements Model
 //
 //            Record record = records.get(k);
 ////             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;
-//         }
+//        }
 //        }
 //        log.log(DEBUG, "Exiting serialize workbook");
 //        return retval;
@@ -1821,10 +1814,10 @@ public class Workbook implements Model
 
         // from Russia with love ;)
         if ( Locale.getDefault().toString().equals( "ru_RU" ) ) {
-               retval.setCurrentCountry(( short ) 7);
+            retval.setCurrentCountry(( short ) 7);
         }
         else {
-               retval.setCurrentCountry(( short ) 1);
+            retval.setCurrentCountry(( short ) 1);
         }
 
         return retval;
@@ -1950,10 +1943,10 @@ public class Workbook implements Model
      */
     public NameRecord addName(NameRecord name)
     {
-       
+        
         LinkTable linkTable = getOrCreateLinkTable();
         if(linkTable.nameAlreadyExists(name)) {
-               throw new IllegalArgumentException(
+            throw new IllegalArgumentException(
                 "You are trying to assign a duplicated name record: "
                 + name.getNameText());
         }
@@ -1964,27 +1957,18 @@ public class Workbook implements Model
     
     /**
      * 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)
-    {
-        if (index == -1 || index+1 > Short.MAX_VALUE) 
-            throw new IllegalArgumentException("Index is not valid ["+index+"]");
+    public NameRecord createBuiltInName(byte builtInName, int sheetNumber) {
+        if (sheetNumber < 0 || sheetNumber+1 > Short.MAX_VALUE) {
+            throw new IllegalArgumentException("Sheet number ["+sheetNumber+"]is not valid ");
+        }
         
-        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)) {
-               cont++;
-               String altNameName = prefix + cont;
-               
-               // 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());
+            throw new RuntimeException("Builtin (" + builtInName 
+                    + ") already exists for sheet (" + sheetNumber + ")");
         }
         addName(name);
         return name;
@@ -1992,16 +1976,15 @@ public class Workbook implements Model
 
 
     /** 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);
-            records.remove(idx + namenum);
-            linkTable.removeName(namenum);
+            records.remove(idx + nameIndex);
+            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
      */
     public short getFormat(String format, boolean createIfNotFound) {
-       Iterator iterator;
-       for (iterator = formats.iterator(); iterator.hasNext();) {
-           FormatRecord r = (FormatRecord)iterator.next();
-           if (r.getFormatString().equals(format)) {
-               return r.getIndexCode();
-           }
-       }
+    Iterator iterator;
+    for (iterator = formats.iterator(); iterator.hasNext();) {
+        FormatRecord r = (FormatRecord)iterator.next();
+        if (r.getFormatString().equals(format)) {
+        return r.getIndexCode();
+        }
+    }
 
-       if (createIfNotFound) {
-           return createFormat(format);
-       }
+    if (createIfNotFound) {
+        return createFormat(format);
+    }
 
-       return -1;
+    return -1;
     }
 
     /**
@@ -2031,7 +2014,7 @@ public class Workbook implements Model
      * @return ArrayList of FormatRecords in the notebook
      */
     public ArrayList getFormats() {
-       return formats;
+    return formats;
     }
 
     /**
@@ -2043,7 +2026,7 @@ public class Workbook implements Model
      */
     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;
 //        ++bspos;
         FormatRecord rec = new FormatRecord();
@@ -2113,7 +2096,7 @@ public class Workbook implements Model
 
     public List getHyperlinks()
     {
-       return hyperlinks;
+        return hyperlinks;
     }
     
     public List getRecords()
@@ -2170,54 +2153,54 @@ public class Workbook implements Model
      * Finds the primary drawing group, if one already exists
      */
     public void findDrawingGroup() {
-       // Need to find a DrawingGroupRecord that
-       //  contains a EscherDggRecord
-       for(Iterator rit = records.iterator(); rit.hasNext();) {
-               Record r = (Record)rit.next();
-               
-               if(r instanceof DrawingGroupRecord) {
-               DrawingGroupRecord dg = (DrawingGroupRecord)r;
-               dg.processChildRecords();
-               
-               EscherContainerRecord cr =
-                       dg.getEscherContainer();
-               if(cr == null) {
-                       continue;
-               }
-               
-               EscherDggRecord dgg = null;
-               for(Iterator it = cr.getChildRecords().iterator(); it.hasNext();) {
-                       Object er = it.next();
-                       if(er instanceof EscherDggRecord) {
-                               dgg = (EscherDggRecord)er;
-                       }
-               }
-               
-               if(dgg != null) {
-                       drawingManager = new DrawingManager2(dgg);
-                       return;
-               }
-               }
-       }
-
-       // Look for the DrawingGroup record
+        // Need to find a DrawingGroupRecord that
+        //  contains a EscherDggRecord
+        for(Iterator rit = records.iterator(); rit.hasNext();) {
+            Record r = (Record)rit.next();
+            
+            if(r instanceof DrawingGroupRecord) {
+                DrawingGroupRecord dg =    (DrawingGroupRecord)r;
+                dg.processChildRecords();
+                
+                EscherContainerRecord cr =
+                    dg.getEscherContainer();
+                if(cr == null) {
+                    continue;
+                }
+                
+                EscherDggRecord dgg = null;
+                for(Iterator it = cr.getChildRecords().iterator(); it.hasNext();) {
+                    Object er = it.next();
+                    if(er instanceof EscherDggRecord) {
+                        dgg = (EscherDggRecord)er;
+                    }
+                }
+                
+                if(dgg != null) {
+                    drawingManager = new DrawingManager2(dgg);
+                    return;
+                }
+            }
+        }
+
+        // Look for the DrawingGroup record
         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) {
-               DrawingGroupRecord dg =
-                       (DrawingGroupRecord)records.get(dgLoc);
-               EscherDggRecord dgg = null;
-               for(Iterator it = dg.getEscherRecords().iterator(); it.hasNext();) {
-                       Object er = it.next();
-                       if(er instanceof EscherDggRecord) {
-                               dgg = (EscherDggRecord)er;
-                       }
-               }
-               
-               if(dgg != null) {
-                       drawingManager = new DrawingManager2(dgg);
-               }
+            DrawingGroupRecord dg =
+                (DrawingGroupRecord)records.get(dgLoc);
+            EscherDggRecord dgg = null;
+            for(Iterator it = dg.getEscherRecords().iterator(); it.hasNext();) {
+                Object er = it.next();
+                if(er instanceof EscherDggRecord) {
+                    dgg = (EscherDggRecord)er;
+                }
+            }
+            
+            if(dgg != null) {
+                drawingManager = new DrawingManager2(dgg);
+            }
         }
     }
 
@@ -2379,7 +2362,7 @@ public class Workbook implements Model
      */
     public boolean isWriteProtected() {
         if (this.fileShare == null) {
-               return false;
+            return false;
         }
         FileSharingRecord frec = getFileSharing();
         return (frec.getReadOnly() == 1);
index dbd796991c69656a525e80eebc782d3e4c00e838..bfc2ac4ed2f03aef8f235dafe2723bc382dd86ce 100644 (file)
@@ -43,10 +43,10 @@ import org.apache.poi.util.StringUtil;
  * @version 1.0-pre
  */
 public final class NameRecord extends Record {
-    /**
-     */
-    public final static short sid = 0x18; //Docs says that it is 0x218
-    
+       /**
+        */
+       public final static short sid = 0x18; //Docs says that it is 0x218
+       
        /**Included for completeness sake, not implemented
           */
        public final static byte  BUILTIN_CONSOLIDATE_AREA      = (byte)1;
@@ -91,68 +91,68 @@ public final class NameRecord extends Record {
        /**Included for completeness sake, not implemented
         */
        public final static byte  BUILTIN_SHEET_TITLE           = (byte)12;
-    
-    public static final short OPT_HIDDEN_NAME =   (short) 0x0001;
-    public static final short OPT_FUNCTION_NAME = (short) 0x0002;
-    public static final short OPT_COMMAND_NAME =  (short) 0x0004;
-    public static final short OPT_MACRO =         (short) 0x0008;
-    public static final short OPT_COMPLEX =       (short) 0x0010;
-    public static final short OPT_BUILTIN =       (short) 0x0020;
-    public static final short OPT_BINDATA =       (short) 0x1000;
-
-    
-    private short             field_1_option_flag;
-    private byte              field_2_keyboard_shortcut;
-    private byte              field_3_length_name_text;
-    private short             field_4_length_name_definition;
-    private short             field_5_index_to_sheet;     // unused: see field_6
-    private short             field_6_equals_to_index_to_sheet;
-    private byte              field_7_length_custom_menu;
-    private byte              field_8_length_description_text;
-    private byte              field_9_length_help_topic_text;
-    private byte              field_10_length_status_bar_text;
-    private byte              field_11_compressed_unicode_flag;   // not documented
-    private byte              field_12_builtIn_name;
-    private String            field_12_name_text;
-    private Stack             field_13_name_definition;
-    private String            field_14_custom_menu_text;
-    private String            field_15_description_text;
-    private String            field_16_help_topic_text;
-    private String            field_17_status_bar_text;
-
-
-    /** Creates new NameRecord */
-    public NameRecord() {
-        field_13_name_definition = new Stack();
-
-        field_12_name_text = new String();
-        field_14_custom_menu_text = new String();
-        field_15_description_text = new String();
-        field_16_help_topic_text = new String();
-        field_17_status_bar_text = new String();
-    }
-
-    /**
-     * Constructs a Name record and sets its fields appropriately.
-     *
-     * @param in the RecordInputstream to read the record from
-     */
-    public NameRecord(RecordInputStream in) {
-        super(in);
-    }
+       
+       public static final short OPT_HIDDEN_NAME =   (short) 0x0001;
+       public static final short OPT_FUNCTION_NAME = (short) 0x0002;
+       public static final short OPT_COMMAND_NAME =  (short) 0x0004;
+       public static final short OPT_MACRO =         (short) 0x0008;
+       public static final short OPT_COMPLEX =       (short) 0x0010;
+       public static final short OPT_BUILTIN =       (short) 0x0020;
+       public static final short OPT_BINDATA =       (short) 0x1000;
+
+       
+       private short             field_1_option_flag;
+       private byte              field_2_keyboard_shortcut;
+       private byte              field_3_length_name_text;
+       private short             field_4_length_name_definition;
+       private short             field_5_index_to_sheet;     // unused: see field_6
+       /** the one based sheet number.  Zero if this is a global name */
+       private int               field_6_sheetNumber;
+       private byte              field_7_length_custom_menu;
+       private byte              field_8_length_description_text;
+       private byte              field_9_length_help_topic_text;
+       private byte              field_10_length_status_bar_text;
+       private byte              field_11_compressed_unicode_flag;   // not documented
+       private byte              field_12_builtIn_name;
+       private String            field_12_name_text;
+       private Stack             field_13_name_definition;
+       private String            field_14_custom_menu_text;
+       private String            field_15_description_text;
+       private String            field_16_help_topic_text;
+       private String            field_17_status_bar_text;
+
+
+       /** Creates new NameRecord */
+       public NameRecord() {
+           field_13_name_definition = new Stack();
+
+           field_12_name_text = new String();
+           field_14_custom_menu_text = new String();
+           field_15_description_text = new String();
+           field_16_help_topic_text = new String();
+           field_17_status_bar_text = new String();
+       }
+
+       /**
+        * Constructs a Name record and sets its fields appropriately.
+        *
+        * @param in the RecordInputstream to read the record from
+        */
+       public NameRecord(RecordInputStream in) {
+           super(in);
+       }
 
        /**
         * Constructor to create a built-in named region
         * @param builtin Built-in byte representation for the name record, use the public constants
-        * @param index 
         */
-       public NameRecord(byte builtin, short index)
+       public NameRecord(byte builtin, int sheetNumber)
        {
            this();         
            this.field_12_builtIn_name = builtin;
            this.setOptionFlag((short)(this.getOptionFlag() | OPT_BUILTIN));
            this.setNameTextLength((byte)1);
-           this.setEqualsToIndexToSheet(index); //the extern sheets are set through references
+           field_6_sheetNumber = sheetNumber; //the extern sheets are set through references
            
            //clearing these because they are not used with builtin records
                this.setCustomMenuLength((byte)0);
@@ -163,268 +163,260 @@ public final class NameRecord extends Record {
            
        }
 
-    /** sets the option flag for the named range
-     * @param flag option flag
-     */
-    public void setOptionFlag(short flag){
-        field_1_option_flag = flag;
-    }
-
-
-    /** sets the keyboard shortcut
-     * @param shortcut keyboard shortcut
-     */
-    public void setKeyboardShortcut(byte shortcut){
-        field_2_keyboard_shortcut = shortcut;
-    }
-
-    /** sets the name of the named range length
-     * @param length name length
-     */
-    public void setNameTextLength(byte length){
-        field_3_length_name_text = length;
-    }
-
-    /** sets the definition (reference - formula) length
-     * @param length defenition length
-     */
-    public void setDefinitionTextLength(short length){
-        field_4_length_name_definition = length;
-    }
-
-    /** sets the index number to the extern sheet (thats is what writen in documentation
-     *  but as i saw , it works differently)
-     * @param index extern sheet index
-     */
-    public void setUnused(short index){
-        field_5_index_to_sheet = index;
-
-        // field_6_equals_to_index_to_sheet is equal to field_5_index_to_sheet
+       /** sets the option flag for the named range
+        * @param flag option flag
+        */
+       public void setOptionFlag(short flag){
+           field_1_option_flag = flag;
+       }
+
+
+       /** sets the keyboard shortcut
+        * @param shortcut keyboard shortcut
+        */
+       public void setKeyboardShortcut(byte shortcut){
+           field_2_keyboard_shortcut = shortcut;
+       }
+
+       /** sets the name of the named range length
+        * @param length name length
+        */
+       public void setNameTextLength(byte length){
+           field_3_length_name_text = length;
+       }
+
+       /** sets the definition (reference - formula) length
+        * @param length defenition length
+        */
+       public void setDefinitionTextLength(short length){
+           field_4_length_name_definition = length;
+       }
+
+       /** sets the index number to the extern sheet (thats is what writen in documentation
+        *  but as i saw , it works differently)
+        * @param index extern sheet index
+        */
+       public void setUnused(short index){
+           field_5_index_to_sheet = index;
+
+           // field_6_equals_to_index_to_sheet is equal to field_5_index_to_sheet
 //        field_6_equals_to_index_to_sheet = index;
-    }
+       }
+
+       /**
+        * For named ranges, and built-in names
+        * @return the 1-based sheet number.  Zero if this is a global name 
+        */
+       public int getSheetNumber()
+       {
+           return field_6_sheetNumber;
+       }
+
+       /**
+        * @return function group
+        * @see FnGroupCountRecord
+        */
+       public byte getFnGroup() {
+           int masked = field_1_option_flag & 0x0fc0;
+           return (byte) (masked >> 4);
+       }
+
+
+       public void setSheetNumber(int value)
+       {
+           field_6_sheetNumber = value;
+       }
+
+
+       /** sets the custom menu length
+        * @param length custom menu length
+        */
+       public void setCustomMenuLength(byte length){
+           field_7_length_custom_menu = length;
+       }
+
+       /** sets the length of named range description
+        * @param length description length
+        */
+       public void setDescriptionTextLength(byte length){
+           field_8_length_description_text = length;
+       }
+
+       /** sets the help topic length
+        * @param length help topic length
+        */
+       public void setHelpTopicLength(byte length){
+           field_9_length_help_topic_text = length;
+       }
+
+       /** sets the length of the status bar text
+        * @param length status bar text length
+        */
+       public void setStatusBarLength(byte length){
+           field_10_length_status_bar_text = length;
+       }
+
+       /** sets the compressed unicode flag
+        * @param flag unicode flag
+        */
+       public void setCompressedUnicodeFlag(byte flag) {
+           field_11_compressed_unicode_flag = flag;
+       }
+
+       /** sets the name of the named range
+        * @param name named range name
+        */
+       public void setNameText(String name){
+           field_12_name_text = name;
+           setCompressedUnicodeFlag(
+                       StringUtil.hasMultibyte(name) ? (byte)1 : (byte)0
+           );
+       }
+
+       /** sets the custom menu text
+        * @param text custom menu text
+        */
+       public void setCustomMenuText(String text){
+           field_14_custom_menu_text = text;
+       }
+
+       /** sets the description text
+        * @param text the description text
+        */
+       public void setDescriptionText(String text){
+           field_15_description_text = text;
+       }
+
+       /** sets the help topic text
+        * @param text help topix text
+        */
+       public void setHelpTopicText(String text){
+           field_16_help_topic_text = text;
+       }
+
+       /** sets the status bar text
+        * @param text status bar text
+        */
+       public void setStatusBarText(String text){
+           field_17_status_bar_text = text;
+       }
+
+       /** gets the option flag
+        * @return option flag
+        */
+       public short getOptionFlag(){
+           return field_1_option_flag;
+       }
+
+       /** returns the keyboard shortcut
+        * @return keyboard shortcut
+        */
+       public byte getKeyboardShortcut(){
+           return field_2_keyboard_shortcut ;
+       }
+
+       /** 
+        * gets the name length, in characters
+        * @return name length
+        */
+       public byte getNameTextLength(){
+           return field_3_length_name_text;
+       }
+       
+       /** 
+        * gets the name length, in bytes
+        * @return raw name length
+        */
+       public byte getRawNameTextLength(){
+               if( (field_11_compressed_unicode_flag & 0x01) == 1 ) {
+                       return (byte)(2 * field_3_length_name_text);
+               }
+               return field_3_length_name_text;
+       }
+
+       /** get the definition length
+        * @return definition length
+        */
+       public short getDefinitionLength(){
+           return field_4_length_name_definition;
+       }
+
+       /** gets the index to extern sheet
+        * @return index to extern sheet
+        */
+       public short getUnused(){
+           return field_5_index_to_sheet;
+       }
+
+       /** gets the custom menu length
+        * @return custom menu length
+        */
+       public byte getCustomMenuLength(){
+           return field_7_length_custom_menu;
+       }
+
+       /** gets the description text length
+        * @return description text length
+        */
+       public byte getDescriptionTextLength(){
+           return field_8_length_description_text;
+       }
+
+       /** gets the help topic length
+        * @return help topic length
+        */
+       public byte getHelpTopicLength(){
+           return field_9_length_help_topic_text;
+       }
+
+       /** get the status bar text length
+        * @return satus bar length
+        */
+       public byte getStatusBarLength(){
+           return field_10_length_status_bar_text;
+       }
+
+       /** gets the name compressed Unicode flag
+        * @return compressed unicode flag
+        */
+       public byte getCompressedUnicodeFlag() {
+           return field_11_compressed_unicode_flag;
+       }
+
+       /**
+        * @return true if name is hidden
+        */
+       public boolean isHiddenName() {
+           return (field_1_option_flag & OPT_HIDDEN_NAME) != 0;
+       }
+
+       /**
+        * @return true if name is a function
+        */
+       public boolean isFunctionName() {
+           return (field_1_option_flag & OPT_FUNCTION_NAME) != 0;
+       }
 
-    public short getEqualsToIndexToSheet()
-    {
-        return field_6_equals_to_index_to_sheet;
-    }
+       /**
+        * @return true if name is a command
+        */
+       public boolean isCommandName() {
+           return (field_1_option_flag & OPT_COMMAND_NAME) != 0;
+       }
+
+       /**
+        * @return true if function macro or command macro
+        */
+       public boolean isMacro() {
+           return (field_1_option_flag & OPT_MACRO) != 0;
+       }
 
        /**
-        * Convenience method to retrieve the index the name refers to.
-        * @see #getEqualsToIndexToSheet()
-        * @return short
-        */
-       public short getIndexToSheet() {
-               return getEqualsToIndexToSheet();
-       }
-
-    /**
-     * @return function group
-     * @see FnGroupCountRecord
-     */
-    public byte getFnGroup() {
-        int masked = field_1_option_flag & 0x0fc0;
-        return (byte) (masked >> 4);
-    }
-
-    public void setEqualsToIndexToSheet(short value)
-    {
-        field_6_equals_to_index_to_sheet = value;
-    }
-
-
-    /** sets the custom menu length
-     * @param length custom menu length
-     */
-    public void setCustomMenuLength(byte length){
-        field_7_length_custom_menu = length;
-    }
-
-    /** sets the length of named range description
-     * @param length description length
-     */
-    public void setDescriptionTextLength(byte length){
-        field_8_length_description_text = length;
-    }
-
-    /** sets the help topic length
-     * @param length help topic length
-     */
-    public void setHelpTopicLength(byte length){
-        field_9_length_help_topic_text = length;
-    }
-
-    /** sets the length of the status bar text
-     * @param length status bar text length
-     */
-    public void setStatusBarLength(byte length){
-        field_10_length_status_bar_text = length;
-    }
-
-    /** sets the compressed unicode flag
-     * @param flag unicode flag
-     */
-    public void setCompressedUnicodeFlag(byte flag) {
-        field_11_compressed_unicode_flag = flag;
-    }
-
-    /** sets the name of the named range
-     * @param name named range name
-     */
-    public void setNameText(String name){
-        field_12_name_text = name;
-        setCompressedUnicodeFlag(
-               StringUtil.hasMultibyte(name) ? (byte)1 : (byte)0
-        );
-    }
-
-    //    public void setNameDefintion(String definition){
-    //        test = definition;
-    //    }
-
-    /** sets the custom menu text
-     * @param text custom menu text
-     */
-    public void setCustomMenuText(String text){
-        field_14_custom_menu_text = text;
-    }
-
-    /** sets the description text
-     * @param text the description text
-     */
-    public void setDescriptionText(String text){
-        field_15_description_text = text;
-    }
-
-    /** sets the help topic text
-     * @param text help topix text
-     */
-    public void setHelpTopicText(String text){
-        field_16_help_topic_text = text;
-    }
-
-    /** sets the status bar text
-     * @param text status bar text
-     */
-    public void setStatusBarText(String text){
-        field_17_status_bar_text = text;
-    }
-
-    /** gets the option flag
-     * @return option flag
-     */
-    public short getOptionFlag(){
-        return field_1_option_flag;
-    }
-
-    /** returns the keyboard shortcut
-     * @return keyboard shortcut
-     */
-    public byte getKeyboardShortcut(){
-        return field_2_keyboard_shortcut ;
-    }
-
-    /** 
-     * gets the name length, in characters
-     * @return name length
-     */
-    public byte getNameTextLength(){
-        return field_3_length_name_text;
-    }
-    
-    /** 
-     * gets the name length, in bytes
-     * @return raw name length
-     */
-    public byte getRawNameTextLength(){
-       if( (field_11_compressed_unicode_flag & 0x01) == 1 ) {
-               return (byte)(2 * field_3_length_name_text);
-       }
-       return field_3_length_name_text;
-    }
-
-    /** get the definition length
-     * @return definition length
-     */
-    public short getDefinitionLength(){
-        return field_4_length_name_definition;
-    }
-
-    /** gets the index to extern sheet
-     * @return index to extern sheet
-     */
-    public short getUnused(){
-        return field_5_index_to_sheet;
-    }
-
-    /** gets the custom menu length
-     * @return custom menu length
-     */
-    public byte getCustomMenuLength(){
-        return field_7_length_custom_menu;
-    }
-
-    /** gets the description text length
-     * @return description text length
-     */
-    public byte getDescriptionTextLength(){
-        return field_8_length_description_text;
-    }
-
-    /** gets the help topic length
-     * @return help topic length
-     */
-    public byte getHelpTopicLength(){
-        return field_9_length_help_topic_text;
-    }
-
-    /** get the status bar text length
-     * @return satus bar length
-     */
-    public byte getStatusBarLength(){
-        return field_10_length_status_bar_text;
-    }
-
-    /** gets the name compressed Unicode flag
-     * @return compressed unicode flag
-     */
-    public byte getCompressedUnicodeFlag() {
-        return field_11_compressed_unicode_flag;
-    }
-
-    /**
-     * @return true if name is hidden
-     */
-    public boolean isHiddenName() {
-        return (field_1_option_flag & OPT_HIDDEN_NAME) != 0;
-    }
-
-    /**
-     * @return true if name is a function
-     */
-    public boolean isFunctionName() {
-        return (field_1_option_flag & OPT_FUNCTION_NAME) != 0;
-    }
-
-    /**
-     * @return true if name is a command
-     */
-    public boolean isCommandName() {
-        return (field_1_option_flag & OPT_COMMAND_NAME) != 0;
-    }
-
-    /**
-     * @return true if function macro or command macro
-     */
-    public boolean isMacro() {
-        return (field_1_option_flag & OPT_MACRO) != 0;
-    }
-
-    /**
-     * @return true if array formula or user defined
-     */
-    public boolean isComplexFunction() {
-        return (field_1_option_flag & OPT_COMPLEX) != 0;
-    }
+        * @return true if array formula or user defined
+        */
+       public boolean isComplexFunction() {
+           return (field_1_option_flag & OPT_COMPLEX) != 0;
+       }
 
 
        /**Convenience Function to determine if the name is a built-in name
@@ -440,7 +432,7 @@ public final class NameRecord extends Record {
         */
        public String getNameText(){
 
-       return this.isBuiltInName() ? this.translateBuiltInName(this.getBuiltInName()) : field_12_name_text;
+               return this.isBuiltInName() ? this.translateBuiltInName(this.getBuiltInName()) : field_12_name_text;
        }
 
        /** Gets the Built In Name
@@ -452,81 +444,81 @@ public final class NameRecord extends Record {
        }
 
 
-    /** gets the definition, reference (Formula)
-     * @return definition -- can be null if we cant parse ptgs
-     */
-    public List getNameDefinition() {
-        return field_13_name_definition;
-    }
-
-    public void setNameDefinition(Stack nameDefinition) {
-        field_13_name_definition = nameDefinition;
-    }
-
-    /** get the custom menu text
-     * @return custom menu text
-     */
-    public String getCustomMenuText(){
-        return field_14_custom_menu_text;
-    }
-
-    /** gets the description text
-     * @return description text
-     */
-    public String getDescriptionText(){
-        return field_15_description_text;
-    }
-
-    /** get the help topic text
-     * @return gelp topic text
-     */
-    public String getHelpTopicText(){
-        return field_16_help_topic_text;
-    }
-
-    /** gets the status bar text
-     * @return status bar text
-     */
-    public String getStatusBarText(){
-        return field_17_status_bar_text;
-    }
-
-    /**
-     * called by constructor, should throw runtime exception in the event of a
-     * record passed with a differing ID.
-     *
-     * @param id alleged id for this record
-     */
-    protected void validateSid(short id) {
-        if (id != sid) {
-            throw new RecordFormatException("NOT A valid Name RECORD");
-        }
-    }
-    
-    /**
-     * called by the class that is responsible for writing this sucker.
-     * Subclasses should implement this so that their data is passed back in a
+       /** gets the definition, reference (Formula)
+        * @return definition -- can be null if we cant parse ptgs
+        */
+       public List getNameDefinition() {
+           return field_13_name_definition;
+       }
+
+       public void setNameDefinition(Stack nameDefinition) {
+           field_13_name_definition = nameDefinition;
+       }
+
+       /** get the custom menu text
+        * @return custom menu text
+        */
+       public String getCustomMenuText(){
+           return field_14_custom_menu_text;
+       }
+
+       /** gets the description text
+        * @return description text
+        */
+       public String getDescriptionText(){
+           return field_15_description_text;
+       }
+
+       /** get the help topic text
+        * @return gelp topic text
+        */
+       public String getHelpTopicText(){
+           return field_16_help_topic_text;
+       }
+
+       /** gets the status bar text
+        * @return status bar text
+        */
+       public String getStatusBarText(){
+           return field_17_status_bar_text;
+       }
+
+       /**
+        * called by constructor, should throw runtime exception in the event of a
+        * record passed with a differing ID.
+        *
+        * @param id alleged id for this record
+        */
+       protected void validateSid(short id) {
+           if (id != sid) {
+               throw new RecordFormatException("NOT A valid Name RECORD");
+           }
+       }
+       
+       /**
+        * called by the class that is responsible for writing this sucker.
+        * Subclasses should implement this so that their data is passed back in a
         * @param offset to begin writing at
         * @param data byte array containing instance data
-     * @return number of bytes written
-     */
-    public int serialize( int offset, byte[] data )
-    {
-        LittleEndian.putShort( data, 0 + offset, sid );
-        short size = (short)( 15 + getTextsLength() + getNameDefinitionSize());
-        LittleEndian.putShort( data, 2 + offset, size );
-        // size defined below
-        LittleEndian.putShort( data, 4 + offset, getOptionFlag() );
-        data[6 + offset] = getKeyboardShortcut();
-        data[7 + offset] = getNameTextLength();
-        LittleEndian.putShort( data, 8 + offset, getDefinitionLength() );
-        LittleEndian.putShort( data, 10 + offset, getUnused() );
-        LittleEndian.putShort( data, 12 + offset, getEqualsToIndexToSheet() );
-        data[14 + offset] = getCustomMenuLength();
-        data[15 + offset] = getDescriptionTextLength();
-        data[16 + offset] = getHelpTopicLength();
-        data[17 + offset] = getStatusBarLength();
-        data[18 + offset] = getCompressedUnicodeFlag();
+        * @return number of bytes written
+        */
+       public int serialize( int offset, byte[] data )
+       {
+           LittleEndian.putShort( data, 0 + offset, sid );
+           short size = (short)( 15 + getTextsLength() + getNameDefinitionSize());
+           LittleEndian.putShort( data, 2 + offset, size );
+           // size defined below
+           LittleEndian.putShort( data, 4 + offset, getOptionFlag() );
+           data[6 + offset] = getKeyboardShortcut();
+           data[7 + offset] = getNameTextLength();
+           LittleEndian.putShort( data, 8 + offset, getDefinitionLength() );
+           LittleEndian.putShort( data, 10 + offset, getUnused() );
+           LittleEndian.putUShort( data, 12 + offset, field_6_sheetNumber);
+           data[14 + offset] = getCustomMenuLength();
+           data[15 + offset] = getDescriptionTextLength();
+           data[16 + offset] = getHelpTopicLength();
+           data[17 + offset] = getStatusBarLength();
+           data[18 + offset] = getCompressedUnicodeFlag();
 
                        int start_of_name_definition = 19 + field_3_length_name_text;
 
@@ -544,320 +536,320 @@ public final class NameRecord extends Record {
                        Ptg.serializePtgStack(field_13_name_definition,  data, start_of_name_definition + offset );
 
 
-            int start_of_custom_menu_text = start_of_name_definition + field_4_length_name_definition;
-            StringUtil.putCompressedUnicode( getCustomMenuText(), data, start_of_custom_menu_text + offset );
-
-            int start_of_description_text = start_of_custom_menu_text + field_7_length_custom_menu;
-            StringUtil.putCompressedUnicode( getDescriptionText(), data, start_of_description_text + offset );
-
-            int start_of_help_topic_text = start_of_description_text + field_8_length_description_text;
-            StringUtil.putCompressedUnicode( getHelpTopicText(), data, start_of_help_topic_text + offset );
-
-            int start_of_status_bar_text = start_of_help_topic_text + field_9_length_help_topic_text;
-            StringUtil.putCompressedUnicode( getStatusBarText(), data, start_of_status_bar_text + offset );
-
-            return getRecordSize();
-        /* } */
-    }
-
-    /** 
-     * Gets the length of all texts, in bytes
-     * @return total length
-     */
-    public int getTextsLength(){
-        int result;
-
-        result = getRawNameTextLength() + getDescriptionTextLength() +
-               getHelpTopicLength() + getStatusBarLength();
-
-        return result;
-    }
-    
-    private int getNameDefinitionSize() {
-       int result = 0;
-        List list   = field_13_name_definition;
-        
-        for (int k = 0; k < list.size(); k++)
-        {
-               Ptg ptg = ( Ptg ) list.get(k);
-               
-               result += ptg.getSize();
-        }
-        return result;    
-    }
-
-    /** returns the record size
-     */
-    public int getRecordSize(){
-        int result;
-
-        result = 19 + getTextsLength() + getNameDefinitionSize();
-        
-
-        return result;
-    }
-
-    /** gets the extern sheet number
-     * @return extern sheet index
-     */
-    public short getExternSheetNumber(){
-        if (field_13_name_definition == null || field_13_name_definition.isEmpty()) return 0;
-        Ptg ptg = (Ptg) field_13_name_definition.peek();
-        short result = 0;
-
-        if (ptg.getClass() == Area3DPtg.class){
-            result = ((Area3DPtg) ptg).getExternSheetIndex();
-
-        } else if (ptg.getClass() == Ref3DPtg.class){
-            result = ((Ref3DPtg) ptg).getExternSheetIndex();
-        }
-
-        return result;
-    }
-
-    /** sets the extern sheet number
-     * @param externSheetNumber extern sheet number
-     */
-    public void setExternSheetNumber(short externSheetNumber){
-        Ptg ptg;
-
-        if (field_13_name_definition == null || field_13_name_definition.isEmpty()){
-            field_13_name_definition = new Stack();
-            ptg = createNewPtg();
-        } else {
-            ptg = (Ptg) field_13_name_definition.peek();
-        }
-
-        if (ptg.getClass() == Area3DPtg.class){
-            ((Area3DPtg) ptg).setExternSheetIndex(externSheetNumber);
-
-        } else if (ptg.getClass() == Ref3DPtg.class){
-            ((Ref3DPtg) ptg).setExternSheetIndex(externSheetNumber);
-        }
-
-    }
-
-    private Ptg createNewPtg(){
-        Ptg ptg = new Area3DPtg();
-        field_13_name_definition.push(ptg);
-
-        return ptg;
-    }
-
-    /** gets the reference , the area only (range)
-     * @return area reference
-     */
+               int start_of_custom_menu_text = start_of_name_definition + field_4_length_name_definition;
+               StringUtil.putCompressedUnicode( getCustomMenuText(), data, start_of_custom_menu_text + offset );
+
+               int start_of_description_text = start_of_custom_menu_text + field_7_length_custom_menu;
+               StringUtil.putCompressedUnicode( getDescriptionText(), data, start_of_description_text + offset );
+
+               int start_of_help_topic_text = start_of_description_text + field_8_length_description_text;
+               StringUtil.putCompressedUnicode( getHelpTopicText(), data, start_of_help_topic_text + offset );
+
+               int start_of_status_bar_text = start_of_help_topic_text + field_9_length_help_topic_text;
+               StringUtil.putCompressedUnicode( getStatusBarText(), data, start_of_status_bar_text + offset );
+
+               return getRecordSize();
+           /* } */
+       }
+
+       /** 
+        * Gets the length of all texts, in bytes
+        * @return total length
+        */
+       public int getTextsLength(){
+           int result;
+
+           result = getRawNameTextLength() + getDescriptionTextLength() +
+                       getHelpTopicLength() + getStatusBarLength();
+
+           return result;
+       }
+       
+       private int getNameDefinitionSize() {
+               int result = 0;
+           List list   = field_13_name_definition;
+           
+           for (int k = 0; k < list.size(); k++)
+           {
+                       Ptg ptg = ( Ptg ) list.get(k);
+                       
+                       result += ptg.getSize();
+           }
+           return result;    
+       }
+
+       /** returns the record size
+        */
+       public int getRecordSize(){
+           int result;
+
+           result = 19 + getTextsLength() + getNameDefinitionSize();
+           
+
+           return result;
+       }
+
+       /** gets the extern sheet number
+        * @return extern sheet index
+        */
+       public short getExternSheetNumber(){
+           if (field_13_name_definition == null || field_13_name_definition.isEmpty()) return 0;
+           Ptg ptg = (Ptg) field_13_name_definition.peek();
+           short result = 0;
+
+           if (ptg.getClass() == Area3DPtg.class){
+               result = ((Area3DPtg) ptg).getExternSheetIndex();
+
+           } else if (ptg.getClass() == Ref3DPtg.class){
+               result = ((Ref3DPtg) ptg).getExternSheetIndex();
+           }
+
+           return result;
+       }
+
+       /** sets the extern sheet number
+        * @param externSheetNumber extern sheet number
+        */
+       public void setExternSheetNumber(short externSheetNumber){
+           Ptg ptg;
+
+           if (field_13_name_definition == null || field_13_name_definition.isEmpty()){
+               field_13_name_definition = new Stack();
+               ptg = createNewPtg();
+           } else {
+               ptg = (Ptg) field_13_name_definition.peek();
+           }
+
+           if (ptg.getClass() == Area3DPtg.class){
+               ((Area3DPtg) ptg).setExternSheetIndex(externSheetNumber);
+
+           } else if (ptg.getClass() == Ref3DPtg.class){
+               ((Ref3DPtg) ptg).setExternSheetIndex(externSheetNumber);
+           }
+
+       }
+
+       private Ptg createNewPtg(){
+           Ptg ptg = new Area3DPtg();
+           field_13_name_definition.push(ptg);
+
+           return ptg;
+       }
+
+       /** gets the reference , the area only (range)
+        * @return area reference
+        */
        public String getAreaReference(HSSFWorkbook book){
                return FormulaParser.toFormulaString(book, field_13_name_definition);
        }
 
-    /** sets the reference , the area only (range)
-     * @param ref area reference
-     */
-    public void setAreaReference(String ref){
-        //Trying to find if what ptg do we need
-        RangeAddress ra = new RangeAddress(ref);
-        Ptg oldPtg;
-        Ptg ptg;
-
-        if (field_13_name_definition==null ||field_13_name_definition.isEmpty()){
-            field_13_name_definition = new Stack();
-            oldPtg = createNewPtg();
-        } else {
-            //Trying to find extern sheet index
-            oldPtg = (Ptg) field_13_name_definition.pop();
-        }
-
-        short externSheetIndex = 0;
-
-        if (oldPtg.getClass() == Area3DPtg.class){
-            externSheetIndex =  ((Area3DPtg) oldPtg).getExternSheetIndex();
-
-        } else if (oldPtg.getClass() == Ref3DPtg.class){
-            externSheetIndex =  ((Ref3DPtg) oldPtg).getExternSheetIndex();
-        }
-
-        if (ra.hasRange()) {
-               // Is it contiguous or not?
-               AreaReference[] refs = 
-                       AreaReference.generateContiguous(ref);
-            this.setDefinitionTextLength((short)0);
-
-            // Add the area reference(s) 
-               for(int i=0; i<refs.length; i++) {
+       /** sets the reference , the area only (range)
+        * @param ref area reference
+        */
+       public void setAreaReference(String ref){
+           //Trying to find if what ptg do we need
+           RangeAddress ra = new RangeAddress(ref);
+           Ptg oldPtg;
+           Ptg ptg;
+
+           if (field_13_name_definition==null ||field_13_name_definition.isEmpty()){
+               field_13_name_definition = new Stack();
+               oldPtg = createNewPtg();
+           } else {
+               //Trying to find extern sheet index
+               oldPtg = (Ptg) field_13_name_definition.pop();
+           }
+
+           short externSheetIndex = 0;
+
+           if (oldPtg.getClass() == Area3DPtg.class){
+               externSheetIndex =  ((Area3DPtg) oldPtg).getExternSheetIndex();
+
+           } else if (oldPtg.getClass() == Ref3DPtg.class){
+               externSheetIndex =  ((Ref3DPtg) oldPtg).getExternSheetIndex();
+           }
+
+           if (ra.hasRange()) {
+                       // Is it contiguous or not?
+                       AreaReference[] refs = 
+                               AreaReference.generateContiguous(ref);
+               this.setDefinitionTextLength((short)0);
+
+               // Add the area reference(s) 
+                       for(int i=0; i<refs.length; i++) {
                    ptg = new Area3DPtg();
                    ((Area3DPtg) ptg).setExternSheetIndex(externSheetIndex);
                    ((Area3DPtg) ptg).setArea(refs[i].formatAsString());
                    field_13_name_definition.push(ptg);
                    this.setDefinitionTextLength( (short)(getDefinitionLength() + ptg.getSize()) );
-               }
-               // And then a union if we had more than one area
-               if(refs.length > 1) {
-                       ptg = UnionPtg.instance;
-                field_13_name_definition.push(ptg);
+                       }
+                       // And then a union if we had more than one area
+                       if(refs.length > 1) {
+                               ptg = UnionPtg.instance;
+                   field_13_name_definition.push(ptg);
                    this.setDefinitionTextLength( (short)(getDefinitionLength() + ptg.getSize()) );
-               }
-        } else {
-            ptg = new Ref3DPtg();
-            ((Ref3DPtg) ptg).setExternSheetIndex(externSheetIndex);
-            ((Ref3DPtg) ptg).setArea(ref);
-            field_13_name_definition.push(ptg);
-            this.setDefinitionTextLength((short)ptg.getSize());
-        }
-    }
-
-    /**
-     * called by the constructor, should set class level fields.  Should throw
-     * runtime exception for bad/icomplete data.
-     *
-     * @param in the RecordInputstream to read the record from
-     */
-    protected void fillFields(RecordInputStream in) {
-        field_1_option_flag             = in.readShort();
-        field_2_keyboard_shortcut       = in.readByte();
-        field_3_length_name_text        = in.readByte();
-        field_4_length_name_definition  = in.readShort();
-        field_5_index_to_sheet          = in.readShort();
-        field_6_equals_to_index_to_sheet= in.readShort();
-        field_7_length_custom_menu      = in.readByte();
-        field_8_length_description_text = in.readByte();
-        field_9_length_help_topic_text  = in.readByte();
-        field_10_length_status_bar_text = in.readByte();
-            
-        //store the name in byte form if it's a builtin name
-        field_11_compressed_unicode_flag= in.readByte();        
-        if (this.isBuiltInName()) {
-           field_12_builtIn_name = in.readByte();
-        } else {                
-           if (field_11_compressed_unicode_flag == 1) {
-             field_12_name_text = in.readUnicodeLEString(field_3_length_name_text);
-           } else {
-             field_12_name_text = in.readCompressedUnicode(field_3_length_name_text);
-           }
-        }
-            
-        field_13_name_definition = Ptg.createParsedExpressionTokens(field_4_length_name_definition, in);
-    
-        //Who says that this can only ever be compressed unicode???
-        field_14_custom_menu_text       = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_7_length_custom_menu));
-    
-        field_15_description_text       = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_8_length_description_text));
-    
-        field_16_help_topic_text        = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_9_length_help_topic_text));
-    
-        field_17_status_bar_text        = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_10_length_status_bar_text));
-        /*} */
-    }
-
-    /**
-     * return the non static version of the id for this record.
-     */
-    public short getSid() {
-        return sid;
-    }
-    /*
-      20 00 
-      00 
-      01 
-      1A 00 // sz = 0x1A = 26
-      00 00 
-      01 00 
-      00 
-      00 
-      00 
-      00 
-      00 // unicode flag
-      07 // name
-      
-      29 17 00 3B 00 00 00 00 FF FF 00 00 02 00 3B 00 //{ 26
-      00 07 00 07 00 00 00 FF 00 10                   //  }
-      
-      
-      
-      20 00 
-      00 
-      01 
-      0B 00 // sz = 0xB = 11
-      00 00 
-      01 00 
-      00 
-      00 
-      00 
-      00 
-      00 // unicode flag
-      07 // name
-      
-      3B 00 00 07 00 07 00 00 00 FF 00   // { 11 }
+                       }
+           } else {
+               ptg = new Ref3DPtg();
+               ((Ref3DPtg) ptg).setExternSheetIndex(externSheetIndex);
+               ((Ref3DPtg) ptg).setArea(ref);
+               field_13_name_definition.push(ptg);
+               this.setDefinitionTextLength((short)ptg.getSize());
+           }
+       }
+
+       /**
+        * called by the constructor, should set class level fields.  Should throw
+        * runtime exception for bad/icomplete data.
+        *
+        * @param in the RecordInputstream to read the record from
+        */
+       protected void fillFields(RecordInputStream in) {
+           field_1_option_flag             = in.readShort();
+           field_2_keyboard_shortcut       = in.readByte();
+           field_3_length_name_text        = in.readByte();
+           field_4_length_name_definition  = in.readShort();
+           field_5_index_to_sheet          = in.readShort();
+           field_6_sheetNumber = in.readUShort();
+           field_7_length_custom_menu      = in.readByte();
+           field_8_length_description_text = in.readByte();
+           field_9_length_help_topic_text  = in.readByte();
+           field_10_length_status_bar_text = in.readByte();
+               
+           //store the name in byte form if it's a builtin name
+           field_11_compressed_unicode_flag= in.readByte();        
+           if (this.isBuiltInName()) {
+              field_12_builtIn_name = in.readByte();
+           } else {                
+              if (field_11_compressed_unicode_flag == 1) {
+                field_12_name_text = in.readUnicodeLEString(field_3_length_name_text);
+              } else {
+                field_12_name_text = in.readCompressedUnicode(field_3_length_name_text);
+              }
+           }
+               
+           field_13_name_definition = Ptg.createParsedExpressionTokens(field_4_length_name_definition, in);
+       
+           //Who says that this can only ever be compressed unicode???
+           field_14_custom_menu_text       = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_7_length_custom_menu));
+       
+           field_15_description_text       = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_8_length_description_text));
+       
+           field_16_help_topic_text        = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_9_length_help_topic_text));
+       
+           field_17_status_bar_text        = in.readCompressedUnicode(LittleEndian.ubyteToInt(field_10_length_status_bar_text));
+           /*} */
+       }
+
+       /**
+        * return the non static version of the id for this record.
+        */
+       public short getSid() {
+           return sid;
+       }
+       /*
+         20 00 
+         00 
+         01 
+         1A 00 // sz = 0x1A = 26
+         00 00 
+         01 00 
+         00 
+         00 
+         00 
+         00 
+         00 // unicode flag
+         07 // name
+         
+         29 17 00 3B 00 00 00 00 FF FF 00 00 02 00 3B 00 //{ 26
+         00 07 00 07 00 00 00 FF 00 10                   //  }
+         
+         
+         
+         20 00 
+         00 
+         01 
+         0B 00 // sz = 0xB = 11
+         00 00 
+         01 00 
+         00 
+         00 
+         00 
+         00 
+         00 // unicode flag
+         07 // name
+         
+         3B 00 00 07 00 07 00 00 00 FF 00   // { 11 }
   */
-    /*
-      18, 00, 
-      1B, 00, 
-      
-      20, 00, 
-      00, 
-      01, 
-      0B, 00, 
-      00, 
-      00, 
-      00, 
-      00, 
-      00, 
-      07, 
-      3B 00 00 07 00 07 00 00 00 FF 00 ]     
-     */
-
-    /**
-     * @see Object#toString()
-     */
-    public String toString() {
-        StringBuffer buffer = new StringBuffer();
-
-        buffer.append("[NAME]\n");
-        buffer.append("    .option flags         = ").append( HexDump.toHex( field_1_option_flag ) )
-            .append("\n");
-        buffer.append("    .keyboard shortcut    = ").append( HexDump.toHex( field_2_keyboard_shortcut ) )
-            .append("\n");
-        buffer.append("    .length of the name   = ").append( field_3_length_name_text )
-            .append("\n");
-        buffer.append("    .size of the formula data = ").append( field_4_length_name_definition )
-            .append("\n");
-        buffer.append("    .unused                   = ").append( field_5_index_to_sheet )
-            .append("\n");
-        buffer.append("    .index to sheet (1-based, 0=Global)           = ").append( field_6_equals_to_index_to_sheet )
-            .append("\n");
-        buffer.append("    .Length of menu text (character count)        = ").append( field_7_length_custom_menu )
-            .append("\n");
-        buffer.append("    .Length of description text (character count) = ").append( field_8_length_description_text )
-            .append("\n");
-        buffer.append("    .Length of help topic text (character count)  = ").append( field_9_length_help_topic_text )
-            .append("\n");
-        buffer.append("    .Length of status bar text (character count)  = ").append( field_10_length_status_bar_text )
-            .append("\n");
-        buffer.append("    .Name (Unicode flag)  = ").append( field_11_compressed_unicode_flag )
-            .append("\n");
-        buffer.append("    .Name (Unicode text)  = ").append( getNameText() )
-            .append("\n");
-        
-        buffer.append("    .Parts (" + field_13_name_definition.size() +"):")
-            .append("\n");
-        Iterator it = field_13_name_definition.iterator();
-        while(it.hasNext()) {
-               Ptg ptg = (Ptg)it.next();
-               buffer.append("       " + ptg.toString()).append("\n");
-        }
-        
-        buffer.append("    .Menu text (Unicode string without length field)        = ").append( field_14_custom_menu_text )
-            .append("\n");
-        buffer.append("    .Description text (Unicode string without length field) = ").append( field_15_description_text )
-            .append("\n");
-        buffer.append("    .Help topic text (Unicode string without length field)  = ").append( field_16_help_topic_text )
-            .append("\n");
-        buffer.append("    .Status bar text (Unicode string without length field)  = ").append( field_17_status_bar_text )
-            .append("\n");
-        buffer.append("[/NAME]\n");
-        
-        return buffer.toString();
-    }
+       /*
+         18, 00, 
+         1B, 00, 
+         
+         20, 00, 
+         00, 
+         01, 
+         0B, 00, 
+         00, 
+         00, 
+         00, 
+         00, 
+         00, 
+         07, 
+         3B 00 00 07 00 07 00 00 00 FF 00 ]     
+        */
+
+       /**
+        * @see Object#toString()
+        */
+       public String toString() {
+           StringBuffer buffer = new StringBuffer();
+
+           buffer.append("[NAME]\n");
+           buffer.append("    .option flags         = ").append( HexDump.toHex( field_1_option_flag ) )
+               .append("\n");
+           buffer.append("    .keyboard shortcut    = ").append( HexDump.toHex( field_2_keyboard_shortcut ) )
+               .append("\n");
+           buffer.append("    .length of the name   = ").append( field_3_length_name_text )
+               .append("\n");
+           buffer.append("    .size of the formula data = ").append( field_4_length_name_definition )
+               .append("\n");
+           buffer.append("    .unused                   = ").append( field_5_index_to_sheet )
+               .append("\n");
+           buffer.append("    .index to sheet (1-based, 0=Global)           = ").append( field_6_sheetNumber )
+               .append("\n");
+           buffer.append("    .Length of menu text (character count)        = ").append( field_7_length_custom_menu )
+               .append("\n");
+           buffer.append("    .Length of description text (character count) = ").append( field_8_length_description_text )
+               .append("\n");
+           buffer.append("    .Length of help topic text (character count)  = ").append( field_9_length_help_topic_text )
+               .append("\n");
+           buffer.append("    .Length of status bar text (character count)  = ").append( field_10_length_status_bar_text )
+               .append("\n");
+           buffer.append("    .Name (Unicode flag)  = ").append( field_11_compressed_unicode_flag )
+               .append("\n");
+           buffer.append("    .Name (Unicode text)  = ").append( getNameText() )
+               .append("\n");
+           
+           buffer.append("    .Parts (" + field_13_name_definition.size() +"):")
+               .append("\n");
+           Iterator it = field_13_name_definition.iterator();
+           while(it.hasNext()) {
+                       Ptg ptg = (Ptg)it.next();
+                       buffer.append("       " + ptg.toString()).append("\n");
+           }
+           
+           buffer.append("    .Menu text (Unicode string without length field)        = ").append( field_14_custom_menu_text )
+               .append("\n");
+           buffer.append("    .Description text (Unicode string without length field) = ").append( field_15_description_text )
+               .append("\n");
+           buffer.append("    .Help topic text (Unicode string without length field)  = ").append( field_16_help_topic_text )
+               .append("\n");
+           buffer.append("    .Status bar text (Unicode string without length field)  = ").append( field_17_status_bar_text )
+               .append("\n");
+           buffer.append("[/NAME]\n");
+           
+           return buffer.toString();
+       }
 
        /**Creates a human readable name for built in types
         * @return Unknown if the built-in name cannot be translated
index 5966c0d80fc46afc379e98e292019d5569bf24f6..0f8a14446a79f3bbe65a30e08e5394211ccf5513 100644 (file)
@@ -61,6 +61,9 @@ import java.util.Stack;
  */
 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;
 
     /**
@@ -835,7 +838,8 @@ public class HSSFWorkbook extends POIDocument
 
     /**
      * 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
      * workbook level.
      * <p>
@@ -865,10 +869,10 @@ public class HSSFWorkbook extends POIDocument
         // Check arguments
         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 (startColumn < -1 || startColumn >= 0xFF) throw new IllegalArgumentException("Invalid column range specification");
-        if (endColumn < -1 || endColumn >= 0xFF) throw new IllegalArgumentException("Invalid column range specification");
-        if (startRow < -1 || startRow > 65535) throw new IllegalArgumentException("Invalid row range specification");
-        if (endRow < -1 || endRow > 65535) throw new IllegalArgumentException("Invalid row range specification");
+        if (startColumn < -1 || startColumn >= MAX_COLUMN) throw new IllegalArgumentException("Invalid column range specification");
+        if (endColumn < -1 || endColumn >= MAX_COLUMN) throw new IllegalArgumentException("Invalid column range specification");
+        if (startRow < -1 || startRow > MAX_ROW) 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 (startRow > endRow) throw new IllegalArgumentException("Invalid row range specification");
 
@@ -880,50 +884,60 @@ public class HSSFWorkbook extends POIDocument
         boolean removingRange =
                 startColumn == -1 && endColumn == -1 && startRow == -1 && endRow == -1;
 
-        boolean isNewRecord = false;
-        NameRecord nameRecord;
-        nameRecord = findExistingRowColHeaderNameRecord(sheetIndex);
-        if (removingRange )
-        {
-            if (nameRecord != null)
-                workbook.removeName(findExistingRowColHeaderNameRecordIdx(sheetIndex+1));
+        int rowColHeaderNameIndex = findExistingRowColHeaderNameRecordIdx(sheetIndex);
+        if (removingRange) {
+            if (rowColHeaderNameIndex >= 0) {
+                workbook.removeName(rowColHeaderNameIndex);
+            }
             return;
         }
-        if ( nameRecord == null )
-        {
-            nameRecord = workbook.createBuiltInName(NameRecord.BUILTIN_PRINT_TITLE, sheetIndex+1);
+        boolean isNewRecord;
+        NameRecord nameRecord;
+        if (rowColHeaderNameIndex < 0) {
             //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;
+        } else {
+            nameRecord = workbook.getNameRecord(rowColHeaderNameIndex);
+            isNewRecord = false;
         }
 
         short definitionTextLength = settingRowAndColumn ? (short)0x001a : (short)0x000b;
-        nameRecord.setDefinitionTextLength(definitionTextLength);
+        nameRecord.setDefinitionTextLength(definitionTextLength); // TODO - remove
 
         Stack ptgs = new Stack();
 
-        if (settingRowAndColumn)
-        {
-            ptgs.add(new MemFuncPtg(23)); // TODO - where did constant '23' come from?
+        if (settingRowAndColumn) {
+            final int exprsSize = 2 * 11 + 1; // Area3DPtg.SIZE + UnionPtg.SIZE
+            ptgs.add(new MemFuncPtg(exprsSize));
         }
         if (startColumn >= 0)
         {
-            Area3DPtg area3DPtg1 = new Area3DPtg();
-            area3DPtg1.setExternSheetIndex(externSheetIndex);
-            area3DPtg1.setFirstColumn((short)startColumn);
-            area3DPtg1.setLastColumn((short)endColumn);
-            area3DPtg1.setFirstRow((short)0);
-            area3DPtg1.setLastRow((short)0xFFFF);
-            ptgs.add(area3DPtg1);
+            Area3DPtg colArea = new Area3DPtg();
+            colArea.setExternSheetIndex(externSheetIndex);
+            colArea.setFirstColumn((short)startColumn);
+            colArea.setLastColumn((short)endColumn);
+            colArea.setFirstRow(0);
+            colArea.setLastRow(MAX_ROW);
+            colArea.setFirstColRelative(false);
+            colArea.setLastColRelative(false);
+            colArea.setFirstRowRelative(false);
+            colArea.setLastRowRelative(false);
+            ptgs.add(colArea);
         }
         if (startRow >= 0)
         {
-            Area3DPtg area3DPtg2 = new Area3DPtg();
-            area3DPtg2.setExternSheetIndex(externSheetIndex);
-            area3DPtg2.setFirstColumn((short)0);
-            area3DPtg2.setLastColumn((short)0x00FF);
-            area3DPtg2.setFirstRow((short)startRow);
-            area3DPtg2.setLastRow((short)endRow);
-            ptgs.add(area3DPtg2);
+            Area3DPtg rowArea = new Area3DPtg();
+            rowArea.setExternSheetIndex(externSheetIndex);
+            rowArea.setFirstColumn((short)0);
+            rowArea.setLastColumn(MAX_COLUMN);
+            rowArea.setFirstRow(startRow);
+            rowArea.setLastRow(endRow);
+            rowArea.setFirstColRelative(false);
+            rowArea.setLastColRelative(false);
+            rowArea.setFirstRowRelative(false);
+            rowArea.setLastRowRelative(false);
+            ptgs.add(rowArea);
         }
         if (settingRowAndColumn)
         {
@@ -943,38 +957,31 @@ public class HSSFWorkbook extends POIDocument
         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 )
-    {
-        int index = 0;
-        NameRecord r = null;
-        while ((r = (NameRecord) workbook.findNextRecordBySid(NameRecord.sid, index)) != null)
-        {
-            int indexToSheet = r.getEqualsToIndexToSheet() -1;
-            if(indexToSheet > -1) { //ignore "GLOBAL" name records
-                int nameRecordSheetIndex = workbook.getSheetIndexFromExternSheetIndex(indexToSheet);
-                if (isRowColHeaderRecord( r ) && nameRecordSheetIndex == sheetIndex)
-                {
-                    return index;
-                }
+    private int findExistingRowColHeaderNameRecordIdx(int sheetIndex) {
+        for(int defNameIndex =0; defNameIndex<names.size(); defNameIndex++) {
+            NameRecord r = workbook.getNameRecord(defNameIndex);
+            if (r == null) {
+                throw new RuntimeException("Unable to find all defined names to iterate over");
+            }
+            if (!isRowColHeaderRecord( r )) {
+                continue;
+            }
+            if(r.getSheetNumber() == 0) {
+                //ignore "GLOBAL" name records
+                continue;
+            }
+            int externIndex = r.getSheetNumber() -1;
+            int nameRecordSheetIndex = workbook.getSheetIndexFromExternSheetIndex(externIndex);
+            if (nameRecordSheetIndex == sheetIndex) {
+                return defNameIndex;
             }
-            index++;
         }
-
         return -1;
     }
 
-    private boolean isRowColHeaderRecord( NameRecord r )
-    {
-        return r.getOptionFlag() == 0x20 && ("" + ((char)7)).equals(r.getNameText());
+    private static boolean isRowColHeaderRecord(NameRecord r) {
+        return r.isBuiltInName() && r.getBuiltInName() == NameRecord.BUILTIN_PRINT_TITLE;
     }
 
     /**
@@ -1068,7 +1075,7 @@ public class HSSFWorkbook extends POIDocument
      *  and that's not something you should normally do
      */
     protected void resetFontCache() {
-       fonts = new Hashtable();
+        fonts = new Hashtable();
     }
 
     /**
index a6143747a14d3593bb81b86d197d2714e4c9f0d4..caec8e897f8ab10470fb9314ad4d636476ef4b9f 100644 (file)
@@ -1013,7 +1013,7 @@ public final class TestBugs extends TestCase {
         Workbook w = wb.getWorkbook();
         for(int i=0; i<w.getNumNames(); i++) {
             NameRecord r = w.getNameRecord(i);
-            assertTrue(r.getIndexToSheet() <= wb.getNumberOfSheets());
+            assertTrue(r.getSheetNumber() <= wb.getNumberOfSheets());
             
             List nd = r.getNameDefinition();
             assertEquals(1, nd.size());
@@ -1031,7 +1031,7 @@ public final class TestBugs extends TestCase {
         
         for(int i=0; i<w.getNumNames(); i++) {
             NameRecord r = w.getNameRecord(i);
-            assertTrue(r.getIndexToSheet() <= wb.getNumberOfSheets());
+            assertTrue(r.getSheetNumber() <= wb.getNumberOfSheets());
             
             List nd = r.getNameDefinition();
             assertEquals(1, nd.size());
@@ -1048,7 +1048,7 @@ public final class TestBugs extends TestCase {
         
         for(int i=0; i<w.getNumNames(); i++) {
             NameRecord r = w.getNameRecord(i);
-            assertTrue(r.getIndexToSheet() <= wb.getNumberOfSheets());
+            assertTrue(r.getSheetNumber() <= wb.getNumberOfSheets());
             
             List nd = r.getNameDefinition();
             assertEquals(1, nd.size());
index d8b7cde29223c8e388fa2a3ada11421b1b57c521..35a2d955fb12fe5d4764274b328237f151fb46f7 100644 (file)
@@ -50,7 +50,7 @@ public final class TestHSSFWorkbook extends TestCase {
         b.createSheet();
         b.setRepeatingRowsAndColumns( 2, 0,1,-1,-1 );
         NameRecord nameRecord = b.getWorkbook().getNameRecord( 0 );
-        assertEquals( 3, nameRecord.getIndexToSheet() );
+        assertEquals(3, nameRecord.getSheetNumber());
     }
 
     public void testCaseInsensitiveNames() {
@@ -411,84 +411,84 @@ public final class TestHSSFWorkbook extends TestCase {
      *  that point to deleted sheets
      */
     public void testNamesToDeleteSheets() throws Exception {
-       HSSFWorkbook b = openSample("30978-deleted.xls");
-       assertEquals(3, b.getNumberOfNames());
-       
-       // Sheet 2 is deleted
-       assertEquals("Sheet1", b.getSheetName(0));
-       assertEquals("Sheet3", b.getSheetName(1));
-       
-       Area3DPtg ptg;
-       NameRecord nr;
-       HSSFName n;
-       
-       /* ======= Name pointing to deleted sheet ====== */
-       
-       // First at low level
-       nr = b.getWorkbook().getNameRecord(0);
-       assertEquals("On2", nr.getNameText());
-       assertEquals(0, nr.getIndexToSheet());
-       assertEquals(1, nr.getExternSheetNumber());
-       assertEquals(1, nr.getNameDefinition().size());
-       
-       ptg = (Area3DPtg)nr.getNameDefinition().get(0);
-       assertEquals(1, ptg.getExternSheetIndex());
-       assertEquals(0, ptg.getFirstColumn());
-       assertEquals(0, ptg.getFirstRow());
-       assertEquals(0, ptg.getLastColumn());
-       assertEquals(2, ptg.getLastRow());
-       
-       // Now at high level
-       n = b.getNameAt(0);
-       assertEquals("On2", n.getNameName());
-       assertEquals("", n.getSheetName());
-       assertEquals("#REF!$A$1:$A$3", n.getReference());
-       
-       
-       /* ======= Name pointing to 1st sheet ====== */
-       
-       // First at low level
-       nr = b.getWorkbook().getNameRecord(1);
-       assertEquals("OnOne", nr.getNameText());
-       assertEquals(0, nr.getIndexToSheet());
-       assertEquals(0, nr.getExternSheetNumber());
-       assertEquals(1, nr.getNameDefinition().size());
-       
-       ptg = (Area3DPtg)nr.getNameDefinition().get(0);
-       assertEquals(0, ptg.getExternSheetIndex());
-       assertEquals(0, ptg.getFirstColumn());
-       assertEquals(2, ptg.getFirstRow());
-       assertEquals(0, ptg.getLastColumn());
-       assertEquals(3, ptg.getLastRow());
-       
-       // Now at high level
-       n = b.getNameAt(1);
-       assertEquals("OnOne", n.getNameName());
-       assertEquals("Sheet1", n.getSheetName());
-       assertEquals("Sheet1!$A$3:$A$4", n.getReference());
-       
-       
-       /* ======= Name pointing to 3rd sheet ====== */
-       
-       // First at low level
-       nr = b.getWorkbook().getNameRecord(2);
-       assertEquals("OnSheet3", nr.getNameText());
-       assertEquals(0, nr.getIndexToSheet());
-       assertEquals(2, nr.getExternSheetNumber());
-       assertEquals(1, nr.getNameDefinition().size());
-       
-       ptg = (Area3DPtg)nr.getNameDefinition().get(0);
-       assertEquals(2, ptg.getExternSheetIndex());
-       assertEquals(0, ptg.getFirstColumn());
-       assertEquals(0, ptg.getFirstRow());
-       assertEquals(0, ptg.getLastColumn());
-       assertEquals(1, ptg.getLastRow());
-       
-       // Now at high level
-       n = b.getNameAt(2);
-       assertEquals("OnSheet3", n.getNameName());
-       assertEquals("Sheet3", n.getSheetName());
-       assertEquals("Sheet3!$A$1:$A$2", n.getReference());
+        HSSFWorkbook b = openSample("30978-deleted.xls");
+        assertEquals(3, b.getNumberOfNames());
+        
+        // Sheet 2 is deleted
+        assertEquals("Sheet1", b.getSheetName(0));
+        assertEquals("Sheet3", b.getSheetName(1));
+        
+        Area3DPtg ptg;
+        NameRecord nr;
+        HSSFName n;
+        
+        /* ======= Name pointing to deleted sheet ====== */
+        
+        // First at low level
+        nr = b.getWorkbook().getNameRecord(0);
+        assertEquals("On2", nr.getNameText());
+        assertEquals(0, nr.getSheetNumber());
+        assertEquals(1, nr.getExternSheetNumber());
+        assertEquals(1, nr.getNameDefinition().size());
+        
+        ptg = (Area3DPtg)nr.getNameDefinition().get(0);
+        assertEquals(1, ptg.getExternSheetIndex());
+        assertEquals(0, ptg.getFirstColumn());
+        assertEquals(0, ptg.getFirstRow());
+        assertEquals(0, ptg.getLastColumn());
+        assertEquals(2, ptg.getLastRow());
+        
+        // Now at high level
+        n = b.getNameAt(0);
+        assertEquals("On2", n.getNameName());
+        assertEquals("", n.getSheetName());
+        assertEquals("#REF!$A$1:$A$3", n.getReference());
+        
+        
+        /* ======= Name pointing to 1st sheet ====== */
+        
+        // First at low level
+        nr = b.getWorkbook().getNameRecord(1);
+        assertEquals("OnOne", nr.getNameText());
+        assertEquals(0, nr.getSheetNumber());
+        assertEquals(0, nr.getExternSheetNumber());
+        assertEquals(1, nr.getNameDefinition().size());
+        
+        ptg = (Area3DPtg)nr.getNameDefinition().get(0);
+        assertEquals(0, ptg.getExternSheetIndex());
+        assertEquals(0, ptg.getFirstColumn());
+        assertEquals(2, ptg.getFirstRow());
+        assertEquals(0, ptg.getLastColumn());
+        assertEquals(3, ptg.getLastRow());
+        
+        // Now at high level
+        n = b.getNameAt(1);
+        assertEquals("OnOne", n.getNameName());
+        assertEquals("Sheet1", n.getSheetName());
+        assertEquals("Sheet1!$A$3:$A$4", n.getReference());
+        
+        
+        /* ======= Name pointing to 3rd sheet ====== */
+        
+        // First at low level
+        nr = b.getWorkbook().getNameRecord(2);
+        assertEquals("OnSheet3", nr.getNameText());
+        assertEquals(0, nr.getSheetNumber());
+        assertEquals(2, nr.getExternSheetNumber());
+        assertEquals(1, nr.getNameDefinition().size());
+        
+        ptg = (Area3DPtg)nr.getNameDefinition().get(0);
+        assertEquals(2, ptg.getExternSheetIndex());
+        assertEquals(0, ptg.getFirstColumn());
+        assertEquals(0, ptg.getFirstRow());
+        assertEquals(0, ptg.getLastColumn());
+        assertEquals(1, ptg.getLastRow());
+        
+        // Now at high level
+        n = b.getNameAt(2);
+        assertEquals("OnSheet3", n.getNameName());
+        assertEquals("Sheet3", n.getSheetName());
+        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
      */
     public void testExtraDataAfterEOFRecord() {
-       try {
-               HSSFTestDataSamples.openSampleWorkbook("ex45582-22397.xls");
-       } catch (RecordFormatException e) {
-               if (e.getCause() instanceof LittleEndian.BufferUnderrunException) {
-                       throw new AssertionFailedError("Identified bug 45582");
-               }
-       }
-       }
+        try {
+            HSSFTestDataSamples.openSampleWorkbook("ex45582-22397.xls");
+        } catch (RecordFormatException e) {
+            if (e.getCause() instanceof LittleEndian.BufferUnderrunException) {
+                throw new AssertionFailedError("Identified bug 45582");
+            }
+        }
+    }
 }
index 0a508805db1e94f578817437a3bdfec37753cf29..2382a82359a22d8d28c3fa30820efe2a9253901b 100644 (file)
 
 package org.apache.poi.hssf.usermodel;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.IOException;
 
 import junit.framework.TestCase;
 
 import org.apache.poi.hssf.HSSFTestDataSamples;
 import org.apache.poi.hssf.util.AreaReference;
 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);
        }
 
-       public static void main(String[] args) {
-               junit.textui.TestRunner.run(TestNamedRange.class);
-       }
-
        /** Test of TestCase method, of class test.RangeTest. */
        public void testNamedRange() {
                HSSFWorkbook wb = openSample("Simple.xls");
@@ -411,7 +405,7 @@ public final class TestNamedRange extends TestCase {
                String cellValue = "TEST Value";
                HSSFWorkbook wb = new HSSFWorkbook();
                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
                HSSFName namedCell = wb.createName();
@@ -447,7 +441,7 @@ public final class TestNamedRange extends TestCase {
                String sname = "TestSheet", cname = "TestName", cvalue = "TestVal";
                HSSFWorkbook wb = new HSSFWorkbook();
                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
                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();
-               HSSFSheet sheet = wb.createSheet();
+               HSSFSheet sheet = wb.createSheet("FirstSheet");
                
-               for (int rowItem = 0; rowItem < 10; rowItem++) {
-                       HSSFRow r = sheet.createRow(rowItem);
-                       for (int column = 0; column < 2; column++) {
-                               HSSFCell cellItem = r.createCell((short) column);
-                               cellItem.setCellType(HSSFCell.CELL_TYPE_STRING);
-                               cellItem.setCellValue(new HSSFRichTextString("Some value here"));
-                               if (rowItem == 2) {
-                                       wb.setRepeatingRowsAndColumns(0, 0, 0, 0, 3 - 1);
-                                       sheet.createFreezePane(0, 3);
-                               } 
-                       }
+               // set repeating rows and columns twice for the first sheet
+               for (int i = 0; i < 2; i++) {
+                       wb.setRepeatingRowsAndColumns(0, 0, 0, 0, 3-1);
+                       sheet.createFreezePane(0, 3);
                }
-
-               assertEquals(2, wb.getNumberOfNames());
+               assertEquals(1, wb.getNumberOfNames());
                HSSFName nr1 = wb.getNameAt(0);
-               HSSFName nr2 = wb.getNameAt(1);
                
                assertEquals("Print_Titles", nr1.getNameName());
-               assertEquals("Sheet0!$A$1:$A$0,Sheet0!$A$1:$IV$3", nr1.getReference());
-               
-               assertEquals("Excel_Name_Record_Titles_1_1", nr2.getNameName());
-               assertEquals("Sheet0!$A$1:$A$0,Sheet0!$A$1:$IV$3", nr2.getReference());
+               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());
+               }
                
                // Save and re-open
-               ByteArrayOutputStream baos = new ByteArrayOutputStream();
-               wb.write(baos);
-               ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
-               HSSFWorkbook nwb = new HSSFWorkbook(new POIFSFileSystem(bais));
+               HSSFWorkbook nwb = HSSFTestDataSamples.writeOutAndReadBack(wb);
 
-               assertEquals(2, nwb.getNumberOfNames());
+               assertEquals(1, nwb.getNumberOfNames());
                nr1 = nwb.getNameAt(0);
-               nr2 = nwb.getNameAt(1);
                
-               // TODO -
-               //  should these references really have been corrected?
-               //  and if so, why not also above?
                assertEquals("Print_Titles", nr1.getNameName());
-               assertEquals("Sheet0!A:A,Sheet0!$A$1:$IV$3", nr1.getReference());
+               assertEquals("FirstSheet!A:A,FirstSheet!$A$1:$IV$3", nr1.getReference());
+               
+               // check that setting RR&C on a second sheet causes a new Print_Titles built-in
+               // name to be created
+               sheet = nwb.createSheet("SecondSheet");
+               nwb.setRepeatingRowsAndColumns(1, 1, 2, 0, 0);
+
+               assertEquals(2, nwb.getNumberOfNames());
+               HSSFName nr2 = nwb.getNameAt(1);
                
-               assertEquals("Excel_Name_Record_Titles_1_1", nr2.getNameName());
-               assertEquals("Sheet0!A:A,Sheet0!$A$1:$IV$3", nr2.getReference());
+               assertEquals("Print_Titles", nr2.getNameName());
+               assertEquals("SecondSheet!B:C,SecondSheet!$A$1:$IV$1", nr2.getReference());
                
-               // In case you fancy checking in excel, to ensure it
-               //  won't complain about the file now
-               FileOutputStream fout = new FileOutputStream(File.createTempFile("POI-45126-", ".xls"));
-               wb.write(fout);
-               fout.close();
+               if (false) {
+                       // In case you fancy checking in excel, to ensure it
+                       //  won't complain about the file now
+                       try {
+                               File tempFile = File.createTempFile("POI-45126-", ".xls");
+                               FileOutputStream fout = new FileOutputStream(tempFile);
+                               nwb.write(fout);
+                               fout.close();
+                               System.out.println("check out " + tempFile.getAbsolutePath());
+                       } catch (IOException e) {
+                               throw new RuntimeException(e);
+                       }
+               }
        }
 }