private void ConvertGroup(HSSFShapeGroup shape, EscherContainerRecord escherParent, Hashtable shapeToObj) { EscherContainerRecord spgrContainer = new EscherContainerRecord(); EscherContainerRecord spContainer = new EscherContainerRecord(); EscherSpgrRecord spgr = new EscherSpgrRecord(); EscherSpRecord sp = new EscherSpRecord(); EscherOptRecord opt = new EscherOptRecord(); EscherRecord anchor; EscherClientDataRecord clientData = new EscherClientDataRecord(); spgrContainer.RecordId = EscherContainerRecord.SPGR_CONTAINER; spgrContainer.Options = (short)0x000F; spContainer.RecordId = EscherContainerRecord.SP_CONTAINER; spContainer.Options = (short)0x000F; spgr.RecordId = EscherSpgrRecord.RECORD_ID; spgr.Options = (short)0x0001; spgr.RectX1 = shape.X1; spgr.RectY1 = shape.Y1; spgr.RectX2 = shape.X2; spgr.RectY2 = shape.Y2; sp.RecordId = EscherSpRecord.RECORD_ID; sp.Options = (short)0x0002; int shapeId = drawingManager.AllocateShapeId(drawingGroupId); sp.ShapeId = shapeId; if (shape.Anchor is HSSFClientAnchor) { sp.Flags = EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR; } else { sp.Flags = EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_CHILD; } opt.RecordId = EscherOptRecord.RECORD_ID; opt.Options = (short)0x0023; opt.AddEscherProperty(new EscherBoolProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x00040004)); opt.AddEscherProperty(new EscherBoolProperty(EscherProperties.GROUPSHAPE__PRINT, 0x00080000)); anchor = ConvertAnchor.CreateAnchor(shape.Anchor); // clientAnchor.Col1( ( (HSSFClientAnchor) shape.Anchor ).Col1 ); // clientAnchor.Row1( (short) ( (HSSFClientAnchor) shape.Anchor ).Row1 ); // clientAnchor.Dx1( (short) shape.Anchor.Dx1 ); // clientAnchor.Dy1( (short) shape.Anchor.Dy1 ); // clientAnchor.Col2( ( (HSSFClientAnchor) shape.Anchor ).Col2 ); // clientAnchor.Row2( (short) ( (HSSFClientAnchor) shape.Anchor ).Row2 ); // clientAnchor.Dx2( (short) shape.Anchor.Dx2 ); // clientAnchor.Dy2( (short) shape.Anchor.Dy2 ); clientData.RecordId = (EscherClientDataRecord.RECORD_ID); clientData.Options = ((short)0x0000); spgrContainer.AddChildRecord(spContainer); spContainer.AddChildRecord(spgr); spContainer.AddChildRecord(sp); spContainer.AddChildRecord(opt); spContainer.AddChildRecord(anchor); spContainer.AddChildRecord(clientData); ObjRecord obj = new ObjRecord(); CommonObjectDataSubRecord cmo = new CommonObjectDataSubRecord(); cmo.ObjectType = CommonObjectType.GROUP; cmo.ObjectId = shapeId; cmo.IsLocked = true; cmo.IsPrintable = true; cmo.IsAutoFill = true; cmo.IsAutoline = true; GroupMarkerSubRecord gmo = new GroupMarkerSubRecord(); EndSubRecord end = new EndSubRecord(); obj.AddSubRecord(cmo); obj.AddSubRecord(gmo); obj.AddSubRecord(end); shapeToObj[clientData] = obj; escherParent.AddChildRecord(spgrContainer); ConvertShapes(shape, spgrContainer, shapeToObj); }
/** * Constructs a OBJ record and Sets its fields appropriately. * * @param in the RecordInputstream to Read the record from */ public ObjRecord(RecordInputStream in1) { // TODO - problems with OBJ sub-records stream // MS spec says first sub-record is always CommonObjectDataSubRecord, // and last is // always EndSubRecord. OOO spec does not mention ObjRecord(0x005D). // Existing POI test data seems to violate that rule. Some test data // seems to contain // garbage, and a crash is only averted by stopping at what looks like // the 'EndSubRecord' //Check if this can be continued, if so then the //following wont work properly //int subSize = 0; byte[] subRecordData = in1.ReadRemainder(); if (LittleEndian.GetUShort(subRecordData, 0) != CommonObjectDataSubRecord.sid) { // seems to occur in just one junit on "OddStyleRecord.xls" (file created by CrystalReports) // Excel tolerates the funny ObjRecord, and replaces it with a corrected version // The exact logic/reasoning is not yet understood _uninterpretedData = subRecordData; subrecords = null; return; } //if (subRecordData.Length % 2 != 0) //{ // String msg = "Unexpected length of subRecordData : " + HexDump.ToHex(subRecordData); // throw new RecordFormatException(msg); //} subrecords = new List <SubRecord>(); using (MemoryStream bais = new MemoryStream(subRecordData)) { LittleEndianInputStream subRecStream = new LittleEndianInputStream(bais); CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord)SubRecord.CreateSubRecord(subRecStream, 0); subrecords.Add(cmo); while (true) { SubRecord subRecord = SubRecord.CreateSubRecord(subRecStream, cmo.ObjectType); subrecords.Add(subRecord); if (subRecord.IsTerminating) { break; } } int nRemainingBytes = subRecStream.Available(); if (nRemainingBytes > 0) { // At present (Oct-2008), most unit test samples have (subRecordData.length % 2 == 0) _isPaddedToQuadByteMultiple = subRecordData.Length % MAX_PAD_ALIGNMENT == 0; if (nRemainingBytes >= (_isPaddedToQuadByteMultiple ? MAX_PAD_ALIGNMENT : NORMAL_PAD_ALIGNMENT)) { if (!CanPaddingBeDiscarded(subRecordData, nRemainingBytes)) { String msg = "Leftover " + nRemainingBytes + " bytes in subrecord data " + HexDump.ToHex(subRecordData); throw new RecordFormatException(msg); } _isPaddedToQuadByteMultiple = false; } } else { _isPaddedToQuadByteMultiple = false; } _uninterpretedData = null; } }