.NET

Reply
Mentor
mgorecki
Posts: 414
Registered: ‎09-23-2004
Message 11 of 16 (123 Views)

Re: Inserting a Block with Attributes

05-06-2014 01:25 PM in reply to: mgorecki

Unfortunately, the blocks being read in, still do not have usable attributes.  Also, I cannot insert any of them manually.

Mentor
mgorecki
Posts: 414
Registered: ‎09-23-2004
Message 12 of 16 (113 Views)

Re: Inserting a Block with Attributes

05-07-2014 08:55 AM in reply to: norman.yuan

Hi Norman,

Ok, I did some additional code thinking that maybe the blocks keep getting overwritten when the same block needs to get inserted.

I put a break in as you suggested and found it keeps failing in the "Else" section

Dim bref AsNew DatabaseServices.BlockReference(InsPt, myBT(baseName))  <--crashes here (InsPt and basename are valid)

I know you're busy, but could you explain BlockTables and BlockTableReference, as I can't see why this wouldn't work.

Public Sub InsertSMDComp(ByVal InsPt As Point3d, ByVal BlockName As String, ByVal RefDes As String, _
        ByVal rotation As Double, ByVal scale As Double)
        Dim smdTransMan As DatabaseServices.TransactionManager
        Dim smdTrans As DatabaseServices.Transaction
        Dim myDwg As Document
        Dim myBT As BlockTable
        Dim myBTR As BlockTableRecord
        Dim baseName As String = System.IO.Path.GetFileNameWithoutExtension(BlockName)

        myDwg = Application.DocumentManager.MdiActiveDocument
        smdTransMan = myDwg.TransactionManager
        smdTrans = smdTransMan.StartTransaction
        myBT = myDwg.Database.BlockTableId.GetObject(OpenMode.ForRead)
        If myBT.Has(baseName) Then
            myBTR = myBT(BlockTableRecord.ModelSpace).GetObject(OpenMode.ForWrite)
            Dim myBlockRef As New DatabaseServices.BlockReference(InsPt, myBT(baseName))
            myBlockRef.Rotation = rotation
            myBlockRef.ScaleFactors = New Geometry.Scale3d(scale, scale, scale)
            myBTR.AppendEntity(myBlockRef)
            smdTrans.AddNewlyCreatedDBObject(myBlockRef, True)
            'Set the Attribute Value
            Dim myEnt As DatabaseServices.Entity
            For Each id As ObjectId In myBTR
                myEnt = id.GetObject(OpenMode.ForRead)
                If TypeOf myEnt Is AttributeDefinition Then
                    Dim myAttDef As AttributeDefinition = myEnt
                    'Create attribute reference based on the attributeDefinition
                    Dim attrRef As New AttributeReference
                    attrRef.SetAttributeFromBlock(myAttDef, myBlockRef.BlockTransform)
                    attrRef.TextString = RefDes
                    myBlockRef.AttributeCollection.AppendAttribute(attrRef)
                    smdTrans.AddNewlyCreatedDBObject(attrRef, True)
                End If
            Next
            smdTrans.Commit()
        Else
            Try
                Using db As Database = New Database(False, True)
                    Dim myDB As Database = myDwg.Database
                    db.ReadDwgFile(BlockName, IO.FileShare.Read, True, "")
                    'Dim bt As BlockTable = smdTrans.GetObject(myDB.BlockTableId, OpenMode.ForRead, True)
                    Dim btr As BlockTableRecord = smdTrans.GetObject(myBT(BlockTableRecord.ModelSpace), OpenMode.ForWrite, True)
                    Dim bref As New DatabaseServices.BlockReference(InsPt, myBT(baseName))
                    bref.Rotation = rotation
                    bref.ScaleFactors = New Scale3d(scale, scale, scale)
                    btr.AppendEntity(bref)
                    smdTrans.AddNewlyCreatedDBObject(bref, True)
                    'Set the Attribute Value
                    Dim myEnt As DatabaseServices.Entity
                    For Each id As ObjectId In btr
                        myEnt = id.GetObject(OpenMode.ForRead)
                        If TypeOf myEnt Is AttributeDefinition Then
                            Dim myAttDef As AttributeDefinition = myEnt
                            'Create attribute reference based on the attributeDefinition
                            Dim attrRef As New AttributeReference
                            attrRef.SetAttributeFromBlock(myAttDef, bref.BlockTransform)
                            attrRef.TextString = RefDes
                            bref.AttributeCollection.AppendAttribute(attrRef)
                            smdTrans.AddNewlyCreatedDBObject(attrRef, True)
                        End If
                    Next
                    smdTrans.Commit()
                End Using
            Catch ex As Autodesk.AutoCAD.Runtime.Exception
                MsgBox(ex.ToString)
            End Try
        End If

        smdTrans.Dispose()
        smdTransMan.Dispose()
    End Sub

 

 Thank you

