public WorkbookStream InsertRecord(BiffRecord recordToInsert, BiffRecord insertAfterRecord = null) { return(InsertRecords(new List <BiffRecord>() { recordToInsert }, insertAfterRecord)); }
public long GetRecordByteOffset(BiffRecord record) { int listOffset = GetRecordOffset(record); //Size of BiffRecord is 4 (header) + Length return(_biffRecords.Take(listOffset).Sum(r => r.Length + 4)); }
public static string ToHexDumpString(this BiffRecord record, int maxLength = 0x10, bool showAttrInfo = false) { string biffString = record.ToString(); //Skip the 4 byte header byte[] bytes = record.GetBytes().Skip(4).ToArray(); string hexDumpString = HexDump(bytes); if (record is Formula) { biffString = ((Formula)record).ToFormulaString(showAttrInfo); } else if (record.Id == RecordType.Dimensions) { biffString = record.AsRecordType <Dimensions>().ToString(); } else if (record.Id == RecordType.Lbl) { biffString = ((Lbl)record).ToString(); } if ((bytes.Length <= maxLength && bytes.Length > 0) || record.Id == RecordType.Obj) { biffString += "\n" + hexDumpString; } return(biffString); }
public WorkbookStream InitializeGlobalStreamLabels() { List <BoundSheet8> sheets = WbStream.GetAllRecordsByType <BoundSheet8>(); BiffRecord lastCountryRecord = WbStream.GetAllRecordsByType <Country>().Last(); SupBook supBookRecord = new SupBook(sheets.Count, 0x401); int macroOffset = sheets.TakeWhile(s => s.dt != BoundSheet8.SheetType.Macrosheet).Count(); ExternSheet externSheetRecord = new ExternSheet(1, new List <XTI>() { new XTI(0, macroOffset, macroOffset) }); if (WbStream.GetAllRecordsByType <SupBook>().Count > 0) { WbStream = WbStream.ReplaceRecord(WbStream.GetAllRecordsByType <SupBook>().First(), supBookRecord); } else { WbStream = WbStream.InsertRecord(supBookRecord, lastCountryRecord); } if (WbStream.GetAllRecordsByType <ExternSheet>().Count > 0) { WbStream = WbStream.InsertRecord(externSheetRecord, WbStream.GetAllRecordsByType <ExternSheet>().Last()); } else { WbStream = WbStream.InsertRecord(externSheetRecord, supBookRecord); } return(WbStream); }
public WorkbookStream InsertRecords(List <BiffRecord> recordsToInsert, BiffRecord insertAfterRecord = null) { if (insertAfterRecord == null) { List <BiffRecord> recordsWithAppendedRecord = _biffRecords.Concat(recordsToInsert).ToList(); return(new WorkbookStream(recordsWithAppendedRecord)); } if (ContainsRecord(insertAfterRecord) == false) { throw new ArgumentException("Could not find insertAfterRecord"); } var insertRecordOffset = GetRecordOffset(insertAfterRecord) + 1; //records [r1, TARGET, r2, r3, r4, r5] //records.count = 6 //insertRecordOffset = 2 //records.Take(2) = [r1, TARGET] //records.TakeLast(4) = [r2, r3, r4, r5] //output = [r1, TARGET, INSERT, r2, r3, r4, r5] var newRecords = _biffRecords.Take(insertRecordOffset).Concat(recordsToInsert) .Concat(_biffRecords.TakeLast(_biffRecords.Count - insertRecordOffset)).ToList(); return(new WorkbookStream(newRecords)); }
public static List <BiffRecord> ParseBiffStreamBytes(byte[] bytes) { List <BiffRecord> records = new List <BiffRecord>(); MemoryStream ms = new MemoryStream(bytes); VirtualStreamReader vsr = new VirtualStreamReader(ms); while (vsr.BaseStream.Position < vsr.BaseStream.Length) { RecordType id = (RecordType)vsr.ReadUInt16(); if (id == 0) { // Console.WriteLine("RecordID == 0 - stopping"); break; } UInt16 length = vsr.ReadUInt16(); BiffRecord br = new BiffRecord(vsr, id, length); vsr.ReadBytes(length); records.Add(br); } return(records); }
public WorkbookStream AddLabel(string label, Stack <AbstractPtg> rgce, bool isMacroStack = false) { /* * Labels require a reference to an XTI index which is used to say which * BoundSheet8 record maps to the appropriate tab. In order to make this * record we need a SupBook record, and ExternSheet record to specify * which BoundSheet8 record to use. * * Currently this assumes there are no SupBook or ExternSheet records in * use, handling of these cases for complex decoy docs is coming * in the future. * * TODO handle existing SupBook/ExternSheet records when adding Lbl entries */ List <BoundSheet8> sheets = WbStream.GetAllRecordsByType <BoundSheet8>(); List <SupBook> supBooksExisting = WbStream.GetAllRecordsByType <SupBook>(); List <ExternSheet> externSheetsExisting = WbStream.GetAllRecordsByType <ExternSheet>(); ExternSheet lastExternSheet; if (supBooksExisting.Count > 0 || externSheetsExisting.Count > 0) { lastExternSheet = externSheetsExisting.Last(); } else { BiffRecord lastCountryRecord = WbStream.GetAllRecordsByType <Country>().Last(); SupBook supBookRecord = new SupBook(sheets.Count, 0x401); int macroOffset = sheets.TakeWhile(s => s.dt != BoundSheet8.SheetType.Macrosheet).Count(); ExternSheet externSheetRecord = new ExternSheet(1, new List <XTI>() { new XTI(0, macroOffset, macroOffset) }); WbStream = WbStream.InsertRecord(supBookRecord, lastCountryRecord); WbStream = WbStream.InsertRecord(externSheetRecord, supBookRecord); lastExternSheet = externSheetRecord; } Lbl newLbl = new Lbl(label, 0); if (isMacroStack) { newLbl.fProc = true; newLbl.fFunc = true; } newLbl.SetRgce(rgce); WbStream = WbStream.InsertRecord(newLbl, lastExternSheet); WbStream = WbStream.FixBoundSheetOffsets(); return(WbStream); }
public FrtWrapper(IStreamReader reader, RecordType id, UInt16 length) : base(reader, id, length) { this.frtHeaderOld = new FrtHeaderOld(reader); this.wrappedRecord = BiffRecord.ReadRecord(reader); // skip padding bytes this.Reader.BaseStream.Position = this.Offset + this.Length; }
private int GetRecordOffset(BiffRecord record) { if (ContainsRecord(record) == false) { throw new ArgumentException(string.Format("Could not find record {0}", record)); } var recordOffset = _biffRecords.TakeWhile(r => r.Equals(record) == false).Count(); return(recordOffset); }
public static string ToHexDumpString(this BiffRecord record, int maxLength = 0x10, bool showAttrInfo = false, bool includeHeader = false) { string biffString = record.ToString(); byte[] bytes = record.GetBytes(); //Skip the 4 byte header if we aren't including the header if (includeHeader == false) { bytes = bytes.Skip(4).ToArray(); } string hexDumpString = HexDump(bytes); if (record is Formula) { Formula f = (Formula)record; if (f.cce == 0 && f.RawBytesValue.Length != bytes.Length + 4) { biffString = "!Error Parsing Formula!"; } else { biffString = f.ToFormulaString(showAttrInfo); } } else if (record.Id == RecordType.Dimensions) { biffString = record.AsRecordType <Dimensions>().ToString(); } else if (record.Id == RecordType.Lbl) { try { biffString = record.AsRecordType <Lbl>().ToString(); } catch (Exception e) { biffString = record.ToString(); } } if ((bytes.Length <= maxLength && bytes.Length > 0) || record.Id == RecordType.Obj) { biffString += "\n" + hexDumpString; } return(biffString); }
public WorkbookStream RemoveRecord(BiffRecord recordToRemove) { if (ContainsRecord(recordToRemove) == false) { throw new ArgumentException("Could not find recordToRemove"); } var removeRecordOffset = GetRecordOffset(recordToRemove); var newRecords = _biffRecords.Take(removeRecordOffset).Concat( _biffRecords.TakeLast(_biffRecords.Count - removeRecordOffset - 1)).ToList(); return(new WorkbookStream(newRecords)); }
public void TestBiffRecordCloneAndGetBytes() { BoundSheet8 bs8 = new BoundSheet8(BoundSheet8.HiddenState.Visible, BoundSheet8.SheetType.Worksheet, "MySheetName"); byte[] bs8bytes = bs8.GetBytes(); BiffRecord bs8CloneRecord = (BiffRecord)bs8.Clone(); byte[] bs8cloneBytes = bs8CloneRecord.GetBytes(); Assert.AreEqual(bs8bytes, bs8cloneBytes); BoundSheet8 bs8Clone = bs8CloneRecord.AsRecordType <BoundSheet8>(); byte[] bs8asRecordBytes = bs8Clone.GetBytes(); Assert.AreEqual(bs8bytes, bs8asRecordBytes); }
public static string ToHexDumpString(this BiffRecord record, int maxLength = 0x10) { string biffString = record.ToString(); //Skip the 4 byte header byte[] bytes = record.GetBytes().Skip(4).ToArray(); string hexDumpString = HexDump(bytes); if ((bytes.Length <= maxLength && bytes.Length > 0) || record.Id == RecordType.Obj) { biffString += "\n" + hexDumpString; } return(biffString); }
public WorkbookStream AddLabel(string label, int rw, int col) { /* * Labels require a reference to an XTI index which is used to say which * BoundSheet8 record maps to the appropriate tab. In order to make this * record we need a SupBook record, and ExternSheet record to specify * which BoundSheet8 record to use. * * Currently this assumes there are no SupBook or ExternSheet records in * use, handling of these cases for complex decoy docs is coming * in the future. * * TODO handle existing SupBook/ExternSheet records when adding Lbl entries */ List <BoundSheet8> sheets = WbStream.GetAllRecordsByType <BoundSheet8>(); List <SupBook> supBooksExisting = WbStream.GetAllRecordsByType <SupBook>(); List <ExternSheet> externSheetsExisting = WbStream.GetAllRecordsByType <ExternSheet>(); if (supBooksExisting.Count > 0 || externSheetsExisting.Count > 0) { throw new NotImplementedException("Use a Decoy Document with no Labels"); } BiffRecord lastCountryRecord = WbStream.GetAllRecordsByType <Country>().Last(); SupBook supBookRecord = new SupBook(sheets.Count, 0x401); int macroOffset = sheets.TakeWhile(s => s.dt != BoundSheet8.SheetType.Macrosheet).Count(); ExternSheet externSheetRecord = new ExternSheet(1, new List <XTI>() { new XTI(0, macroOffset, macroOffset) }); Stack <AbstractPtg> ptgStack = new Stack <AbstractPtg>(); ptgStack.Push(new PtgRef3d(rw, col, 0)); Lbl newLbl = new Lbl(label, 0); newLbl.SetRgce(ptgStack); WbStream = WbStream.InsertRecord(supBookRecord, lastCountryRecord); WbStream = WbStream.InsertRecord(externSheetRecord, supBookRecord); WbStream = WbStream.InsertRecord(newLbl, externSheetRecord); WbStream = WbStream.FixBoundSheetOffsets(); return(WbStream); }
public WorkbookStream SetMacroBinaryContent(byte[] payload, int rwStart, int colStart, int dstRwStart, int dstColStart, SheetPackingMethod packingMethod = SheetPackingMethod.ObfuscatedCharFunc, PayloadPackingMethod payloadPackingMethod = PayloadPackingMethod.MatchSheetPackingMethod) { List <string> payloadMacros; List <BiffRecord> formulasToAdd = new List <BiffRecord>(); if (payloadPackingMethod == PayloadPackingMethod.MatchSheetPackingMethod) { payloadMacros = FormulaHelper.BuildPayloadMacros(payload); formulasToAdd.AddRange(FormulaHelper.ConvertStringsToRecords(payloadMacros, rwStart, colStart, dstRwStart, dstColStart, 15, packingMethod)); } else if (payloadPackingMethod == PayloadPackingMethod.Base64) { payloadMacros = FormulaHelper.BuildBase64PayloadMacros(payload); formulasToAdd = FormulaHelper.ConvertBase64StringsToRecords(payloadMacros, rwStart, colStart); } WorkbookStream macroStream = GetMacroStream(); try { BiffRecord lastFormulaInSheet = macroStream.GetAllRecordsByType <Formula>().Last(); // If we are using base64 packing, we write STRING entries after our formulas, so check for that first if (payloadPackingMethod == PayloadPackingMethod.Base64) { try { lastFormulaInSheet = macroStream.GetAllRecordsByType <STRING>().Last(); } catch { lastFormulaInSheet = macroStream.GetAllRecordsByType <Formula>().Last(); } } WorkbookStream modifiedStream = WbStream.InsertRecords(formulasToAdd, lastFormulaInSheet); WbStream = modifiedStream; return(modifiedStream); } catch (Exception) { throw new ArgumentException( "SetMacroBinaryContent must be called on a stream with at least 1 existing Formula Record"); } }
public GelFrame(IStreamReader reader, RecordType id, UInt16 length) : base(reader, id, length) { // assert that the correct record type is instantiated Debug.Assert(this.Id == ID); // copy data to a memory stream to cope with Continue records using (MemoryStream ms = new MemoryStream()) { byte[] buffer = reader.ReadBytes(length); ms.Write(buffer, 0, length); if (BiffRecord.GetNextRecordType(reader) == RecordType.GelFrame) { RecordType nextId = (RecordType)reader.ReadUInt16(); UInt16 nextLength = reader.ReadUInt16(); buffer = reader.ReadBytes(nextLength); ms.Write(buffer, 0, nextLength); } while (BiffRecord.GetNextRecordType(reader) == RecordType.Continue) { RecordType nextId = (RecordType)reader.ReadUInt16(); UInt16 nextLength = reader.ReadUInt16(); buffer = reader.ReadBytes(nextLength); ms.Write(buffer, 0, nextLength); } ms.Position = 0; // initialize class members from stream this.OPT1 = Record.ReadRecord(ms); if (ms.Position < ms.Length) { this.OPT2 = Record.ReadRecord(ms); } } // assert that the correct number of bytes has been read from the stream //Debug.Assert(this.Offset + this.Length == this.Reader.BaseStream.Position); }
public TxORuns(IStreamReader reader, ushort cbRuns) { int noOfRuns = (cbRuns / 8) - 1; this.rgTxoRuns = new Run[noOfRuns]; for (int i = 0; i < noOfRuns; i++) { if (i == 1028 && BiffRecord.GetNextRecordType(reader) == RecordType.Continue) { // yet another Continue record to be parsed -> skip record header ushort id = reader.ReadUInt16(); ushort size = reader.ReadUInt16(); } this.rgTxoRuns[i] = new Run(reader); } this.lastRun = new TxOLastRun(reader); }
public static List <BiffRecord> ParseBiffStreamBytes(byte[] bytes) { List <BiffRecord> records = new List <BiffRecord>(); MemoryStream ms = new MemoryStream(bytes); VirtualStreamReader vsr = new VirtualStreamReader(ms); while (vsr.BaseStream.Position < vsr.BaseStream.Length) { RecordType id = (RecordType)vsr.ReadUInt16(); UInt16 length = vsr.ReadUInt16(); BiffRecord br = new BiffRecord(vsr, id, length); vsr.ReadBytes(length); records.Add(br); } return(records); }
public static T AsRecordType <T>(this BiffRecord record) where T : BiffRecord { byte[] recordBytes = record.GetBytes(); using (MemoryStream ms = new MemoryStream(recordBytes)) { VirtualStreamReader vsr = new VirtualStreamReader(ms); RecordType id = (RecordType)vsr.ReadUInt16(); ushort len = vsr.ReadUInt16(); var typeConstructor = typeof(T).GetConstructor(new Type[] { typeof(IStreamReader), typeof(RecordType), typeof(ushort) }); if (typeConstructor == null) { throw new ArgumentException(string.Format("Could not find appropriate constructor for type {0}", typeof(T).FullName)); } return((T)typeConstructor.Invoke(new object[] { vsr, id, len })); } }
public static List <BiffRecord> UpdateGlobalsStreamReferences(List <BiffRecord> records) { List <Lbl> labelRecords = records.Where(r => r.Id == RecordType.Lbl).Select(r => r.AsRecordType <Lbl>()).ToList(); List <BoundSheet8> sheetRecords = records.Where(r => r.Id == RecordType.BoundSheet8).Select(r => r.AsRecordType <BoundSheet8>()).ToList(); //Incorrect way to do this, but works for simpler cases - just pull the first ExternSheet record in the XLS file. BiffRecord firstExternSheet = records.FirstOrDefault(r => r.Id == RecordType.ExternSheet); List <BiffRecord> updatedRecords = new List <BiffRecord>(); foreach (var record in records) { switch (record) { case Formula formulaRecord: Stack <AbstractPtg> modifiedFormulaStack = UpdateNameRecords(formulaRecord.ptgStack, labelRecords); if (firstExternSheet != null) { modifiedFormulaStack = UpdateSheetReferences(modifiedFormulaStack, sheetRecords, firstExternSheet.AsRecordType <ExternSheet>()); } formulaRecord.SetCellParsedFormula(new CellParsedFormula(modifiedFormulaStack)); updatedRecords.Add(formulaRecord); continue; case Lbl lblRecord: Stack <AbstractPtg> modifiedLabelStack = UpdateNameRecords(lblRecord.rgce, labelRecords); if (firstExternSheet != null) { modifiedLabelStack = UpdateSheetReferences(modifiedLabelStack, sheetRecords, firstExternSheet.AsRecordType <ExternSheet>()); } lblRecord.SetRgce(modifiedLabelStack); updatedRecords.Add(lblRecord); continue; default: updatedRecords.Add(record); continue; } } return(updatedRecords); }
public WorkbookStream AddFormula(Formula formula, PayloadPackingMethod payloadPackingMethod = PayloadPackingMethod.MatchSheetPackingMethod) { BiffRecord lastFormula = WbStream.GetAllRecordsByType <Formula>().Last(); // If we are using base64 packing, we write STRING entries after our formulas, so check for that first if (payloadPackingMethod == PayloadPackingMethod.Base64) { try { lastFormula = WbStream.GetAllRecordsByType <STRING>().Last(); } catch { lastFormula = WbStream.GetAllRecordsByType <Formula>().Last(); } } WbStream = WbStream.InsertRecord(formula, lastFormula); WbStream = WbStream.FixBoundSheetOffsets(); return(WbStream); }
private bool IsEncryptedWorkbookStream(Stream stream) { bool flag = false; if ((stream != null) && (stream.Length != 0L)) { BiffRecord record = new BiffRecord(); BiffRecord record2 = new BiffRecord(); stream.Seek(20L, (SeekOrigin)SeekOrigin.Begin); BinaryReader reader = new BinaryReader(stream); record.Read(reader); stream.Seek(0x18L, (SeekOrigin)SeekOrigin.Begin); record2.Read(reader); if ((record.RecordType == BiffRecordNumber.FILEPASS) || (record2.RecordType == BiffRecordNumber.FILEPASS)) { flag = true; } stream.Seek(0L, (SeekOrigin)SeekOrigin.Begin); } return(flag); }
public WorkbookStream ReplaceRecord(BiffRecord oldRecord, BiffRecord newRecord) { if (ContainsRecord(oldRecord) == false) { throw new ArgumentException("Could not find oldRecord"); } //records [r1, OLD, r2, r3, r4, r5] //records.count = 6 //replaceRecordOffset = 1 //records.Take(1) = [r1] //records.TakeLast(4) = [r2, r3, r4, r5] //output = [r1, NEW, r2, r3, r4, r5] var replaceRecordOffset = GetRecordOffset(oldRecord); var newRecords = _biffRecords.Take(replaceRecordOffset).Append(newRecord) .Concat(_biffRecords.TakeLast(_biffRecords.Count - (replaceRecordOffset + 1))).ToList(); return(new WorkbookStream(newRecords)); }
public void TestRemoveRecord() { byte[] wbBytes = TestHelpers.GetMacroTestBytes(); WorkbookStream wbs = new WorkbookStream(wbBytes); BiffRecord haltRecord = wbs.GetAllRecordsByType <Formula>().Last(); List <Formula> formulas = wbs.GetAllRecordsByType <Formula>(); Assert.AreEqual(3, formulas.Count); wbs = wbs.RemoveRecord(haltRecord); formulas = wbs.GetAllRecordsByType <Formula>(); Assert.AreEqual(2, formulas.Count); foreach (var formula in formulas) { List <AbstractPtg> ptgs = formula.ptgStack.ToList(); List <PtgFunc> funcs = ptgs.Where(p => p.Id == PtgNumber.PtgFunc).Cast <PtgFunc>().ToList(); bool haltFunctionExists = funcs.Any(func => func.Ftab == FtabValues.HALT); Assert.AreEqual(false, haltFunctionExists); } }
public Pls(IStreamReader reader, RecordType id, ushort length) : base(reader, id, length) { // assert that the correct record type is instantiated Debug.Assert(this.Id == ID); using (var ms = new MemoryStream()) { var buffer = reader.ReadBytes(length); ms.Write(buffer, 0, length); while (BiffRecord.GetNextRecordType(reader) == RecordType.Pls) { var nextId = (RecordType)reader.ReadUInt16(); ushort nextLength = reader.ReadUInt16(); buffer = reader.ReadBytes(nextLength); ms.Write(buffer, 0, nextLength); } while (BiffRecord.GetNextRecordType(reader) == RecordType.Continue) { var nextId = (RecordType)reader.ReadUInt16(); ushort nextLength = reader.ReadUInt16(); buffer = reader.ReadBytes(nextLength); ms.Write(buffer, 0, nextLength); } ms.Position = 0; // initialize class members from stream this.rgb = new byte[ms.Length]; ms.Read(this.rgb, 0, (int)ms.Length); // assert that the correct number of bytes has been read from the stream //Debug.Assert(this.Offset + this.Length == this.Reader.BaseStream.Position); } }
public void TestLongMacroImport() { List <String> simpleMacros = new List <string>(); for (int cell = 0; cell < 50; cell += 1) { string cellContent = ""; for (int i = 0; i < 0x1000; i += 1) { cellContent += "A"; } simpleMacros.Add(cellContent); } List <BiffRecord> records = FormulaHelper.ConvertStringsToRecords(simpleMacros, 0, 0xA0, 0, 0); BiffRecord firstGoto = records.Cast <Formula>().Last(f => f.col == 0xa0); BiffRecord secondColRecord1 = records.Cast <Formula>().First(f => f.col == 0xa1); Assert.IsNotNull(firstGoto); Assert.IsNotNull(secondColRecord1); }
public WorkbookStream SetMacroBinaryContent(byte[] payload, int rwStart, int colStart, int dstRwStart, int dstColStart, SheetPackingMethod packingMethod = SheetPackingMethod.ObfuscatedCharFunc) { List <string> payloadMacros = FormulaHelper.BuildPayloadMacros(payload); List <BiffRecord> formulasToAdd = new List <BiffRecord>(); formulasToAdd.AddRange(FormulaHelper.ConvertStringsToRecords(payloadMacros, rwStart, colStart, dstRwStart, dstColStart, 15, packingMethod)); WorkbookStream macroStream = GetMacroStream(); try { BiffRecord lastFormulaInSheet = macroStream.GetAllRecordsByType <Formula>().Last(); WorkbookStream modifiedStream = WbStream.InsertRecords(formulasToAdd, lastFormulaInSheet); WbStream = modifiedStream; return(modifiedStream); } catch (Exception) { throw new ArgumentException( "SetMacroBinaryContent must be called on a stream with at least 1 existing Formula Record"); } }
public void TestGetDefaultMacroSheetInternationalized() { Intl manuallyCreatedIntlRecord = new Intl(); byte[] intlBytes = manuallyCreatedIntlRecord.GetBytes(); BiffRecord rec = new BiffRecord(intlBytes); Intl convertedRecord = rec.AsRecordType <Intl>(); Assert.AreEqual(convertedRecord.GetBytes(), manuallyCreatedIntlRecord.GetBytes()); WorkbookStream wbs = TestHelpers.GetDefaultMacroTemplate(); List <BiffRecord> sheetRecords = wbs.GetRecordsForBOFRecord(wbs.GetAllRecordsByType <BOF>().Last()); WorkbookStream internationalWbs = new WorkbookStream(sheetRecords); var intlRecord = new Intl(); internationalWbs = internationalWbs.InsertRecord(intlRecord, internationalWbs.GetAllRecordsByType <b2xtranslator.Spreadsheet.XlsFileFormat.Records.Index>().First()); Assert.IsTrue(internationalWbs.ContainsRecord(intlRecord)); var nextRecord = internationalWbs.Records.SkipWhile(r => r.Id != RecordType.Intl).Skip(1).Take(1).First(); Assert.IsTrue(nextRecord.Id == RecordType.CalcMode); }
public bool ContainsRecord(BiffRecord record) { var matchingRecordTypes = _biffRecords.Where(r => r.Id == record.Id).ToList(); return(matchingRecordTypes.Any(r => r.Equals(record))); }
public TxO(IStreamReader reader, RecordType id, UInt16 length) : base(reader, id, length) { // assert that the correct record type is instantiated Debug.Assert(this.Id == ID); long startPosition = this.Reader.BaseStream.Position; // NOTE: controlInfo is an option field that exists if and only if the value of // cmo.ot in the preceding Obj record is 0, 5, 7, 11, 12 or 14. // However, the current parser implementation does not allow us to see the preceding // record(s) witout an enormous recactoring. Therefore we're a little bit hacky here // and try to read the record first without the optional field. If we didn't succeed // we start a second try, this time including the optional field. // for (int noOfTries = 1; noOfTries < 3; noOfTries++) { // initialize class members from stream UInt16 flags = reader.ReadUInt16(); this.hAlignment = (HorizontalAlignment)Utils.BitmaskToInt(flags, 0xE); this.vAlignment = (VerticalAlignment)Utils.BitmaskToInt(flags, 0x70); this.rot = (TextRotation)reader.ReadUInt16(); reader.ReadBytes(6); // reserved // read optional field controlInfo on second try if (noOfTries == 2) { this.controlInfo = new ControlInfo(reader); } this.cchText = reader.ReadUInt16(); this.cbRuns = reader.ReadUInt16(); this.ifntEmpty = reader.ReadUInt16(); this.fmla = new ObjFmla(reader); if (this.Offset + this.Length == this.Reader.BaseStream.Position) { break; } else if (noOfTries == 1) { // re-read record, this time including the optional controlInfo field this.Reader.BaseStream.Position = startPosition; } } // assert that the correct number of bytes has been read from the stream Debug.Assert(this.Offset + this.Length == this.Reader.BaseStream.Position); // NOTE: If the field cchText is not zero, this record doesn‘t fully specify the text. // The rest of the data that MUST be specified is the text string and the formatting runs // information. // if (this.cchText > 0 && BiffRecord.GetNextRecordType(reader) == RecordType.Continue) { // skip record header reader.ReadUInt16(); reader.ReadUInt16(); this.text = new XLUnicodeStringNoCch(reader, this.cchText); if (BiffRecord.GetNextRecordType(reader) == RecordType.Continue) { // skip record header reader.ReadUInt16(); reader.ReadUInt16(); this.runs = new TxORuns(reader, this.cbRuns); } } }