.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Change Block Attribute

7 REPLIES 7
SOLVED
Reply
Message 1 of 8
SRSDS
1160 Views, 7 Replies

Change Block Attribute

Hi,

I’m new to this and I do need to understand better how to access the BTR, read and write BRef, attDef, AttRef etc. But this has me stumped. There are a few different examples  but can’t find anything that works and don't know why.

 

I have inserted a block in modelspace, I have the BlockRefID and now want to change its attribute values.

This finds the attributes tags but doesn’t write the sValue. Can anyone spot why it isn’t writing the value to the block or suggest something better

 

    Public Sub ChangeAttributeValue(ByVal BlockRefID As ObjectId, ByVal sTagName As String, ByVal sValue As String)

        Dim doc As Document = Application.DocumentManager.MdiActiveDocument

        Dim db As Database = doc.Database

        Dim tr As Transaction = db.TransactionManager.StartTransaction()

        Dim br As BlockReference = DirectCast(tr.GetObject(BlockRefID, OpenMode.ForWrite), BlockReference)

        Dim RefBTR As BlockTableRecord = tr.GetObject(br.BlockTableRecord, OpenMode.ForRead)

        Dim attEnt As Entity

        Try

            For Each attID As ObjectId In RefBTR

                attEnt = tr.GetObject(attID, OpenMode.ForRead)

                If TypeOf attEnt Is AttributeDefinition Then

                    Dim attDef As AttributeDefinition = attEnt

                    Dim attRef As AttributeReference = New AttributeReference()

                    attRef.SetAttributeFromBlock(attDef, br.BlockTransform)

                    If attRef.Tag = sTagName Then

                        attRef.TextString = sValue

                        Exit Sub

                    End If

                End If

            Next

        Catch ex As Autodesk.AutoCAD.Runtime.Exception

            tr.Abort()

        Finally

            tr.Commit()

        End Try

    End Sub

 

Hope someone can help.

7 REPLIES 7
Message 2 of 8
chiefbraincloud
in reply to: SRSDS

The code you have there is not doing what you think it's doing.

 

What you have done is opened the block definition, created a New Attribute Reference, set it's value, then threw it in the trash.

 

What you need to do is skip the BlockTableRecord (definition).  Open the BlockReference as you have done, then change your For Each to:

 

For Each AttRefId in br.AttributeCollection

   dim AttRef as AttributeReference = tr.GetObject(AttRefId, OpenMode.ForWrite, false, true)

   If AttRef.Tag = sTagName then

        .....

   End If

Next

Dave O.                                                                  Sig-Logos32.png
Message 3 of 8
SRSDS
in reply to: chiefbraincloud

Thanks Chief,

 

Thats one of the few things I've tried. A similar procedure works fine with the dynamic block properties.

Strange thing is that the blockref (br) does show the 27 items in the DynamicBlockReferencePropertyCollection (which I can access and change) but 0 items in the AttributeColection when it has 3 Attributes. 

 

 

    Public Sub ChangeAttributeValue(ByVal BlockRefID As ObjectId, ByVal sTagName As String, ByVal sValue As String)
        Dim doc As Document = Application.DocumentManager.MdiActiveDocument
        Using db As Database = HostApplicationServices.WorkingDatabase()
            Using tr As Transaction = db.TransactionManager.StartTransaction()
                Try
                    Dim br As BlockReference = DirectCast(tr.GetObject(BlockRefID, OpenMode.ForWrite), BlockReference)
                    Dim attcol As AttributeCollection = br.AttributeCollection
                    For Each attId As ObjectId In attcol
                        Dim attref As AttributeReference = DirectCast(tr.GetObject(attId, OpenMode.ForWrite), AttributeReference)
                        If attref.Tag = sTagName Then
                            attref.TextString = sValue
                        End If
                    Next
                    tr.Commit()
                Catch ex As Autodesk.AutoCAD.Runtime.Exception
                    ed.WriteMessage("Exception: " + ex.Message)
                Finally
                    tr.Dispose()
                End Try
            End Using
            db.Dispose()
        End Using
    End Sub

 

Message 4 of 8
SRSDS
in reply to: SRSDS

