I try to add blocks into AutoCAD with attributes and I am almost there! But it does weird things with annotative blocks.
The function is this:
Public Shared Function hzInsertBlock(ByVal pntInsert As Geometry.Point3d,
ByVal strBlockName As String,
ByVal dScale As Double,
ByVal strLayerName As String) As DatabaseServices.ObjectId
' TODO: Check block if is dynamic and do other things
Dim retVal As DatabaseServices.ObjectId = Nothing
Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
' Get the current document editor
Dim ed As Editor = doc.Editor
' Get the current database
Using db As Database = HostApplicationServices.WorkingDatabase
' Get the current transaction
Dim tr As Transaction = db.TransactionManager.StartTransaction
' using transaction
Using tr
Try
' Open current space for write
Dim myBT As BlockTable = doc.Database.BlockTableId.GetObject(OpenMode.ForRead)
Dim myBTR As BlockTableRecord = CType(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
' Annotation Scales
Dim ocm As ObjectContextManager = db.ObjectContextManager
Dim occ As ObjectContextCollection = ocm.GetContextCollection("ACDB_ANNOTATIONSCALES")
' Insert Block
Dim myBlockDef As BlockTableRecord = myBT(strBlockName).GetObject(OpenMode.ForRead)
Dim myBlockRef As New DatabaseServices.BlockReference(pntInsert, myBT(strBlockName))
Dim obj As ObjectId = myBTR.AppendEntity(myBlockRef)
tr.AddNewlyCreatedDBObject(myBlockRef, True)
' Set Attribute Value
Dim myAttColl As DatabaseServices.AttributeCollection
Dim myEnt As DatabaseServices.Entity
Dim myBTREnum As BlockTableRecordEnumerator
myAttColl = myBlockRef.AttributeCollection
myBTREnum = myBlockDef.GetEnumerator
While myBTREnum.MoveNext
myEnt = myBTREnum.Current.GetObject(OpenMode.ForWrite)
If TypeOf myEnt Is DatabaseServices.AttributeDefinition Then
Dim myAttDef As DatabaseServices.AttributeDefinition = myEnt
Dim myAttRef As New DatabaseServices.AttributeReference
myAttRef.SetAttributeFromBlock(myAttDef, myBlockRef.BlockTransform)
myAttColl.AppendAttribute(myAttRef)
tr.AddNewlyCreatedDBObject(myAttRef, True)
End If
End While
' Set Layer
myBlockRef.Layer = strLayerName
' Set Scale
myBlockRef.ScaleFactors = New Geometry.Scale3d(dScale, dScale, dScale)
' Set Current Annotative Scale if block is Annotative
If myBlockRef.Annotative = AnnotativeStates.True Then
Dim AnnoObj As DBObject = tr.GetObject(obj, OpenMode.ForRead)
Internal.ObjectContexts.AddContext(AnnoObj, occ.CurrentContext)
End If
' Set return value
retVal = myBlockRef.ObjectId
' Commit transaction
tr.Commit()
Catch ex As Autodesk.AutoCAD.Runtime.Exception
ed.WriteMessage("Error: {0}" & vbLf & "Stack trace: {1}", ex.Message, ex.StackTrace)
End Try
End Using ' dispose transaction
End Using ' dispose database
' return
Return retVal
End Function
For filling the attributes I have a different function. Above is the function that will place a block and takes the attributes from the definition and adds it to the reference. There are two problems. One problem is that the attribute is always the size of the original, even while I add the current scale 1:500 or 1:250 to the block, the other problem is that the first placed block has the attribute at the right position, all others will have the attributes one textline lower. See image.
The red one is the only correct one.