/**
         * Gets the sheet names
         *
         * @return an array of strings containing the sheet names
         */
        public override string[] getSheetNames()
        {
            string[] names = new string[boundsheets.Count];

            BoundsheetRecord br = null;

            for (int i = 0; i < names.Length; i++)
            {
                br       = (BoundsheetRecord)boundsheets[i];
                names[i] = br.getName();
            }

            return(names);
        }
        /**
         * Gets the name of the external sheet specified by the index
         *
         * @param index the external sheet index
         * @return the name of the external sheet
         */
        public string getLastExternalSheetName(int index)
        {
            // For biff7, the whole external reference thing works differently
            // Hopefully for our purposes sheet references will all be local
            if (workbookBof.isBiff7())
            {
                BoundsheetRecord br = (BoundsheetRecord)boundsheets[index];

                return(br.getName());
            }

            int           supbookIndex = externSheet.getSupbookIndex(index);
            SupbookRecord sr           = (SupbookRecord)supbooks[supbookIndex];

            int lastTab = externSheet.getLastTabIndex(index);

            if (sr.getType() == SupbookRecord.INTERNAL)
            {
                // It's an internal reference - get the name from the boundsheets list
                if (lastTab == 65535)
                {
                    return("#REF");
                }
                else
                {
                    BoundsheetRecord br = (BoundsheetRecord)boundsheets[lastTab];
                    return(br.getName());
                }
            }
            else if (sr.getType() == SupbookRecord.EXTERNAL)
            {
                // External reference - get the sheet name from the supbook record
                StringBuilder sb = new StringBuilder();
                FileInfo      fl = new FileInfo(sr.getFileName());
                sb.Append("'");
                sb.Append(fl.FullName);                         // getAbsolutePath
                sb.Append("[");
                sb.Append(fl.Name);
                sb.Append("]");
                sb.Append((lastTab == 65535) ? "#REF" : sr.getSheetName(lastTab));
                sb.Append("'");
                return(sb.ToString());
            }

            // An unknown supbook - return unkown
            //logger.warn("Unknown Supbook 4");
            return("[UNKNOWN]");
        }
        /**
         * Does the hard work of building up the object graph from the excel bytes
         *
         * @exception BiffException
         * @exception PasswordException if the workbook is password protected
         */
        protected override void parse()
        {
            Record r = null;

            BOFRecord bof = new BOFRecord(excelFile.next());

            workbookBof = bof;
            bofs++;

            if (!bof.isBiff8() && !bof.isBiff7())
            {
                throw new BiffException(BiffException.unrecognizedBiffVersion);
            }

            if (!bof.isWorkbookGlobals())
            {
                throw new BiffException(BiffException.expectedGlobals);
            }
            ArrayList continueRecords = new ArrayList();
            ArrayList localNames      = new ArrayList();

            nameTable      = new ArrayList();
            addInFunctions = new ArrayList();

            // Skip to the first worksheet
            while (bofs == 1)
            {
                r = excelFile.next();

                if (r.getType() == Type.SST)
                {
                    continueRecords.Clear();
                    Record nextrec = excelFile.peek();
                    while (nextrec.getType() == Type.CONTINUE)
                    {
                        continueRecords.Add(excelFile.next());
                        nextrec = excelFile.peek();
                    }

                    // cast the array
                    Record[] records = new Record[continueRecords.Count];
                    int      pos     = 0;
                    foreach (Record record in continueRecords)
                    {
                        records[pos++] = record;
                    }

                    sharedStrings = new SSTRecord(r, records, settings);
                }
                else if (r.getType() == Type.FILEPASS)
                {
                    throw new PasswordException();
                }
                else if (r.getType() == Type.NAME)
                {
                    NameRecord nr = null;

                    if (bof.isBiff8())
                    {
                        nr = new NameRecord(r, settings, nameTable.Count);
                    }
                    else
                    {
                        nr = new NameRecord(r, settings, nameTable.Count,
                                            NameRecord.biff7);
                    }

                    // Add all local and global names to the name table in order to
                    // preserve the indexing
                    nameTable.Add(nr);

                    if (nr.isGlobal())
                    {
                        namedRecords.Add(nr.getName(), nr);
                    }
                    else
                    {
                        localNames.Add(nr);
                    }
                }
                else if (r.getType() == Type.FONT)
                {
                    FontRecord fr = null;

                    if (bof.isBiff8())
                    {
                        fr = new FontRecord(r, settings);
                    }
                    else
                    {
                        fr = new FontRecord(r, settings, FontRecord.biff7);
                    }
                    fonts.addFont(fr);
                }
                else if (r.getType() == Type.PALETTE)
                {
                    CSharpJExcel.Jxl.Biff.PaletteRecord palette = new CSharpJExcel.Jxl.Biff.PaletteRecord(r);
                    formattingRecords.setPalette(palette);
                }
                else if (r.getType() == Type.NINETEENFOUR)
                {
                    NineteenFourRecord nr = new NineteenFourRecord(r);
                    nineteenFour = nr.is1904();
                }
                else if (r.getType() == Type.FORMAT)
                {
                    FormatRecord fr = null;
                    if (bof.isBiff8())
                    {
                        fr = new FormatRecord(r, settings, FormatRecord.biff8);
                    }
                    else
                    {
                        fr = new FormatRecord(r, settings, FormatRecord.biff7);
                    }
                    try
                    {
                        formattingRecords.addFormat(fr);
                    }
                    catch (NumFormatRecordsException e)
                    {
                        // This should not happen.  Bomb out
                        Assert.verify(false, e.Message);
                    }
                }
                else if (r.getType() == Type.XF)
                {
                    XFRecord xfr = null;
                    if (bof.isBiff8())
                    {
                        xfr = new XFRecord(r, settings, XFRecord.biff8);
                    }
                    else
                    {
                        xfr = new XFRecord(r, settings, XFRecord.biff7);
                    }

                    try
                    {
                        formattingRecords.addStyle(xfr);
                    }
                    catch (NumFormatRecordsException e)
                    {
                        // This should not happen.  Bomb out
                        Assert.verify(false, e.Message);
                    }
                }
                else if (r.getType() == Type.BOUNDSHEET)
                {
                    BoundsheetRecord br = null;

                    if (bof.isBiff8())
                    {
                        br = new BoundsheetRecord(r, settings);
                    }
                    else
                    {
                        br = new BoundsheetRecord(r, BoundsheetRecord.biff7);
                    }

                    if (br.isSheet())
                    {
                        boundsheets.Add(br);
                    }
                    else if (br.isChart() && !settings.getDrawingsDisabled())
                    {
                        boundsheets.Add(br);
                    }
                }
                else if (r.getType() == Type.EXTERNSHEET)
                {
                    if (bof.isBiff8())
                    {
                        externSheet = new ExternalSheetRecord(r, settings);
                    }
                    else
                    {
                        externSheet = new ExternalSheetRecord(r, settings, ExternalSheetRecord.biff7);
                    }
                }
                else if (r.getType() == Type.XCT)
                {
                    XCTRecord xctr = new XCTRecord(r);
                    xctRecords.Add(xctr);
                }
                else if (r.getType() == Type.CODEPAGE)
                {
                    CodepageRecord cr = new CodepageRecord(r);
                    settings.setCharacterSet(cr.getCharacterSet());
                }
                else if (r.getType() == Type.SUPBOOK)
                {
                    Record nextrec = excelFile.peek();
                    while (nextrec.getType() == Type.CONTINUE)
                    {
                        r.addContinueRecord(excelFile.next());
                        nextrec = excelFile.peek();
                    }

                    SupbookRecord sr = new SupbookRecord(r, settings);
                    supbooks.Add(sr);
                }
                else if (r.getType() == Type.EXTERNNAME)
                {
                    ExternalNameRecord enr = new ExternalNameRecord(r, settings);

                    if (enr.isAddInFunction())
                    {
                        addInFunctions.Add(enr.getName());
                    }
                }
                else if (r.getType() == Type.PROTECT)
                {
                    ProtectRecord pr = new ProtectRecord(r);
                    wbProtected = pr.isProtected();
                }
                else if (r.getType() == Type.OBJPROJ)
                {
                    doesContainMacros = true;
                }
                else if (r.getType() == Type.COUNTRY)
                {
                    countryRecord = new CountryRecord(r);
                }
                else if (r.getType() == Type.MSODRAWINGGROUP)
                {
                    if (!settings.getDrawingsDisabled())
                    {
                        msoDrawingGroup = new MsoDrawingGroupRecord(r);

                        if (drawingGroup == null)
                        {
                            drawingGroup = new DrawingGroup(Origin.READ);
                        }

                        drawingGroup.add(msoDrawingGroup);

                        Record nextrec = excelFile.peek();
                        while (nextrec.getType() == Type.CONTINUE)
                        {
                            drawingGroup.add(excelFile.next());
                            nextrec = excelFile.peek();
                        }
                    }
                }
                else if (r.getType() == Type.BUTTONPROPERTYSET)
                {
                    buttonPropertySet = new ButtonPropertySetRecord(r);
                }
                else if (r.getType() == Type.EOF)
                {
                    bofs--;
                }
                else if (r.getType() == Type.REFRESHALL)
                {
                    RefreshAllRecord rfm = new RefreshAllRecord(r);
                    settings.setRefreshAll(rfm.getRefreshAll());
                }
                else if (r.getType() == Type.TEMPLATE)
                {
                    TemplateRecord rfm = new TemplateRecord(r);
                    settings.setTemplate(rfm.getTemplate());
                }
                else if (r.getType() == Type.EXCEL9FILE)
                {
                    Excel9FileRecord e9f = new Excel9FileRecord(r);
                    settings.setExcel9File(e9f.getExcel9File());
                }
                else if (r.getType() == Type.WINDOWPROTECT)
                {
                    WindowProtectedRecord winp = new WindowProtectedRecord(r);
                    settings.setWindowProtected(winp.getWindowProtected());
                }
                else if (r.getType() == Type.HIDEOBJ)
                {
                    HideobjRecord hobj = new HideobjRecord(r);
                    settings.setHideobj(hobj.getHideMode());
                }
                else if (r.getType() == Type.WRITEACCESS)
                {
                    WriteAccessRecord war = new WriteAccessRecord(r, bof.isBiff8(), settings);
                    settings.setWriteAccess(war.getWriteAccess());
                }
                else
                {
                    // logger.info("Unsupported record type: " +
                    //            Integer.toHexString(r.getCode())+"h");
                }
            }

            bof = null;
            if (excelFile.hasNext())
            {
                r = excelFile.next();

                if (r.getType() == Type.BOF)
                {
                    bof = new BOFRecord(r);
                }
            }

            // Only get sheets for which there is a corresponding Boundsheet record
            while (bof != null && getNumberOfSheets() < boundsheets.Count)
            {
                if (!bof.isBiff8() && !bof.isBiff7())
                {
                    throw new BiffException(BiffException.unrecognizedBiffVersion);
                }

                if (bof.isWorksheet())
                {
                    // Read the sheet in
                    SheetImpl s = new SheetImpl(excelFile,
                                                sharedStrings,
                                                formattingRecords,
                                                bof,
                                                workbookBof,
                                                nineteenFour,
                                                this);

                    BoundsheetRecord br = (BoundsheetRecord)boundsheets[getNumberOfSheets()];
                    s.setName(br.getName());
                    s.setHidden(br.isHidden());
                    addSheet(s);
                }
                else if (bof.isChart())
                {
                    // Read the sheet in
                    SheetImpl s = new SheetImpl(excelFile,
                                                sharedStrings,
                                                formattingRecords,
                                                bof,
                                                workbookBof,
                                                nineteenFour,
                                                this);

                    BoundsheetRecord br = (BoundsheetRecord)boundsheets[getNumberOfSheets()];
                    s.setName(br.getName());
                    s.setHidden(br.isHidden());
                    addSheet(s);
                }
                else
                {
                    //logger.warn("BOF is unrecognized");


                    while (excelFile.hasNext() && r.getType() != Type.EOF)
                    {
                        r = excelFile.next();
                    }
                }

                // The next record will normally be a BOF or empty padding until
                // the end of the block is reached.  In exceptionally unlucky cases,
                // the last EOF  will coincide with a block division, so we have to
                // check there is more data to retrieve.
                // Thanks to liamg for spotting this
                bof = null;
                if (excelFile.hasNext())
                {
                    r = excelFile.next();

                    if (r.getType() == Type.BOF)
                    {
                        bof = new BOFRecord(r);
                    }
                }
            }

            // Add all the local names to the specific sheets
            foreach (NameRecord nr in localNames)
            {
                if (nr.getBuiltInName() == null)
                {
                    //logger.warn("Usage of a local non-builtin name");
                }
                else if (nr.getBuiltInName() == BuiltInName.PRINT_AREA ||
                         nr.getBuiltInName() == BuiltInName.PRINT_TITLES)
                {
                    // appears to use the internal tab number rather than the
                    // external sheet index
                    SheetImpl s = (SheetImpl)sheets[nr.getSheetRef() - 1];
                    s.addLocalName(nr);
                }
            }
        }
        /**
         * Gets the name of the external sheet specified by the index
         *
         * @param index the external sheet index
         * @return the name of the external sheet
         */
        public string getExternalSheetName(int index)
        {
            // For biff7, the whole external reference thing works differently
            // Hopefully for our purposes sheet references will all be local
            if (workbookBof.isBiff7())
            {
                BoundsheetRecord br = (BoundsheetRecord)boundsheets[index];

                return(br.getName());
            }

            int           supbookIndex = externSheet.getSupbookIndex(index);
            SupbookRecord sr           = (SupbookRecord)supbooks[supbookIndex];

            int    firstTab     = externSheet.getFirstTabIndex(index);
            int    lastTab      = externSheet.getLastTabIndex(index);
            string firstTabName = string.Empty;
            string lastTabName  = string.Empty;

            if (sr.getType() == SupbookRecord.INTERNAL)
            {
                // It's an internal reference - get the name from the boundsheets list
                if (firstTab == 65535)
                {
                    firstTabName = "#REF";
                }
                else
                {
                    BoundsheetRecord br = (BoundsheetRecord)boundsheets[firstTab];
                    firstTabName = br.getName();
                }

                if (lastTab == 65535)
                {
                    lastTabName = "#REF";
                }
                else
                {
                    BoundsheetRecord br = (BoundsheetRecord)boundsheets[lastTab];
                    lastTabName = br.getName();
                }

                string sheetName = (firstTab == lastTab) ? firstTabName :
                                   firstTabName + ':' + lastTabName;

                // if the sheet name contains apostrophes then escape them
                sheetName = sheetName.IndexOf('\'') == -1 ? sheetName :
                            StringHelper.replace(sheetName, "\'", "\'\'");


                // if the sheet name contains spaces, then enclose in quotes
                return(sheetName.IndexOf(' ') < 0 ? sheetName : '\'' + sheetName + '\'');
            }
            else if (sr.getType() == SupbookRecord.EXTERNAL)
            {
                // External reference - get the sheet name from the supbook record
                StringBuilder sb = new StringBuilder();
                FileInfo      fl = new FileInfo(sr.getFileName());
                sb.Append("'");
                sb.Append(fl.FullName);                         // .getAbsolutePath
                sb.Append("[");
                sb.Append(fl.Name);
                sb.Append("]");
                sb.Append((firstTab == 65535) ? "#REF" : sr.getSheetName(firstTab));
                if (lastTab != firstTab)
                {
                    sb.Append(sr.getSheetName(lastTab));
                }
                sb.Append("'");
                return(sb.ToString());
            }

            // An unknown supbook - return unkown
            //logger.warn("Unknown Supbook 3");
            return("[UNKNOWN]");
        }
        /**
         * Does the hard work of building up the object graph from the excel bytes
         *
         * @exception BiffException
         * @exception PasswordException if the workbook is password protected
         */
        protected override void parse()
        {
            Record r = null;

            BOFRecord bof = new BOFRecord(excelFile.next());
            workbookBof = bof;
            bofs++;

            if (!bof.isBiff8() && !bof.isBiff7())
                {
                throw new BiffException(BiffException.unrecognizedBiffVersion);
                }

            if (!bof.isWorkbookGlobals())
                {
                throw new BiffException(BiffException.expectedGlobals);
                }
            ArrayList continueRecords = new ArrayList();
            ArrayList localNames = new ArrayList();
            nameTable = new ArrayList();
            addInFunctions = new ArrayList();

            // Skip to the first worksheet
            while (bofs == 1)
                {
                r = excelFile.next();

                if (r.getType() == Type.SST)
                    {
                    continueRecords.Clear();
                    Record nextrec = excelFile.peek();
                    while (nextrec.getType() == Type.CONTINUE)
                        {
                        continueRecords.Add(excelFile.next());
                        nextrec = excelFile.peek();
                        }

                    // cast the array
                    Record[] records = new Record[continueRecords.Count];
                    int pos = 0;
                    foreach (Record record in continueRecords)
                        records[pos++] = record;

                    sharedStrings = new SSTRecord(r,records,settings);
                    }
                else if (r.getType() == Type.FILEPASS)
                    {
                    throw new PasswordException();
                    }
                else if (r.getType() == Type.NAME)
                    {
                    NameRecord nr = null;

                    if (bof.isBiff8())
                        {
                        nr = new NameRecord(r,settings,nameTable.Count);

                        }
                    else
                        {
                        nr = new NameRecord(r,settings,nameTable.Count,
                                            NameRecord.biff7);
                        }

                    // Add all local and global names to the name table in order to
                    // preserve the indexing
                    nameTable.Add(nr);

                    if (nr.isGlobal())
                        namedRecords.Add(nr.getName(),nr);
                    else
                        localNames.Add(nr);
                    }
                else if (r.getType() == Type.FONT)
                    {
                    FontRecord fr = null;

                    if (bof.isBiff8())
                        fr = new FontRecord(r,settings);
                    else
                        fr = new FontRecord(r,settings,FontRecord.biff7);
                    fonts.addFont(fr);
                    }
                else if (r.getType() == Type.PALETTE)
                    {
                    CSharpJExcel.Jxl.Biff.PaletteRecord palette = new CSharpJExcel.Jxl.Biff.PaletteRecord(r);
                    formattingRecords.setPalette(palette);
                    }
                else if (r.getType() == Type.NINETEENFOUR)
                    {
                    NineteenFourRecord nr = new NineteenFourRecord(r);
                    nineteenFour = nr.is1904();
                    }
                else if (r.getType() == Type.FORMAT)
                    {
                    FormatRecord fr = null;
                    if (bof.isBiff8())
                        fr = new FormatRecord(r,settings,FormatRecord.biff8);
                    else
                        fr = new FormatRecord(r,settings,FormatRecord.biff7);
                    try
                        {
                        formattingRecords.addFormat(fr);
                        }
                    catch (NumFormatRecordsException e)
                        {
                        // This should not happen.  Bomb out
                        Assert.verify(false,e.Message);
                        }
                    }
                else if (r.getType() == Type.XF)
                    {
                    XFRecord xfr = null;
                    if (bof.isBiff8())
                        xfr = new XFRecord(r,settings,XFRecord.biff8);
                    else
                        xfr = new XFRecord(r,settings,XFRecord.biff7);

                    try
                        {
                        formattingRecords.addStyle(xfr);
                        }
                    catch (NumFormatRecordsException e)
                        {
                        // This should not happen.  Bomb out
                        Assert.verify(false,e.Message);
                        }
                    }
                else if (r.getType() == Type.BOUNDSHEET)
                    {
                    BoundsheetRecord br = null;

                    if (bof.isBiff8())
                        br = new BoundsheetRecord(r,settings);
                    else
                        br = new BoundsheetRecord(r,BoundsheetRecord.biff7);

                    if (br.isSheet())
                        boundsheets.Add(br);
                    else if (br.isChart() && !settings.getDrawingsDisabled())
                        boundsheets.Add(br);
                    }
                else if (r.getType() == Type.EXTERNSHEET)
                    {
                    if (bof.isBiff8())
                        externSheet = new ExternalSheetRecord(r,settings);
                    else
                        externSheet = new ExternalSheetRecord(r,settings,ExternalSheetRecord.biff7);
                    }
                else if (r.getType() == Type.XCT)
                    {
                    XCTRecord xctr = new XCTRecord(r);
                    xctRecords.Add(xctr);
                    }
                else if (r.getType() == Type.CODEPAGE)
                    {
                    CodepageRecord cr = new CodepageRecord(r);
                    settings.setCharacterSet(cr.getCharacterSet());
                    }
                else if (r.getType() == Type.SUPBOOK)
                    {
                    Record nextrec = excelFile.peek();
                    while (nextrec.getType() == Type.CONTINUE)
                        {
                        r.addContinueRecord(excelFile.next());
                        nextrec = excelFile.peek();
                        }

                    SupbookRecord sr = new SupbookRecord(r,settings);
                    supbooks.Add(sr);
                    }
                else if (r.getType() == Type.EXTERNNAME)
                    {
                    ExternalNameRecord enr = new ExternalNameRecord(r,settings);

                    if (enr.isAddInFunction())
                        {
                        addInFunctions.Add(enr.getName());
                        }
                    }
                else if (r.getType() == Type.PROTECT)
                    {
                    ProtectRecord pr = new ProtectRecord(r);
                    wbProtected = pr.isProtected();
                    }
                else if (r.getType() == Type.OBJPROJ)
                    {
                    doesContainMacros = true;
                    }
                else if (r.getType() == Type.COUNTRY)
                    {
                    countryRecord = new CountryRecord(r);
                    }
                else if (r.getType() == Type.MSODRAWINGGROUP)
                    {
                    if (!settings.getDrawingsDisabled())
                        {
                        msoDrawingGroup = new MsoDrawingGroupRecord(r);

                        if (drawingGroup == null)
                            {
                            drawingGroup = new DrawingGroup(Origin.READ);
                            }

                        drawingGroup.add(msoDrawingGroup);

                        Record nextrec = excelFile.peek();
                        while (nextrec.getType() == Type.CONTINUE)
                            {
                            drawingGroup.add(excelFile.next());
                            nextrec = excelFile.peek();
                            }
                        }
                    }
                else if (r.getType() == Type.BUTTONPROPERTYSET)
                    buttonPropertySet = new ButtonPropertySetRecord(r);
                else if (r.getType() == Type.EOF)
                    bofs--;
                else if (r.getType() == Type.REFRESHALL)
                    {
                    RefreshAllRecord rfm = new RefreshAllRecord(r);
                    settings.setRefreshAll(rfm.getRefreshAll());
                    }
                else if (r.getType() == Type.TEMPLATE)
                    {
                    TemplateRecord rfm = new TemplateRecord(r);
                    settings.setTemplate(rfm.getTemplate());
                    }
                else if (r.getType() == Type.EXCEL9FILE)
                    {
                    Excel9FileRecord e9f = new Excel9FileRecord(r);
                    settings.setExcel9File(e9f.getExcel9File());
                    }
                else if (r.getType() == Type.WINDOWPROTECT)
                    {
                    WindowProtectedRecord winp = new WindowProtectedRecord(r);
                    settings.setWindowProtected(winp.getWindowProtected());
                    }
                else if (r.getType() == Type.HIDEOBJ)
                    {
                    HideobjRecord hobj = new HideobjRecord(r);
                    settings.setHideobj(hobj.getHideMode());
                    }
                else if (r.getType() == Type.WRITEACCESS)
                    {
                    WriteAccessRecord war = new WriteAccessRecord(r,bof.isBiff8(),settings);
                    settings.setWriteAccess(war.getWriteAccess());
                    }
                else
                    {
                    // logger.info("Unsupported record type: " +
                    //            Integer.toHexString(r.getCode())+"h");
                    }
                }

            bof = null;
            if (excelFile.hasNext())
                {
                r = excelFile.next();

                if (r.getType() == Type.BOF)
                    bof = new BOFRecord(r);
                }

            // Only get sheets for which there is a corresponding Boundsheet record
            while (bof != null && getNumberOfSheets() < boundsheets.Count)
                {
                if (!bof.isBiff8() && !bof.isBiff7())
                    throw new BiffException(BiffException.unrecognizedBiffVersion);

                if (bof.isWorksheet())
                    {
                    // Read the sheet in
                    SheetImpl s = new SheetImpl(excelFile,
                                                sharedStrings,
                                                formattingRecords,
                                                bof,
                                                workbookBof,
                                                nineteenFour,
                                                this);

                    BoundsheetRecord br = (BoundsheetRecord)boundsheets[getNumberOfSheets()];
                    s.setName(br.getName());
                    s.setHidden(br.isHidden());
                    addSheet(s);
                    }
                else if (bof.isChart())
                    {
                    // Read the sheet in
                    SheetImpl s = new SheetImpl(excelFile,
                                                sharedStrings,
                                                formattingRecords,
                                                bof,
                                                workbookBof,
                                                nineteenFour,
                                                this);

                    BoundsheetRecord br = (BoundsheetRecord)boundsheets[getNumberOfSheets()];
                    s.setName(br.getName());
                    s.setHidden(br.isHidden());
                    addSheet(s);
                    }
                else
                    {
                    //logger.warn("BOF is unrecognized");

                    while (excelFile.hasNext() && r.getType() != Type.EOF)
                        r = excelFile.next();
                    }

                // The next record will normally be a BOF or empty padding until
                // the end of the block is reached.  In exceptionally unlucky cases,
                // the last EOF  will coincide with a block division, so we have to
                // check there is more data to retrieve.
                // Thanks to liamg for spotting this
                bof = null;
                if (excelFile.hasNext())
                    {
                    r = excelFile.next();

                    if (r.getType() == Type.BOF)
                        bof = new BOFRecord(r);
                    }
                }

            // Add all the local names to the specific sheets
            foreach (NameRecord nr in localNames)
                {
                if (nr.getBuiltInName() == null)
                    {
                    //logger.warn("Usage of a local non-builtin name");
                    }
                else if (nr.getBuiltInName() == BuiltInName.PRINT_AREA ||
                         nr.getBuiltInName() == BuiltInName.PRINT_TITLES)
                    {
                    // appears to use the internal tab number rather than the
                    // external sheet index
                    SheetImpl s = (SheetImpl)sheets[nr.getSheetRef() - 1];
                    s.addLocalName(nr);
                    }
                }
        }