Esempio n. 1
0
    @Override
    public void processRecord(final Record record) {
      switch (record.getSid()) {
        case BOFRecord.sid:
          // 开始解析到workboot sheet 等
          BOFRecord bof = (BOFRecord) record;
          if (bof.getType() == bof.TYPE_WORKBOOK) {
            // workbook
          } else if (bof.getType() == bof.TYPE_WORKSHEET) {
            // sheet
          }
          break;
        case BoundSheetRecord.sid:
          // 开始解析BundleSheet
          BoundSheetRecord bsr = (BoundSheetRecord) record;
          // bsr.getSheetname() 得到sheet name
          break;
        case RowRecord.sid:
          // 开始解析行
          RowRecord rowrec = (RowRecord) record;
          break;
        case NumberRecord.sid:
          // 解析一个Number类型的单元格值
          NumberRecord numrec = (NumberRecord) record;
          // numrec.getRow()  numrec.getColumn()   numrec.getValue()

          // 非第一行 第一列
          if (numrec.getRow() > 0 && numrec.getColumn() == 0) {
            current = new ExcelData();
            current.setId(Double.valueOf(numrec.getValue()).longValue());
          }
          break;
        case SSTRecord.sid:
          // SSTRecords存储了在Excel中使用的所有唯一String的数组
          sstrec = (SSTRecord) record;
          break;
        case LabelSSTRecord.sid:
          // 解析一个String类型的单元格值(存储在SSTRecord)
          LabelSSTRecord lrec = (LabelSSTRecord) record;

          if (lrec.getRow() > 0 && lrec.getColumn() == 1) {
            current.setContent(sstrec.getString(lrec.getSSTIndex()).getString());
            dataList.add(current);

            totalSize++;

            // 最后一个单元格时 判断是否该写了
            if (totalSize % batchSize == 0) {
              doBatchSave(dataList);
              dataList.clear();
            }
          }
          break;
      }
    }
Esempio n. 2
0
  /**
   * Constructor
   *
   * @param f the excel file
   * @param sst the shared string table
   * @param fr formatting records
   * @param sb the bof record which indicates the start of the sheet
   * @param wb the bof record which indicates the start of the sheet
   * @param nf the 1904 flag
   * @param wp the workbook which this sheet belongs to
   * @throws BiffException
   */
  DefaultSheet(
      File f,
      SSTRecord sst,
      FormattingRecords fr,
      BOFRecord sb,
      BOFRecord wb,
      boolean nf,
      WorkbookParser wp)
      throws BiffException {
    excelFile = f;
    sharedStrings = sst;
    formattingRecords = fr;
    sheetBof = sb;
    workbookBof = wb;
    columnInfosArray = new ArrayList();
    sharedFormulas = new ArrayList();
    hyperlinks = new ArrayList();
    rowProperties = new ArrayList(10);
    columnInfosInitialized = false;
    rowRecordsInitialized = false;
    nineteenFour = nf;
    workbook = wp;
    workbookSettings = workbook.getSettings();

    // Mark the position in the stream, and then skip on until the end
    startPosition = f.getPos();

    if (sheetBof.isChart()) {
      // Set the start pos to include the bof so the sheet reader can handle it
      startPosition -= (sheetBof.getLength() + 4);
    }

    Record r = null;
    int bofs = 1;

    while (bofs >= 1) {
      r = f.next();

      // use this form for quick performance
      if (r.getCode() == Type.EOF.value) {
        bofs--;
      }

      if (r.getCode() == Type.BOF.value) {
        bofs++;
      }
    }
  }