*Expert Elite*
norman.yuan
Posts: 994
Registered: ‎04-27-2009
Message 13 of 16 (106 Views)

Re: Inserting a Block with Attributes

05-07-2014 12:25 PM in reply to: mgorecki

Well, the error is quite obvious to me: in the the If myBT.Has(baseName) Then... Else...End If statement, I saw your logic is like:

 

If The block definition in fond in the BlockTable Then

    ''Insert the Block

Else

   ''Create a side Database from the block file;

   ''Insert it into the drawing database->Here You FORGOT TO DO IT!!!

   ''Insert the block

End If

 

Since in the Else clause you did not insert the Block file into the drawing as Block definition (e.g. MyDb.Insert(baseName, db, False)), thus the error.

 

Your code in the Then... branch is wrong too, (had you test it with a drawing that already has the block definition in it, you would have run into an exception at

 

myBlockRef=New BlockReference(intPt, myBT)

 

Because, myBT is a BlockTable, not a BlockTableRecord Id (type of ObjectId). It should be

 

myBlockref=New BlockReference(intPt, myBT(baseName))

 

Also, you might want to lean up your code a bit, because you have duplicated code to create Blockreference in both branches of the IF.. statement. You can do it this way (psuedo-code)

 

//Get BlockTable

BlockTable bt=...

 

//Test if the block definition exists or not

Dim BtrId As ObjectId=ObjectId.Null

If bt.Has(baseName) Then btrId=bt(baseName)

 

If BtrId.IsNull Then

    //Insert block file

    Using dbAs Database=new Database(False,True)

        db.ReadDwgFile(....)

        BtrId = myDb.Insert(baseName, db, False)

    End Using

End If

 

//Now, your are ready to create a Blcokreference

myBlockRef=New Blockreference(insPt, BtrId);

....

 

Mentor
mgorecki
Posts: 414
Registered: ‎09-23-2004
Message 14 of 16 (93 Views)

Re: Inserting a Block with Attributes

05-08-2014 10:05 AM in reply to: norman.yuan

Ok, the drawings are being read into my drawing as blocks (with attributes).

Here's the part I don't understand, I added this to check for the attribute definition:

myBTR.AppendEntity(bref)

smdTrans.AddNewlyCreatedDBObject(bref,True)

'Set the Attribute Value

If myBTR.HasAttributeDefinitions Then....

 

Even though the drawings (consisting of a polyline and an attribute definition) get read into my drawing as blocks (they have the polyline and att. def. in the block), myBTR.HasAttributeDefinitions shows no attribute definitions.  It skips the code after this if.  The watch also shows no attribute definitions.  How can that be if I can see them?  

*Expert Elite*
norman.yuan
Posts: 994
Registered: ‎04-27-2009
Message 15 of 16 (84 Views)

Re: Inserting a Block with Attributes

05-08-2014 11:46 AM in reply to: mgorecki

In your code, myBTR is ModelSpace block, NOT the block definition that you use to create the BlockReference!

 

You need to open the block definition then loop thorugh its AttributeDefinition. Something, after you created your BlockReference, like:

 

Dim bDef As BlockTableRecord=myTran.GetObject(myBT{baseName), OpenMode.ForRead)

 

If (bDef.HasAttributeDefinitions) Then

    ...

End If

Mentor
mgorecki
Posts: 414
Registered: ‎09-23-2004
Message 16 of 16 (78 Views)

Re: Inserting a Block with Attributes

05-08-2014 03:41 PM in reply to: norman.yuan

Hi Norman, thank you for being patient with me.  This was quite a learning experience, and I appreciate the time you spent.

Here is the updated code, cleaned up for anyone who needs it.

 

Public Sub InsertSMDComp(ByVal InsPt As Point3d, ByVal BlockName As String, ByVal RefDes As String, _
        ByVal rotation As Double, ByVal scale As Double)
        Dim smdTransMan As DatabaseServices.TransactionManager
        Dim smdTrans As DatabaseServices.Transaction
        Dim myDwg As Document
        Dim myBT As BlockTable
        Dim myBTR As BlockTableRecord
        Dim baseName As String = (System.IO.Path.GetFileNameWithoutExtension(BlockName))

        myDwg = Application.DocumentManager.MdiActiveDocument
        smdTransMan = myDwg.TransactionManager
        smdTrans = smdTransMan.StartTransaction
        myBT = myDwg.Database.BlockTableId.GetObject(OpenMode.ForRead)

        Dim BtrId As ObjectId = ObjectId.Null
        If myBT.Has(baseName) Then BtrId = myBT(baseName) 'Drawing has the block
        If BtrId.IsNull Then 'Drawing does not have the block, read the drawuing file to create the block
            Try
                Using db As Database = New Database(False, True)
                    Dim myDB As Database = myDwg.Database
                    db.ReadDwgFile(BlockName, IO.FileShare.Read, True, "") 'Read the drawing file
                    BtrId = myDB.Insert(baseName, db, False) 'Insert drawing file as block into database
                End Using
            Catch ex As Autodesk.AutoCAD.Runtime.Exception
                MsgBox(ex.ToString)
            End Try
        End If
        ' Create the block reference in the drawing, and add the attribute text
        myBTR = myBT(BlockTableRecord.ModelSpace).GetObject(OpenMode.ForWrite)
        Dim bref As New DatabaseServices.BlockReference(InsPt, myBT(baseName))
        bref.Rotation = rotation
        bref.ScaleFactors = New Scale3d(scale, scale, scale)
        myBTR.AppendEntity(bref)
        smdTrans.AddNewlyCreatedDBObject(bref, True)
        Dim bDef As BlockTableRecord = smdTrans.GetObject(myBT(baseName), OpenMode.ForRead)
        'Set the Attribute Value
        If bDef.HasAttributeDefinitions Then
            Dim myEnt As DatabaseServices.Entity
            For Each id As ObjectId In bDef
                myEnt = id.GetObject(OpenMode.ForRead)
                If TypeOf myEnt Is AttributeDefinition Then
                    Dim myAttDef As AttributeDefinition = myEnt
                    'Create attribute reference based on the attributeDefinition
                    Dim attrRef As New AttributeReference
                    attrRef.SetAttributeFromBlock(myAttDef, bref.BlockTransform)
                    attrRef.TextString = RefDes
                    bref.AttributeCollection.AppendAttribute(attrRef)
                    smdTrans.AddNewlyCreatedDBObject(attrRef, True)
                End If
            Next
        End If
        smdTrans.Commit()

        smdTrans.Dispose()
        smdTransMan.Dispose()
    End Sub

 

 

Announcements
Are you familiar with the Autodesk Expert Elites? The Expert Elite program is made up of customers that help other customers by sharing knowledge and exemplifying an engaging style of collaboration. To learn more, please visit our Expert Elite website.
Need installation help?

Start with some of our most frequented solutions or visit the Installation and Licensing Forum to get help installing your software.