/** * 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]"; }
/** * Gets the sheet names * * @return an array of strings containing the sheet names */ public String[] getSheetNames() { String[] names = new String[boundsheets.size()]; BoundsheetRecord br = null; for (int i = 0; i < names.length; i++) { br = (BoundsheetRecord) boundsheets.get(i); names[i] = br.getName(); } return names; }
/** * Gets the sheet index in this workbook. Used when importing a sheet * * @param sheet the sheet * @return the 0-based sheet index, or -1 if it is not found */ public int getIndex(Sheet sheet) { String name = sheet.getName(); int index = -1; int pos = 0; for (Iterator i = boundsheets.iterator(); i.hasNext() && index == -1; ) { BoundsheetRecord br = (BoundsheetRecord) i.next(); if (br.getName().equals(name)) { index = pos; } else { pos++; } } return index; }
/** * Gets the sheet with the specified name from within this workbook * * @param name the sheet name * @return The sheet with the specified name, or null if it is not found */ public Sheet getSheet(String name) { // Iterate through the boundsheet records int pos = 0; boolean found = false; Iterator i = boundsheets.iterator(); BoundsheetRecord br = null; while (i.hasNext() && !found) { br = (BoundsheetRecord) i.next(); if (br.getName().equals(name)) { found = true; } else { pos++; } } return found ? getSheet(pos) : null; }
/** * 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]"; }
/** * 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); } } } }
/** * 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]"; }