I should have copied the code changes you suggested but the result is the same. 0 AttRefs in the collection.

 

 

   Public Sub ChangeAttributeValue(ByVal BlockRefID As ObjectId, ByVal sTagName As String, ByVal sValue As String)
        Dim doc As Document = Application.DocumentManager.MdiActiveDocument
        Dim db As Database = doc.Database
        Dim tr As Transaction = db.TransactionManager.StartTransaction()
        Dim br As BlockReference = DirectCast(tr.GetObject(BlockRefID, OpenMode.ForWrite), BlockReference)
        Try
            For Each AttRefId In br.AttributeCollection
                Dim AttRef As AttributeReference = tr.GetObject(AttRefId, OpenMode.ForWrite, False, True)
                If AttRef.Tag = sTagName Then
                    AttRef.TextString = sValue
                    Exit Sub
                End If
            Next
        Catch ex As Autodesk.AutoCAD.Runtime.Exception
            tr.Abort()
        Finally
            tr.Commit()
        End Try
    End Sub

 

Message 5 of 8
SRSDS
in reply to: SRSDS

I think the problem is my Addblock routine. It adds a block reference but without any attributes. Why would it do that? 

 

 

    Public Sub AddBlock(ByVal blockname)
        Dim db As Database = HostApplicationServices.WorkingDatabase()
        Using tr As Transaction = db.TransactionManager.StartTransaction()
            ' Test if block exists in the block table
            Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
            Dim id As ObjectId = bt(blockname)
            Dim br As New BlockReference(New Point3d(0, 0, 0), id)
            Dim btr As BlockTableRecord = DirectCast(tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite), BlockTableRecord)
            ' Add the block reference to Model space
            btr.AppendEntity(br)
            tr.AddNewlyCreatedDBObject(br, True)
            BlockRefID = br.ObjectId
            ' Commit the transaction
            tr.Commit()
        End Using
    End Sub

 

Message 6 of 8
chiefbraincloud
in reply to: SRSDS

Basically this tells me you did not properly add the Attribute References to the BlockReference when it was inserted, a process which was not necessary if coding in VBA or .NET COM automation, or LSP.

 

The For Each loop you had in your original post is just short of what is needed to accomplish that.

 

I see that while I have been typing and searching Through The Interface for an example you have arrived at the same conclusion.

 

Give me a minute, I'll find an example.

 

 

Dave O.                                                                  Sig-Logos32.png
Message 7 of 8
chiefbraincloud
in reply to: SRSDS

I really hate the way this forum mangles code pasted directly from Visual studio

 

Anyway, I couldn't find the blog post I was looking for, so I just tweeked the code you posted.  Note, I changed the variable name for the ModelSpace BlockTableRecord, just to reduce confusion, and I inserted the necessary block of code for adding the attributes.  As you read it, you'll see there is not really anything magical going on, it's just that with other forms of autocad automation, this was never necessary before.  Changes Highlighted.

 

Public Sub AddBlock(ByVal blockname)
 Dim db As Database = HostApplicationServices.WorkingDatabase()
 Using tr As Transaction = db.TransactionManager.StartTransaction()
  ' Test if block exists in the block table
  Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
  Dim id As ObjectId = bt(blockname)
  Dim btr As BlockTableRecord = tr.GetObject(id, OpenMode.ForRead, False, True)
  Dim br As New BlockReference(New Point3d(0, 0, 0), id)
  Dim MS As BlockTableRecord = DirectCast(tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite), BlockTableRecord)
  ' Add the block reference to Model space
  MS.AppendEntity(br)
  tr.AddNewlyCreatedDBObject(br, True)
  If btr.HasAttributeDefinitions Then
   Dim AtDef As AttributeDefinition, AttRef As AttributeReference
   For Each SubEntId As ObjectId In btr
    If SubEntId.ObjectClass.Name = "AcDbAttributeDefinition" Then
     AtDef = tr.GetObject(SubEntId, OpenMode.ForRead, False, True)
     AttRef = New AttributeReference
     AttRef.SetAttributeFromBlock(AtDef, br.BlockTransform)
     br.AttributeCollection.AppendAttribute(AttRef)
     tr.AddNewlyCreatedDBObject(AttRef, True)
     AtDef.Dispose()
     AttRef.Dispose()
    End If
   Next
  End If
  BlockRefID = br.ObjectId
  ' Commit the transaction
  tr.Commit()
 End Using
End Sub

Dave O.                                                                  Sig-Logos32.png
Message 8 of 8
SRSDS
in reply to: chiefbraincloud

Thanks so much!!

Been stumbling around for quite a while. At least I have a slightly better understanding now.

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost