public void TestReadContinued() { //simulate a continues Drawing record MemoryStream out1 = new MemoryStream(); //main part DrawingRecord dg = new DrawingRecord(); byte[] data1 = new byte[8224]; Arrays.Fill(data1, (byte)1); dg.Data = (/*setter*/data1); byte[] dataX = dg.Serialize(); out1.Write(dataX, 0, dataX.Length); //continued part byte[] data2 = new byte[4048]; Arrays.Fill(data2, (byte)2); ContinueRecord cn = new ContinueRecord(data2); dataX = cn.Serialize(); out1.Write(dataX, 0, dataX.Length); List<Record> rec = RecordFactory.CreateRecords(new MemoryStream(out1.ToArray())); Assert.AreEqual(2, rec.Count); Assert.IsTrue(rec[0] is DrawingRecord); Assert.IsTrue(rec[1] is ContinueRecord); Assert.IsTrue(Arrays.Equals(data1, ((DrawingRecord)rec[0]).Data)); Assert.IsTrue(Arrays.Equals(data2, ((ContinueRecord)rec[1]).Data)); }
public void TestReadContinued() { //simulate a continues Drawing record MemoryStream out1 = new MemoryStream(); //main part DrawingRecord dg = new DrawingRecord(); byte[] data1 = new byte[8224]; Arrays.Fill(data1, (byte)1); dg.Data = (/*setter*/data1); byte[] dataX = dg.Serialize(); out1.Write(dataX, 0, dataX.Length); //continued part byte[] data2 = new byte[4048]; Arrays.Fill(data2, (byte)2); ContinueRecord cn = new ContinueRecord(data2); dataX = cn.Serialize(); out1.Write(dataX, 0, dataX.Length); List<Record> rec = RecordFactory.CreateRecords(new MemoryStream(out1.ToArray())); Assert.AreEqual(1, rec.Count); Assert.IsTrue(rec[0] is DrawingRecord); //DrawingRecord.Data should return concatenated data1 and data2 byte[] tmp = new byte[data1.Length + data2.Length]; Array.Copy(data1, 0, tmp, 0, data1.Length); Array.Copy(data2, 0, tmp, data1.Length, data2.Length); DrawingRecord dg2 = (DrawingRecord)rec[(0)]; Assert.AreEqual(data1.Length + data2.Length, dg2.Data.Length); Assert.IsTrue(Arrays.Equals(tmp, dg2.Data)); }
private static RecordInputStream ConvertToInputStream(DrawingRecord r) { byte[] data = r.Serialize(); RecordInputStream rinp = new RecordInputStream( new MemoryStream(data) ); rinp.NextRecord(); return rinp; }
private static RecordInputStream ConvertToInputStream(DrawingRecord r) { byte[] data = r.Serialize(); using (MemoryStream ms = new MemoryStream(data)) { RecordInputStream rinp = new RecordInputStream(ms); rinp.NextRecord(); return(rinp); } }
/** * Cloning of drawing records must be executed through HSSFPatriarch, because all id's must be changed * @return cloned drawing records */ public override Object Clone() { DrawingRecord rec = new DrawingRecord(); rec.recordData = (byte[])recordData.Clone();// new byte[recordData.Length]; if (contd != null) { rec.contd = (byte[])contd.Clone(); } return(rec); }
public void TestCreateAggregate() { String msoDrawingRecord1 = "0F 00 02 F0 20 01 00 00 10 00 08 F0 08 00 00 00 " + "03 00 00 00 02 04 00 00 0F 00 03 F0 08 01 00 00 " + "0F 00 04 F0 28 00 00 00 01 00 09 F0 10 00 00 00 " + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " + "02 00 0A F0 08 00 00 00 00 04 00 00 05 00 00 00 " + "0F 00 04 F0 64 00 00 00 42 01 0A F0 08 00 00 00 " + "01 04 00 00 00 0A 00 00 73 00 0B F0 2A 00 00 00 " + "BF 00 08 00 08 00 44 01 04 00 00 00 7F 01 00 00 " + "01 00 BF 01 00 00 11 00 C0 01 40 00 00 08 FF 01 " + "10 00 10 00 BF 03 00 00 08 00 00 00 10 F0 12 00 " + "00 00 00 00 01 00 54 00 05 00 45 00 01 00 88 03 " + "05 00 94 00 00 00 11 F0 00 00 00 00"; String msoDrawingRecord2 = "0F 00 04 F0 64 00 00 00 42 01 0A F0 08 00 00 00 " + "02 04 00 00 80 0A 00 00 73 00 0B F0 2A 00 00 00 " + "BF 00 08 00 08 00 44 01 04 00 00 00 7F 01 00 00 " + "01 00 BF 01 00 00 11 00 C0 01 40 00 00 08 FF 01 " + "10 00 10 00 BF 03 00 00 08 00 00 00 10 F0 12 00 " + "00 00 00 00 01 00 8D 03 05 00 E4 00 03 00 4D 03 " + "0B 00 0C 00 00 00 11 F0 00 00 00 00"; DrawingRecord d1 = new DrawingRecord(); d1.Data = (HexRead.ReadFromString(msoDrawingRecord1)); ObjRecord r1 = new ObjRecord(); DrawingRecord d2 = new DrawingRecord(); d2.Data = (HexRead.ReadFromString(msoDrawingRecord2)); ObjRecord r2 = new ObjRecord(); ArrayList records = new ArrayList(); records.Add(d1); records.Add(r1); records.Add(d2); records.Add(r2); DrawingManager2 drawingManager = new DrawingManager2(new EscherDggRecord()); EscherAggregate aggregate = EscherAggregate.CreateAggregate(records, 0, drawingManager); Assert.AreEqual(1, aggregate.EscherRecords.Count); Assert.AreEqual(unchecked((short)0xF002), aggregate.GetEscherRecord(0).RecordId); Assert.AreEqual(2, aggregate.GetEscherRecord(0).ChildRecords.Count); // System.out.println( "aggregate = " + aggregate ); }
public override Object Clone() { DrawingRecord rec = new DrawingRecord(); if (recordData != null) { rec.recordData = new byte[recordData.Length]; Array.Copy(recordData, 0, rec.recordData, 0, recordData.Length); } if (contd != null) { Array.Copy(contd, 0, rec.contd, 0, contd.Length); rec.contd = new byte[contd.Length]; } return(rec); }
/** * @return the next available record, or <code>null</code> if * this pass didn't return a record that's * suitable for returning (eg was a continue record). */ private Record ReadNextRecord() { Record record = RecordFactory.CreateSingleRecord(_recStream); _lastRecordWasEOFLevelZero = false; if (record is BOFRecord) { _bofDepth++; return(record); } if (record is EOFRecord) { _bofDepth--; if (_bofDepth < 1) { _lastRecordWasEOFLevelZero = true; } return(record); } if (record is DBCellRecord) { // Not needed by POI. Regenerated from scratch by POI when spreadsheet is written return(null); } if (record is RKRecord) { return(RecordFactory.ConvertToNumberRecord((RKRecord)record)); } if (record is MulRKRecord) { Record[] records = RecordFactory.ConvertRKRecords((MulRKRecord)record); _unreadRecordBuffer = records; _unreadRecordIndex = 1; return(records[0]); } if (record.Sid == DrawingGroupRecord.sid && _lastRecord is DrawingGroupRecord) { DrawingGroupRecord lastDGRecord = (DrawingGroupRecord)_lastRecord; lastDGRecord.Join((AbstractEscherHolderRecord)record); return(null); } if (record.Sid == ContinueRecord.sid) { ContinueRecord contRec = (ContinueRecord)record; if (_lastRecord is ObjRecord || _lastRecord is TextObjectRecord) { // Drawing records have a very strange continue behaviour. //There can actually be OBJ records mixed between the continues. _lastDrawingRecord.ProcessContinueRecord(contRec.Data); //we must remember the position of the continue record. //in the serialization procedure the original structure of records must be preserved if (_shouldIncludeContinueRecords) { return(record); } return(null); } if (_lastRecord is DrawingGroupRecord) { ((DrawingGroupRecord)_lastRecord).ProcessContinueRecord(contRec.Data); return(null); } if (_lastRecord is DrawingRecord) { ((DrawingRecord)_lastRecord).ProcessContinueRecord(contRec.Data); return(null); } if (_lastRecord is CrtMlFrtRecord) { return(record); } if (_lastRecord is UnknownRecord) { //Gracefully handle records that we don't know about, //that happen to be continued return(record); } if (_lastRecord is EOFRecord) { // This is really odd, but excel still sometimes // outPuts a file like this all the same return(record); } //if (_lastRecord is StringRecord) //{ // ((StringRecord)_lastRecord).ProcessContinueRecord(contRec.Data); // return null; //} throw new RecordFormatException("Unhandled Continue Record"); } _lastRecord = record; if (record is DrawingRecord) { _lastDrawingRecord = (DrawingRecord)record; } return(record); }
//public const byte PANE_LOWER_RIGHT = (byte)0; //public const byte PANE_UPPER_RIGHT = (byte)1; //public const byte PANE_LOWER_LEFT = (byte)2; //public const byte PANE_UPPER_LEFT = (byte)3; /// <summary> /// Clones the low level records of this sheet and returns the new sheet instance. /// This method is implemented by Adding methods for deep cloning to all records that /// can be Added to a sheet. The Record object does not implement Cloneable. /// When Adding a new record, implement a public Clone method if and only if the record /// belongs to a sheet. /// </summary> /// <returns></returns> public InternalSheet CloneSheet() { List<RecordBase> clonedRecords = new List<RecordBase>(this.records.Count); for (int i = 0; i < this.records.Count; i++) { RecordBase rb = (RecordBase)this.records[i]; if (rb is RecordAggregate) { ((RecordAggregate)rb).VisitContainedRecords(new RecordCloner(clonedRecords)); continue; } if (rb is EscherAggregate) { /** * this record will be removed after reading actual data from EscherAggregate */ rb = new DrawingRecord(); } Record rec = (Record)((Record)rb).Clone(); clonedRecords.Add(rec); } return CreateSheet(new RecordStream(clonedRecords, 0)); }
/** * Serializes this aggregate to a byte array. Since this Is an aggregate * record it will effectively Serialize the aggregated records. * * @param offset The offset into the start of the array. * @param data The byte array to Serialize to. * @return The number of bytes Serialized. */ public override int Serialize(int offset, byte [] data) { ConvertUserModelToRecords(); // Determine buffer size IList records = EscherRecords; int size = GetEscherRecordSize(records); byte[] buffer = new byte[size]; // Serialize escher records into one big data structure and keep note of ending offsets. spEndingOffsets = new ArrayList(); shapes = new ArrayList(); int pos = 0; for (IEnumerator iterator = records.GetEnumerator(); iterator.MoveNext();) { EscherRecord e = (EscherRecord)iterator.Current; pos += e.Serialize(pos, buffer, new SerializationListener(ref spEndingOffsets, ref shapes)); } // todo: fix this shapes.Insert(0, null); spEndingOffsets.Insert(0, null); // Split escher records into Separate MSODRAWING and OBJ, TXO records. (We don't break on // the first one because it's the patriach). pos = offset; for (int i = 1; i < shapes.Count; i++) { int endOffset = (int)spEndingOffsets[i] - 1; int startOffset; if (i == 1) { startOffset = 0; } else { startOffset = (int)spEndingOffsets[i - 1]; } // Create and Write a new MSODRAWING record DrawingRecord drawing = new DrawingRecord(); byte[] drawingData = new byte[endOffset - startOffset + 1]; Array.Copy(buffer, startOffset, drawingData, 0, drawingData.Length); drawing.Data = drawingData; int temp = drawing.Serialize(pos, data); pos += temp; // Write the matching OBJ record Record obj = (Record)shapeToObj[shapes[i]]; temp = obj.Serialize(pos, data); pos += temp; } // Write records that need to be Serialized after all drawing Group records for (int i = 0; i < tailRec.Count; i++) { Record rec = (Record)tailRec[i]; pos += rec.Serialize(pos, data); } int bytesWritten = pos - offset; if (bytesWritten != RecordSize) { throw new RecordFormatException(bytesWritten + " bytes written but RecordSize reports " + RecordSize); } return(bytesWritten); }
private static DrawingRecord CreateDrawingRecord() { //throw new NotImplementedException(); byte[] drawingData = HexRead.ReadFromString("0F 00 02 F0 48 00 00 00 30 00 08 F0 " + "08 00 00 00 01 00 00 00 00 0C 00 00 0F 00 03 F0 " + "30 00 00 00 0F 00 04 F0 28 00 00 00 01 00 09 F0 " + "10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " + "00 00 00 00 02 00 0A F0 08 00 00 00 00 0C 00 00 " + "05 00 00 00"); DrawingRecord retval = new DrawingRecord(); retval.Data = drawingData; return retval; }
/** * @return the next available record, or <code>null</code> if * this pass didn't return a record that's * suitable for returning (eg was a continue record). */ private Record ReadNextRecord() { Record record = RecordFactory.CreateSingleRecord(_recStream); _lastRecordWasEOFLevelZero = false; if (record is BOFRecord) { _bofDepth++; return record; } if (record is EOFRecord) { _bofDepth--; if (_bofDepth < 1) { _lastRecordWasEOFLevelZero = true; } return record; } if (record is DBCellRecord) { // Not needed by POI. Regenerated from scratch by POI when spreadsheet is written return null; } if (record is RKRecord) { return RecordFactory.ConvertToNumberRecord((RKRecord)record); } if (record is MulRKRecord) { Record[] records = RecordFactory.ConvertRKRecords((MulRKRecord)record); _unreadRecordBuffer = records; _unreadRecordIndex = 1; return records[0]; } if (record.Sid == DrawingGroupRecord.sid && _lastRecord is DrawingGroupRecord) { DrawingGroupRecord lastDGRecord = (DrawingGroupRecord)_lastRecord; lastDGRecord.Join((AbstractEscherHolderRecord)record); return null; } if (record.Sid == ContinueRecord.sid) { ContinueRecord contRec = (ContinueRecord)record; if (_lastRecord is ObjRecord || _lastRecord is TextObjectRecord) { // Drawing records have a very strange continue behaviour. //There can actually be OBJ records mixed between the continues. _lastDrawingRecord.ProcessContinueRecord(contRec.Data); //we must remember the position of the continue record. //in the serialization procedure the original structure of records must be preserved if (_shouldIncludeContinueRecords) { return record; } return null; } if (_lastRecord is DrawingGroupRecord) { ((DrawingGroupRecord)_lastRecord).ProcessContinueRecord(contRec.Data); return null; } if (_lastRecord is DrawingRecord) { //((DrawingRecord)_lastRecord).ProcessContinueRecord(contRec.Data); return contRec; } if (_lastRecord is CrtMlFrtRecord) { return record; } if (_lastRecord is UnknownRecord) { //Gracefully handle records that we don't know about, //that happen to be continued return record; } if (_lastRecord is EOFRecord) { // This is really odd, but excel still sometimes // outPuts a file like this all the same return record; } //if (_lastRecord is StringRecord) //{ // ((StringRecord)_lastRecord).ProcessContinueRecord(contRec.Data); // return null; //} if (_lastRecord is ExtSSTRecord) // problem case in GS files a continue record with nothing obvious to continue, ignore { return null; } throw new RecordFormatException("Unhandled Continue Record"); } _lastRecord = record; if (record is DrawingRecord) { _lastDrawingRecord = (DrawingRecord)record; } return record; }
public override Object Clone() { DrawingRecord rec = new DrawingRecord(); rec.recordData = (byte[])recordData.Clone();// new byte[recordData.Length]; if (contd != null) { rec.contd = (byte[])contd.Clone(); } return rec; }
/// <summary> /// Returns the next available record, or null if /// this pass didn't return a record that's /// suitable for returning (eg was a continue record). /// </summary> /// <returns></returns> private Record GetNextRecord() { Record toReturn = null; if (in1.HasNextRecord) { // Grab our next record in1.NextRecord(); short sid = in1.Sid; // // for some reasons we have to make the workbook to be at least 4096 bytes // but if we have such workbook we Fill the end of it with zeros (many zeros) // // it Is not good: // if the Length( all zero records ) % 4 = 1 // e.g.: any zero record would be Readed as 4 bytes at once ( 2 - id and 2 - size ). // And the last 1 byte will be Readed WRONG ( the id must be 2 bytes ) // // So we should better to Check if the sid Is zero and not to Read more data // The zero sid shows us that rest of the stream data Is a fake to make workbook // certain size // if (sid == 0) return null; // If we had a last record, and this one // Isn't a continue record, then pass // it on to the listener if ((rec != null) && (sid != ContinueRecord.sid)) { // This last record ought to be returned toReturn = rec; } // If this record Isn't a continue record, // then build it up if (sid != ContinueRecord.sid) { //Console.WriteLine("creating "+sid); Record[] recs = RecordFactory.CreateRecord(in1); // We know that the multiple record situations // don't contain continue records, so just // pass those on to the listener now if (recs.Length > 1) { bonusRecords = new ArrayList(recs.Length - 1); for (int k = 0; k < (recs.Length - 1); k++) { bonusRecords.Add(recs[k]); } } // Regardless of the number we Created, always hold // onto the last record to be Processed on the next // loop, in case it has any continue records rec = recs[recs.Length - 1]; // Don't return it just yet though, as we probably have // a record from the last round to return } else { // Normally, ContinueRecords are handled internally // However, in a few cases, there Is a gap between a record at // its Continue, so we have to handle them specially // This logic Is much like in RecordFactory.CreateRecords() Record[] recs = RecordFactory.CreateRecord(in1); ContinueRecord crec = (ContinueRecord)recs[0]; if ((lastRec is ObjRecord) || (lastRec is TextObjectRecord)) { // You can have Obj records between a DrawingRecord // and its continue! lastDrawingRecord.ProcessContinueRecord(crec.Data); // Trigger them on the drawing record, now it's complete rec = lastDrawingRecord; } else if ((lastRec is DrawingGroupRecord)) { ((DrawingGroupRecord)lastRec).ProcessContinueRecord(crec.Data); // Trigger them on the drawing record, now it's complete rec = lastRec; } else { if (rec is UnknownRecord) { ;//silently skip records we don't know about } else { throw new RecordFormatException("Records should handle ContinueRecord internally. Should not see this exception"); } } } // Update our tracking of the last record lastRec = rec; if (rec is DrawingRecord) { lastDrawingRecord = (DrawingRecord)rec; } } else { // No more records hitEOS = true; } // If we've hit the end-of-stream, then // finish off the last record and be done if (hitEOS) { complete = true; // Return the last record if there was // one, otherwise null if (rec != null) { toReturn = rec; rec = null; } } return toReturn; }
/** * Serializes this aggregate to a byte array. Since this Is an aggregate * record it will effectively Serialize the aggregated records. * * @param offset The offset into the start of the array. * @param data The byte array to Serialize to. * @return The number of bytes Serialized. */ public override int Serialize(int offset, byte [] data) { ConvertUserModelToRecords(); // Determine buffer size IList records = EscherRecords; int size = GetEscherRecordSize(records); byte[] buffer = new byte[size]; // Serialize escher records into one big data structure and keep note of ending offsets. spEndingOffsets = new ArrayList(); shapes = new ArrayList(); int pos = 0; for (IEnumerator iterator = records.GetEnumerator(); iterator.MoveNext(); ) { EscherRecord e = (EscherRecord)iterator.Current; pos += e.Serialize(pos, buffer, new SerializationListener(ref spEndingOffsets,ref shapes)); } // todo: fix this shapes.Insert(0, null); spEndingOffsets.Insert(0, null); // Split escher records into Separate MSODRAWING and OBJ, TXO records. (We don't break on // the first one because it's the patriach). pos = offset; for (int i = 1; i < shapes.Count; i++) { int endOffset = (int)spEndingOffsets[i] - 1; int startOffset; if (i == 1) startOffset = 0; else startOffset = (int)spEndingOffsets[i - 1]; // Create and Write a new MSODRAWING record DrawingRecord drawing = new DrawingRecord(); byte[] drawingData = new byte[endOffset - startOffset + 1]; Array.Copy(buffer, startOffset, drawingData, 0, drawingData.Length); drawing.Data=drawingData; int temp = drawing.Serialize(pos, data); pos += temp; // Write the matching OBJ record Record obj = (Record)shapeToObj[shapes[i]]; temp = obj.Serialize(pos, data); pos += temp; } // Write records that need to be Serialized after all drawing Group records for (int i = 0; i < tailRec.Count; i++) { Record rec = (Record)tailRec[i]; pos += rec.Serialize(pos, data); } int bytesWritten = pos - offset; if (bytesWritten != RecordSize) throw new RecordFormatException(bytesWritten + " bytes written but RecordSize reports " + RecordSize); return bytesWritten; }
/** * @param drawingData - escher records saved into single byte array * @param writtenEscherBytes - count of bytes already saved into drawing records (we should know it to decide create * drawing or continue record) * @param pos current position of data array * @param data - array of bytes where drawing records must be serialized * @param i - number of shape, saved into data array * @return offset of data array after serialization */ private int WriteDataIntoDrawingRecord(byte[] drawingData, int writtenEscherBytes, int pos, byte[] data, int i) { int temp = 0; //First record in drawing layer MUST be DrawingRecord if (writtenEscherBytes + drawingData.Length > RecordInputStream.MAX_RECORD_DATA_SIZE && i != 1) { for (int j = 0; j < drawingData.Length; j += RecordInputStream.MAX_RECORD_DATA_SIZE) { byte[] buf = new byte[Math.Min(RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.Length - j)]; System.Array.Copy(drawingData, j, buf, 0, Math.Min(RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.Length - j)); ContinueRecord drawing = new ContinueRecord(buf); temp += drawing.Serialize(pos + temp, data); } } else { for (int j = 0; j < drawingData.Length; j += RecordInputStream.MAX_RECORD_DATA_SIZE) { if (j == 0) { DrawingRecord drawing = new DrawingRecord(); byte[] buf = new byte[Math.Min(RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.Length - j)]; System.Array.Copy(drawingData, j, buf, 0, Math.Min(RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.Length - j)); drawing.Data = (buf); temp += drawing.Serialize(pos + temp, data); } else { byte[] buf = new byte[Math.Min(RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.Length - j)]; System.Array.Copy(drawingData, j, buf, 0, Math.Min(RecordInputStream.MAX_RECORD_DATA_SIZE, drawingData.Length - j)); ContinueRecord drawing = new ContinueRecord(buf); temp += drawing.Serialize(pos + temp, data); } } } return temp; }
public DrawingRecordForBiffViewer(DrawingRecord r) : base(ConvertToInputStream(r)) { ConvertRawBytesToEscherRecords(); }
public override Object Clone() { DrawingRecord rec = new DrawingRecord(); if (recordData != null) { rec.recordData = new byte[recordData.Length]; Array.Copy(recordData, 0, rec.recordData, 0, recordData.Length); } if (contd != null) { Array.Copy(contd, 0, rec.contd, 0, contd.Length); rec.contd = new byte[contd.Length]; } return rec; }
public void TestCreateAggregate() { String msoDrawingRecord1 = "0F 00 02 F0 20 01 00 00 10 00 08 F0 08 00 00 00 \n" + "03 00 00 00 02 04 00 00 0F 00 03 F0 08 01 00 00 \n" + "0F 00 04 F0 28 00 00 00 01 00 09 F0 10 00 00 00 \n" + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \n" + "02 00 0A F0 08 00 00 00 00 04 00 00 05 00 00 00 \n" + "0F 00 04 F0 64 00 00 00 42 01 0A F0 08 00 00 00 \n" + "01 04 00 00 00 0A 00 00 73 00 0B F0 2A 00 00 00 \n" + "BF 00 08 00 08 00 44 01 04 00 00 00 7F 01 00 00 \n" + "01 00 BF 01 00 00 11 00 C0 01 40 00 00 08 FF 01 \n" + "10 00 10 00 BF 03 00 00 08 00 00 00 10 F0 12 00 \n" + "00 00 00 00 01 00 54 00 05 00 45 00 01 00 88 03 \n" + "05 00 94 00 00 00 11 F0 00 00 00 00"; String msoDrawingRecord2 = "0F 00 04 F0 64 00 00 00 42 01 0A F0 08 00 00 00 " + "02 04 00 00 80 0A 00 00 73 00 0B F0 2A 00 00 00 " + "BF 00 08 00 08 00 44 01 04 00 00 00 7F 01 00 00 " + "01 00 BF 01 00 00 11 00 C0 01 40 00 00 08 FF 01 " + "10 00 10 00 BF 03 00 00 08 00 00 00 10 F0 12 00 " + "00 00 00 00 01 00 8D 03 05 00 E4 00 03 00 4D 03 " + "0B 00 0C 00 00 00 11 F0 00 00 00 00"; DrawingRecord d1 = new DrawingRecord(); d1.Data = HexRead.ReadFromString(msoDrawingRecord1); ObjRecord r1 = new ObjRecord(); DrawingRecord d2 = new DrawingRecord(); d2.Data = (HexRead.ReadFromString(msoDrawingRecord2)); TextObjectRecord r2 = new TextObjectRecord(); r2.Str = (new HSSFRichTextString("Aggregated")); NoteRecord n2 = new NoteRecord(); List<RecordBase> recordStream = new List<RecordBase>(); recordStream.Add(InternalSheet.CreateBOF()); recordStream.Add(d1); recordStream.Add(r1); recordStream.Add(CreateWindow2Record()); recordStream.Add(EOFRecord.instance); ConfirmAggregatedRecords(recordStream); recordStream = new List<RecordBase>(); recordStream.Add(InternalSheet.CreateBOF()); recordStream.Add(d1); recordStream.Add(r1); recordStream.Add(d2); recordStream.Add(r2); recordStream.Add(CreateWindow2Record()); recordStream.Add(EOFRecord.instance); ConfirmAggregatedRecords(recordStream); recordStream = new List<RecordBase>(); recordStream.Add(InternalSheet.CreateBOF()); recordStream.Add(d1); recordStream.Add(r1); recordStream.Add(d2); recordStream.Add(r2); recordStream.Add(n2); recordStream.Add(CreateWindow2Record()); recordStream.Add(EOFRecord.instance); ConfirmAggregatedRecords(recordStream); }
/** * Collapses the drawing records into an aggregate. */ public static EscherAggregate CreateAggregate(IList records, int locFirstDrawingRecord, DrawingManager2 drawingManager) { // Keep track of any shape records Created so we can match them back to the object id's. // Textbox objects are also treated as shape objects. IList shapeRecords = new ArrayList(); EscherRecordFactory recordFactory = new CustomEscherRecordFactory(ref shapeRecords); // Calculate the size of the buffer EscherAggregate agg = new EscherAggregate(drawingManager); int loc = locFirstDrawingRecord; int dataSize = 0; while (loc + 1 < records.Count && GetSid(records, loc) == DrawingRecord.sid && IsObjectRecord(records, loc + 1)) { dataSize += ((DrawingRecord)records[loc]).Data.Length; loc += 2; } // Create one big buffer byte[] buffer = new byte[dataSize]; int offset = 0; loc = locFirstDrawingRecord; while (loc + 1 < records.Count && GetSid(records, loc) == DrawingRecord.sid && IsObjectRecord(records, loc + 1)) { DrawingRecord drawingRecord = (DrawingRecord)records[loc]; Array.Copy(drawingRecord.Data, 0, buffer, offset, drawingRecord.Data.Length); offset += drawingRecord.Data.Length; loc += 2; } // Decode the shapes // agg.escherRecords = new ArrayList(); int pos = 0; while (pos < dataSize) { EscherRecord r = recordFactory.CreateRecord(buffer, pos); int bytesRead = r.FillFields(buffer, pos, recordFactory); agg.AddEscherRecord(r); pos += bytesRead; } // Associate the object records with the shapes loc = locFirstDrawingRecord; int shapeIndex = 0; agg.shapeToObj = new Hashtable(); while (loc + 1 < records.Count && GetSid(records, loc) == DrawingRecord.sid && IsObjectRecord(records, loc + 1)) { Record objRecord = (Record)records[loc + 1]; agg.shapeToObj[shapeRecords[shapeIndex++]] = objRecord; loc += 2; } return(agg); }