Esempio n. 3
0
  /**
   * 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.get(index);

      return br.getName();
    }

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

    int lastTab = externSheet.getLastTabIndex(index);

    if (sr.getType() == SupbookRecord.INTERNAL) {
      // It's an internal reference - get the name from the boundsheets list
      BoundsheetRecord br = (BoundsheetRecord) boundsheets.get(lastTab);

      return br.getName();
    } else if (sr.getType() == SupbookRecord.EXTERNAL) {
      // External reference - get the sheet name from the supbook record
      StringBuffer sb = new StringBuffer();
      sb.append('[');
      sb.append(sr.getFileName());
      sb.append(']');
      sb.append(sr.getSheetName(lastTab));
      return sb.toString();
    }

    // An unknown supbook - return unkown
    return "[UNKNOWN]";
  }
Esempio n. 4
0
  /** Reads in the contents of this sheet */
  final void readSheet() {
    // If this sheet contains only a chart, then set everything to
    // empty and do not bother parsing the sheet
    // Thanks to steve.brophy for spotting this
    if (!sheetBof.isWorksheet()) {
      numRows = 0;
      numCols = 0;
      cells = new Cell[0][0];
      //      return;
    }

    SheetReader reader =
        new SheetReader(
            excelFile,
            sharedStrings,
            formattingRecords,
            sheetBof,
            workbookBof,
            nineteenFour,
            workbook,
            startPosition,
            this);
    reader.read();

    // Take stuff that was read in
    numRows = reader.getNumRows();
    numCols = reader.getNumCols();
    cells = reader.getCells();
    rowProperties = reader.getRowProperties();
    columnInfosArray = reader.getColumnInfosArray();
    hyperlinks = reader.getHyperlinks();
    charts = reader.getCharts();
    mergedCells = reader.getMergedCells();
    header = reader.getHeader();
    footer = reader.getFooter();
    settings = reader.getSettings();
    settings.setHidden(hidden);
    rowBreaks = reader.getRowBreaks();
    workspaceOptions = reader.getWorkspaceOptions();

    reader = null;

    if (!workbookSettings.getGCDisabled()) {
      System.gc();
    }

    if (columnInfosArray.size() > 0) {
      ColumnInfoRecord cir = (ColumnInfoRecord) columnInfosArray.get(columnInfosArray.size() - 1);
      columnInfos = new ColumnInfoRecord[cir.getEndColumn() + 1];
    } else {
      columnInfos = new ColumnInfoRecord[0];
    }
  }
Esempio n. 5
0
  /**
   * Package protected function which gets the real internal sheet index based upon the external
   * sheet reference. This is used for extern sheet references which are specified in formulas
   *
   * @param index the external sheet reference
   * @return the actual sheet index
   */
  public int getLastExternalSheetIndex(int index) {
    // For biff7, the whole external reference thing works differently
    // Hopefully for our purposes sheet references will all be local
    if (workbookBof.isBiff7()) {
      return index;
    }

    Assert.verify(externSheet != null);

    int lastTab = externSheet.getLastTabIndex(index);

    return lastTab;
  }
  /**
   * 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.get(index);

      return br.getName();
    }

    int supbookIndex = externSheet.getSupbookIndex(index);
    SupbookRecord sr = (SupbookRecord) supbooks.get(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.get(lastTab);
        return br.getName();
      }
    } else if (sr.getType() == SupbookRecord.EXTERNAL) {
      // External reference - get the sheet name from the supbook record
      StringBuffer sb = new StringBuffer();
      java.io.File fl = new java.io.File(sr.getFileName());
      sb.append("'");
      sb.append(fl.getAbsolutePath());
      sb.append("[");
      sb.append(fl.getName());
      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]";
  }
Esempio n. 7
0
  /**
   * 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 void parse() throws BiffException, PasswordException {
    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();
    nameTable = 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
        Object[] rec = continueRecords.toArray();
        Record[] records = new Record[rec.length];
        System.arraycopy(rec, 0, records, 0, rec.length);

        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, namedRecords.size());
        } else {
          nr = new NameRecord(r, settings, namedRecords.size(), NameRecord.biff7);
        }

        namedRecords.put(nr.getName(), nr);
        nameTable.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) {
        PaletteRecord palette = new 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.getMessage());
        }
      } else if (r.getType() == Type.XF) {
        XFRecord xfr = null;
        if (bof.isBiff8()) {
          xfr = new XFRecord(r, XFRecord.biff8);
        } else {
          xfr = new XFRecord(r, XFRecord.biff7);
        }

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

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

        if (br.isSheet() || br.isChart()) {
          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.CODEPAGE) {
        CodepageRecord cr = new CodepageRecord(r);
        settings.setCharacterSet(cr.getCharacterSet());
      } else if (r.getType() == Type.SUPBOOK) {
        SupbookRecord sr = new SupbookRecord(r, settings);
        supbooks.add(sr);
      } else if (r.getType() == Type.PROTECT) {
        ProtectRecord pr = new ProtectRecord(r);
        wbProtected = pr.isProtected();
      } else if (r.getType() == Type.OBJPROJ) {
        containsMacros = true;
      } else if (r.getType() == Type.MSODRAWINGGROUP) {
        msoDrawingGroup = new MsoDrawingGroupRecord(r);

        if (drawingGroup == null) {
          drawingGroup = new DrawingGroup(DrawingGroup.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--;
      }
    }

    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.size()) {
      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.get(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.get(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);
        }
      }
    }
  }
Esempio n. 8
0
  /** Reads in the contents of this sheet */
  final void readSheet() {
    // If this sheet contains only a chart, then set everything to
    // empty and do not bother parsing the sheet
    // Thanks to steve.brophy for spotting this
    if (!sheetBof.isWorksheet()) {
      numRows = 0;
      numCols = 0;
      cells = new Cell[0][0];
      //      return;
    }

    SheetReader reader =
        new SheetReader(
            excelFile,
            sharedStrings,
            formattingRecords,
            sheetBof,
            workbookBof,
            nineteenFour,
            workbook,
            startPosition,
            this);
    reader.read();

    // Take stuff that was read in
    numRows = reader.getNumRows();
    numCols = reader.getNumCols();
    cells = reader.getCells();
    rowProperties = reader.getRowProperties();
    columnInfosArray = reader.getColumnInfosArray();
    hyperlinks = reader.getHyperlinks();
    conditionalFormats = reader.getConditionalFormats();
    autoFilter = reader.getAutoFilter();
    charts = reader.getCharts();
    drawings = reader.getDrawings();
    dataValidation = reader.getDataValidation();
    mergedCells = reader.getMergedCells();
    settings = reader.getSettings();
    settings.setHidden(hidden);
    rowBreaks = reader.getRowBreaks();
    columnBreaks = reader.getColumnBreaks();
    workspaceOptions = reader.getWorkspaceOptions();
    plsRecord = reader.getPLS();
    buttonPropertySet = reader.getButtonPropertySet();
    maxRowOutlineLevel = reader.getMaxRowOutlineLevel();
    maxColumnOutlineLevel = reader.getMaxColumnOutlineLevel();

    reader = null;

    if (!workbookSettings.getGCDisabled()) {
      System.gc();
    }

    if (columnInfosArray.size() > 0) {
      ColumnInfoRecord cir = (ColumnInfoRecord) columnInfosArray.get(columnInfosArray.size() - 1);
      columnInfos = new ColumnInfoRecord[cir.getEndColumn() + 1];
    } else {
      columnInfos = new ColumnInfoRecord[0];
    }

    // Add any local names
    if (localNames != null) {
      for (Iterator it = localNames.iterator(); it.hasNext(); ) {
        NameRecord nr = (NameRecord) it.next();
        if (nr.getBuiltInName() == BuiltInName.PRINT_AREA) {
          if (nr.getRanges().length > 0) {
            NameRecord.NameRange rng = nr.getRanges()[0];
            settings.setPrintArea(
                rng.getFirstColumn(), rng.getFirstRow(), rng.getLastColumn(), rng.getLastRow());
          }
        } else if (nr.getBuiltInName() == BuiltInName.PRINT_TITLES) {
          // There can be 1 or 2 entries.
          // Row entries have hardwired column entries (first and last
          //  possible column)
          // Column entries have hardwired row entries (first and last
          // possible row)
          for (int i = 0; i < nr.getRanges().length; i++) {
            NameRecord.NameRange rng = nr.getRanges()[i];
            if (rng.getFirstColumn() == 0 && rng.getLastColumn() == 255) {
              settings.setPrintTitlesRow(rng.getFirstRow(), rng.getLastRow());
            } else {
              settings.setPrintTitlesCol(rng.getFirstColumn(), rng.getLastColumn());
            }
          }
        }
      }
    }
  }
  /**
   * Does the hard work of building up the object graph from the excel bytes
   *
   * @exception BiffException
   * @exception PasswordException if the workbook is password protected
   */
  public void parse() throws BiffException, PasswordException {
    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.size()];
        records = (Record[]) continueRecords.toArray(records);

        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.size());

        } else {
          nr = new NameRecord(r, settings, nameTable.size(), 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.put(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) {
        PaletteRecord palette = new 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.getMessage());
        }
      } 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.getMessage());
        }
      } 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) {
        containsMacros = 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.size()) {
      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.get(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.get(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
    for (Iterator it = localNames.iterator(); it.hasNext(); ) {
      NameRecord nr = (NameRecord) it.next();

      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.get(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.get(index);

      return br.getName();
    }

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

    int firstTab = externSheet.getFirstTabIndex(index);
    int lastTab = externSheet.getLastTabIndex(index);
    String firstTabName = "";
    String lastTabName = "";

    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.get(firstTab);
        firstTabName = br.getName();
      }

      if (lastTab == 65535) {
        lastTabName = "#REF";
      } else {
        BoundsheetRecord br = (BoundsheetRecord) boundsheets.get(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(' ') == -1 ? sheetName : '\'' + sheetName + '\'';
    } else if (sr.getType() == SupbookRecord.EXTERNAL) {
      // External reference - get the sheet name from the supbook record
      StringBuffer sb = new StringBuffer();
      java.io.File fl = new java.io.File(sr.getFileName());
      sb.append("'");
      sb.append(fl.getAbsolutePath());
      sb.append("[");
      sb.append(fl.getName());
      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]";
  }