Jump to content

.NET Update Block Attribute in Paperspace


SuperNim143
 Share

Recommended Posts

I am developing an application that automatically generates a set of drawings from a template using user input and an access dbase.

 

As a part of this I have code that is called to update a single block attribute. It works great for the blocks that are in model space!

 

My issue is with Paperspace. Instead of updating the existing attribute it adds a new attribute with the same name.

 

How do I access the Paperspace block attributes?!? The code used for this is below.

 

Private Sub UpdateBlockAttribute(acBlkRef As BlockReference, attTag As String, textValue As String, Optional modelSpace As Boolean = True)
       Dim acBlkTable As BlockTable
       Dim acBlkDef As BlockTableRecord
       Dim acCurLyr As ObjectId
       Dim acAttRef As DatabaseServices.AttributeReference = Nothing
       Dim attFound As Boolean = False

       Try

           acBlkTable = acTrans.GetObject(acdb.BlockTableId, OpenMode.ForRead)
           acBlkDef = DirectCast(acBlkTable(acBlkRef.Name).GetObject(OpenMode.ForRead), BlockTableRecord)

           Dim acLyrTbl As LayerTable = acTrans.GetObject(acdb.LayerTableId, OpenMode.ForRead)
           acCurLyr = acdb.Clayer
           If acLyrTbl.Has("0") Then
               acdb.Clayer = acLyrTbl("0")
           End If

           For Each acEntId In acBlkDef

               Dim acEnt As Entity = acTrans.GetObject(acEntId, OpenMode.ForRead)
               If Not IsNothing(acEnt) Then

                   If acEnt.GetType.ToString = "Autodesk.AutoCAD.DatabaseServices.AttributeDefinition" Then

                       Dim acAttDef As AttributeDefinition = DirectCast(acEnt, AttributeDefinition)

                       If Not IsNothing(acAttDef) And Not acAttDef.Constant Then

                           acAttRef = New AttributeReference
                           acAttRef.SetAttributeFromBlock(acAttDef, DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).BlockTransform)

                           If acAttDef.Tag.ToString = attTag Or acAttRef.Tag.ToString = attTag Then
                               attFound = True
                               Exit For
                           End If

                       End If

                   End If

               End If

           Next

           DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).AttributeCollection.AppendAttribute(acAttRef)

           'IF THE ATTRIBUTE DOES NOT EXIST, ADD A NEW ONE...
           If Not attFound Then
               acAttRef.Tag = attTag
               acAttRef.Justify = AttachmentPoint.MiddleCenter
               acTrans.AddNewlyCreatedDBObject(acAttRef, True)
               acAttRef.UpgradeOpen()
           End If

           acAttRef.TextString = textValue

           acAttRef.DowngradeOpen()


           acdb.Clayer = acCurLyr
       Catch ex As Exception
           MsgBox("Update Block Attribute: " & ex.Message)

       End Try
   End Sub

Link to comment
Share on other sites

I am developing an application that automatically generates a set of drawings from a template using user input and an access dbase.

 

As a part of this I have code that is called to update a single block attribute. It works great for the blocks that are in model space!

 

My issue is with Paperspace. Instead of updating the existing attribute it adds a new attribute with the same name.

 

How do I access the Paperspace block attributes?!? The code used for this is below.

 

Private Sub UpdateBlockAttribute(acBlkRef As BlockReference, attTag As String, textValue As String, Optional modelSpace As Boolean = True)
       Dim acBlkTable As BlockTable
       Dim acBlkDef As BlockTableRecord
       Dim acCurLyr As ObjectId
       Dim acAttRef As DatabaseServices.AttributeReference = Nothing
       Dim attFound As Boolean = False

       Try

           acBlkTable = acTrans.GetObject(acdb.BlockTableId, OpenMode.ForRead)
           acBlkDef = DirectCast(acBlkTable(acBlkRef.Name).GetObject(OpenMode.ForRead), BlockTableRecord)

           Dim acLyrTbl As LayerTable = acTrans.GetObject(acdb.LayerTableId, OpenMode.ForRead)
           acCurLyr = acdb.Clayer
           If acLyrTbl.Has("0") Then
               acdb.Clayer = acLyrTbl("0")
           End If

           For Each acEntId In acBlkDef

               Dim acEnt As Entity = acTrans.GetObject(acEntId, OpenMode.ForRead)
               If Not IsNothing(acEnt) Then

                   If acEnt.GetType.ToString = "Autodesk.AutoCAD.DatabaseServices.AttributeDefinition" Then

                       Dim acAttDef As AttributeDefinition = DirectCast(acEnt, AttributeDefinition)

                       If Not IsNothing(acAttDef) And Not acAttDef.Constant Then

                           acAttRef = New AttributeReference
                           acAttRef.SetAttributeFromBlock(acAttDef, DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).BlockTransform)

                           If acAttDef.Tag.ToString = attTag Or acAttRef.Tag.ToString = attTag Then
                               attFound = True
                               Exit For
                           End If

                       End If

                   End If

               End If

           Next

           DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).AttributeCollection.AppendAttribute(acAttRef)

           'IF THE ATTRIBUTE DOES NOT EXIST, ADD A NEW ONE...
           If Not attFound Then
               acAttRef.Tag = attTag
               acAttRef.Justify = AttachmentPoint.MiddleCenter
               acTrans.AddNewlyCreatedDBObject(acAttRef, True)
               acAttRef.UpgradeOpen()
           End If

           acAttRef.TextString = textValue

           acAttRef.DowngradeOpen()


           acdb.Clayer = acCurLyr
       Catch ex As Exception
           MsgBox("Update Block Attribute: " & ex.Message)

       End Try
   End Sub

 

Welcome to CADTutor.

 

You haven't posted complete code, or a sample drawing, so it will be hard for me (or others) to pinpoint the exact issue you're facing.

 

That said, this may be of some help:

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;

using acApp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace BlackBox.AutoCAD.Samples
{
   class FOO
   {
       private DocumentCollection acDocs = acApp.DocumentManager;
       void UpdateBlockAttributes(string blockName, string tagString, string textString)
       {
           Document doc = acDocs.MdiActiveDocument;
           Database db = doc.Database;
           Editor ed = doc.Editor;
           tagString = tagString.ToUpper();

           // set clayer to "0" layer
           acApp.SetSystemVariable("clayer", "0");
           
           using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
           {
               // get the blocktable
               BlockTable bt = 
                   (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);

               // instead of iterating the entire blocktable, check to see if 
               // the target block exists within this database's blocktable
               if (!bt.Has(blockName))
               {
                   // if not, then notify user, and exit
                   // uncomment the notification, if you feel it useful - I tend
                   // to not call writemessage() within non-commandmethod methods
                   //ed.WriteMessage("\nerror; Block \"{0}\" does not exist ", blockName);
                   return;
               }

               // otherwise, open the blocktablerecord
               BlockTableRecord btr = 
                   (BlockTableRecord)tr.GetObject(bt[blockName], OpenMode.ForRead);
               
               // and instead, simply iterate all inserts of the target blocktablerecord
               foreach (ObjectId id in btr.GetBlockReferenceIds(true, false))
               {
                   BlockReference br =
                       (BlockReference)tr.GetObject(id, OpenMode.ForRead);

                   // <-- check for locked layer here?

                   // check for attributes
                   foreach (ObjectId attId in br.AttributeCollection)
                   {
                       AttributeReference ar =
                           tr.GetObject(attId, OpenMode.ForRead) as AttributeReference;

                       if (ar != null && ar.Tag.ToUpper() == tagString)
                       {
                           ar.UpgradeOpen();
                           ar.TextString = textString;
                           ar.DowngradeOpen();
                       }
                   }
               }

               tr.Commit();
           }
       }
   }
}

 

 

 

Cheers

Link to comment
Share on other sites

I am not a .NET person but as the OP wants paperspace wouldn't you need to check the block location and make sure its paperspace plus on the correct layout tab. In lisp (setq ss1 (ssget "x" (list (cons 0 "INSERT") (cons 2 bname)(cons 410 tabname)))) in 99.9% for me this returns only 1 block which is the title block but could return more.

Link to comment
Share on other sites

I am not a .NET person but as the OP wants paperspace wouldn't you need to check the block location and make sure its paperspace plus on the correct layout tab. In lisp (setq ss1 (ssget "x" (list (cons 0 "INSERT") (cons 2 bname)(cons 410 tabname)))) in 99.9% for me this returns only 1 block which is the title block but could return more.

 

I understood the OP to seeking to modify many if not all BlockReferences (by blockName), but was only successful with those located in ModelSpace.

 

Perhaps the OP can clarify shortly.

 

Cheers

Link to comment
Share on other sites

Thanks for your responses. I am calling this routine to populate an individual attribute on a single instance of the block. It works great for everything in model space.

 

The blocks that I have trouble with are a titleblock and an additional description block that is contained on Layout1 in paperspace. Instead of updating the existing attribute, it adds a brand new one with the same name.

I am using the same Function and Sub for both model and paperspace.

 

First I call a function that retrieves the block reference. (TBClean is the blockname in this case)

 

acBlkRef = InsertBlockReference("TBClean", False, New Point3d(-0.5, 0.5, 0), True, "TITLE", Colors.Color.FromColorIndex(Colors.ColorMethod.ByAci, 0)) 'black

 

Then I call the sub to update the attribute. (DESCRIPTION(CONT) is the attribute.)

UpdateBlockAttribute(acBlkRef, "DESCRIPTION(CONT)", strDesc)

 

Below is the code for the Function and Sub

 Private Function InsertBlockReference(blockName As String, modelSpace As Boolean, insPt As Point3d, updateExisting As Boolean, Optional layerName As String = "", Optional layerColor As Colors.Color = Nothing) As BlockReference
       Dim acBlkTable As BlockTable
       Dim acLyrTbl As LayerTable
       Dim acCurLyrID As ObjectId
       Dim acBlkRef As BlockReference = Nothing
       Dim acSpaceID As ObjectId
       Dim acBlkTableRecord As BlockTableRecord
       Dim acBlkTableRecordID As ObjectId
       Dim acNewLyr As New LayerTableRecord

       Try
           acBlkTable = acTrans.GetObject(acdb.BlockTableId, OpenMode.ForRead)

           If IsNothing(acBlkTable) Then
               'InsertBlockReference = Nothing
               Return Nothing
           End If

           'store current layer to make it current again after function
           acLyrTbl = acTrans.GetObject(acdb.LayerTableId, OpenMode.ForRead)
           acCurLyrID = acdb.Clayer

           'if a layer is specified, set it to the current layer
           If layerName <> "" Then
               If acLyrTbl.Has(layerName) Then
                   acdb.Clayer = acLyrTbl(layerName)
               Else
                   acNewLyr.Name = layerName
                   acNewLyr.Color = layerColor
                   acLyrTbl.UpgradeOpen()
                   acLyrTbl.Add(acNewLyr)
                   acLyrTbl.DowngradeOpen()
                   acTrans.AddNewlyCreatedDBObject(acNewLyr, True)
                   acdb.Clayer = acLyrTbl(layerName)
               End If
           End If

           'check to see if the block is already in the CAD file
           If acBlkTable.Has(blockName) And updateExisting Then
               'get the BlockReference for the block
               acBlkTableRecord = DirectCast(acTrans.GetObject(acBlkTable.Item(blockName), OpenMode.ForRead), BlockTableRecord)

               Dim acObjIdColl As ObjectIdCollection = acBlkTableRecord.GetBlockReferenceIds(True, True)
               Dim acEntId As ObjectId

               For Each acEntId In acObjIdColl
                   'acBlkRef = acEntId.GetObject(OpenMode.ForRead)
                   acBlkRef = TryCast(acEntId.GetObject(OpenMode.ForWrite), BlockReference)

               Next
           Else
               'if the block is NOT in the CAD file, insert it from the dwg file
               If IO.File.Exists(Me.txtCADBlocksPath.Text & "\" & blockName & ".dwg") Then
                   Dim acBlkSourceDb As Database
                   acBlkSourceDb = New Database(False, True)
                   acBlkSourceDb.ReadDwgFile(Me.txtCADBlocksPath.Text & "\" & blockName & ".dwg", FileOpenMode.OpenForReadAndAllShare, True, Nothing)
                   acBlkTableRecordID = acdb.Insert(blockName, acBlkSourceDb, True)

                   'insert the new block
                   acBlkRef = New BlockReference(insPt, acBlkTableRecordID)

                   'select the correct block table record to insert the new block into... ModelSpace or PaperSpace
                   If modelSpace = True Then
                       acSpaceID = acBlkTable(BlockTableRecord.ModelSpace)
                   Else
                       acSpaceID = acBlkTable(BlockTableRecord.PaperSpace)
                   End If

                   acBlkTableRecord = DirectCast(acTrans.GetObject(acSpaceID, OpenMode.ForWrite), BlockTableRecord)
                   acBlkTableRecord.AppendEntity(acBlkRef)

                   acTrans.AddNewlyCreatedDBObject(acBlkRef, True)

               Else
                   MsgBox("InsertBlock: Block """ & blockName & """ DWG not found")
                   Return Nothing

               End If
           End If

       Catch ex As Exception
           MsgBox("InsertBlock: " & ex.Message)
       Finally
           acdb.Clayer = acCurLyrID

       End Try

       Return acBlkRef

   End Function

 

 Private Sub UpdateBlockAttribute(acBlkRef As BlockReference, attTag As String, textValue As String, Optional modelSpace As Boolean = True)
       Dim acBlkTable As BlockTable
       Dim acBlkDef As BlockTableRecord
       Dim acCurLyr As ObjectId
       Dim acAttRef As DatabaseServices.AttributeReference = Nothing
       Dim attFound As Boolean = False

       Try

           acBlkTable = acTrans.GetObject(acdb.BlockTableId, OpenMode.ForRead)
           'acBlkDef = DirectCast(acBlkTable(acBlkRef.Name).GetObject(OpenMode.ForRead), BlockTableRecord)

           Dim acLyrTbl As LayerTable = acTrans.GetObject(acdb.LayerTableId, OpenMode.ForRead)
           acCurLyr = acdb.Clayer
           If acLyrTbl.Has("0") Then
               acdb.Clayer = acLyrTbl("0")
           End If

           If acBlkTable.Has(acBlkRef.Name) Then
               acBlkDef = acTrans.GetObject(acBlkRef.Id, OpenMode.ForRead)


           End If
           For Each acEntId In acBlkDef

               Dim acEnt As Entity = acTrans.GetObject(acEntId, OpenMode.ForRead)
               If Not IsNothing(acEnt) Then

                   If acEnt.GetType.ToString = "Autodesk.AutoCAD.DatabaseServices.AttributeDefinition" Then

                       Dim acAttDef As AttributeDefinition = DirectCast(acEnt, AttributeDefinition)

                       If Not IsNothing(acAttDef) And Not acAttDef.Constant Then

                           acAttRef = New AttributeReference
                           acAttRef.SetAttributeFromBlock(acAttDef, DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).BlockTransform)

                           If acAttDef.Tag.ToString = attTag Or acAttRef.Tag.ToString = attTag Then
                               attFound = True
                               Exit For
                           End If

                       End If

                   End If

               End If

           Next

           DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).AttributeCollection.AppendAttribute(acAttRef)

           'IF THE ATTRIBUTE DOES NOT EXIST, ADD A NEW ONE...
           If Not attFound Then
               acAttRef.Tag = attTag
               acAttRef.Justify = AttachmentPoint.MiddleCenter
               acTrans.AddNewlyCreatedDBObject(acAttRef, True)
               acAttRef.UpgradeOpen()
           End If

           acAttRef.TextString = textValue

           acAttRef.DowngradeOpen()

           acBlkDef.SynchronizeAttributes()

           acdb.Clayer = acCurLyr
       Catch ex As Exception
           MsgBox("Update Block Attribute: " & ex.Message)

       End Try
   End Sub

 

I hope all of that makes sense.

 

I will have to clear some confidential data from the drawings before they could be posted, but I can do that if you still need them.

Link to comment
Share on other sites

Thanks for clarifying.

 

So forgive my asking, as there must be a reason that I am overlooking, but if you're programmatically inserting the BlockReference and then modifying said BlockReference's Attributes, why not just manually save a copy of the corrected block and insert/overwrite the BlockTableRecord?

 

You could even first iterate the existing INSERTS as I show above, storing values, and properties as needed before hand, post-populating said values in resultant blocks as needed.

 

Cheers

Link to comment
Share on other sites

  • 2 weeks later...

Sorry I did not respond. I have been tied up out of the office for a while.

 

This program is going to be used by our drafters. The idea is that it will be fairly dynamic. They will be able to place their block (using the appropriate block name and attribute names) in a folder and point the program to that location. This will allow them to make the block appearance fit with the customer. The program will update that block for them based on their selections. Looking for the attributes presence in the block and adding it if does not exist will ensure that all required fields are present in the block.

 

We are trying to steer the drafting leads in a more robust direction, but currently this is what they want.

 

The last bit of code that you sent, would that address the paperspace attribute issue?

 

From what I can tell my issue is not opening or reading the paperspace blocks, but locating the attributes.

For some reason when it compares the .tag to attTag it never finds a match, even if it DOES exist.

And this is only on the paper space. That's what I don't understand.

Is the issue possibly that I am not directing it to a particular layout?

 

I am going to take a closer look at the code you provided now that I am back in the office.

 

Thanks again for your input.

Link to comment
Share on other sites

Sorry I did not respond. I have been tied up out of the office for a while.

 

This program is going to be used by our drafters. The idea is that it will be fairly dynamic. They will be able to place their block (using the appropriate block name and attribute names) in a folder and point the program to that location. This will allow them to make the block appearance fit with the customer. The program will update that block for them based on their selections. Looking for the attributes presence in the block and adding it if does not exist will ensure that all required fields are present in the block.

 

We are trying to steer the drafting leads in a more robust direction, but currently this is what they want.

 

The last bit of code that you sent, would that address the paperspace attribute issue?

 

From what I can tell my issue is not opening or reading the paperspace blocks, but locating the attributes.

For some reason when it compares the .tag to attTag it never finds a match, even if it DOES exist.

And this is only on the paper space. That's what I don't understand.

Is the issue possibly that I am not directing it to a particular layout?

 

I am going to take a closer look at the code you provided now that I am back in the office.

 

Thanks again for your input.

 

No worries; I am working all too many hours myself lately, and it doesn't appear to be letting up anytime soon.

 

In any event, perhaps it would be prudent to post a sample drawing, that you can reproduce this issue in, that way we're not having to setup a sample data set & code, etc. from scratch in order to try and help?

 

Cheers

Link to comment
Share on other sites

terminal_template_WIPED.dwg

 

A wiped version of the template dwg is attached. In this case I am updating the DESCRIPTION(CONT) attribute on the TBCLEAN title block in paperspace.

 

Like I said it doesn't find the existing attribute so it then creates a new one with the same name and updates that value.

 

After some more research I'm wondering if the issue stems from not selecting the layout tab. I started to try and bring that into the mix but I haven't had success yet. See my updated code for the Sub below. I feel like I am missing a step though.

 

I get a response that it is not set to an instance of the object. (for all attributes)

 

Private Sub UpdateBlockAttribute(acBlkRef As BlockReference, attTag As String, textValue As String, Optional modelSpace As Boolean = True)
       Dim acBlkTable As BlockTable = Nothing
       Dim acBlkDef As BlockTableRecord
       Dim acCurLyr As ObjectId
       Dim acAttRef As DatabaseServices.AttributeReference = Nothing
       Dim attFound As Boolean = False
       Dim acSpaceID As ObjectId

       Try
           acBlkTable = acTrans.GetObject(acdb.BlockTableId, OpenMode.ForRead)

           If modelSpace = False Then
               acSpaceID = acBlkTable(BlockTableRecord.PaperSpace)
           Else
               acSpaceID = acBlkTable(BlockTableRecord.ModelSpace)
           End If

           acBlkDef = DirectCast(acTrans.GetObject(acSpaceID, OpenMode.ForRead), BlockTableRecord)


           'acBlkDef = DirectCast(acBlkTable(acBlkRef.Name).GetObject(OpenMode.ForRead), BlockTableRecord)

           Dim acLyrTbl As LayerTable = acTrans.GetObject(acdb.LayerTableId, OpenMode.ForRead)
           acCurLyr = acdb.Clayer
           If acLyrTbl.Has("0") Then
               acdb.Clayer = acLyrTbl("0")
           End If

           For Each acEntId In acBlkDef

               Dim acEnt As Entity = acTrans.GetObject(acEntId, OpenMode.ForRead)
               If Not IsNothing(acEnt) Then

                   If acEnt.GetType.ToString = "Autodesk.AutoCAD.DatabaseServices.AttributeDefinition" Then

                       Dim acAttDef As AttributeDefinition = DirectCast(acEnt, AttributeDefinition)

                       If Not IsNothing(acAttDef) And Not acAttDef.Constant Then

                           acAttRef = New AttributeReference
                           acAttRef.SetAttributeFromBlock(acAttDef, DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).BlockTransform)

                           If acAttDef.Tag.ToString = attTag Or acAttRef.Tag.ToString = attTag Then
                               attFound = True
                               Exit For
                           End If

                       End If

                   End If

               End If

           Next

           DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).AttributeCollection.AppendAttribute(acAttRef)

           'IF THE ATTRIBUTE DOES NOT EXIST, ADD A NEW ONE...
           If Not attFound Then
               acAttRef.Tag = attTag
               acAttRef.Justify = AttachmentPoint.MiddleCenter
               acTrans.AddNewlyCreatedDBObject(acAttRef, True)
               acAttRef.UpgradeOpen()
           End If

           acAttRef.TextString = textValue

           acAttRef.DowngradeOpen()

           acBlkDef.SynchronizeAttributes()
           acdb.Clayer = acCurLyr
       Catch ex As Exception
           MsgBox("Update Block Attribute: " & ex.Message & acAttRef.BlockName.ToString & " - " & acAttRef.Tag.ToString)

       End Try
   End Sub

Link to comment
Share on other sites

Thanks for posting the drawing so quickly, and for the additional information.

 

I'll see what I can find out as soon as I can - I am in the middle of completing someone else's project at the moment (why you'd wait to the end of a submittal, to do the vertical Profiles, sanitary runs, revise the storm [if at all], and design the vertical for water & force mains is beyond me, but that's what I've been called in to do, dah dah dah dahhhh. Grrr).

 

 

 

Also, what version(s) are you planning to support?

 

Cheers

Link to comment
Share on other sites

I feel like I'm close, but something is still missing.

I have made a modification to factor layout into it.

I have been able to confirm that it is now iterating through the correct block and does pull in that attribute, however, it still does not recognize the tag as equal to the attTag that is passed in. I'm attaching a quick screen shot of the issue I have with my output. If you look at the attribute names you can see that it creates a new attribute with an identical name.

 

 Private Sub UpdateBlockAttribute(acBlkRef As BlockReference, attTag As String, textValue As String, Optional modelSpace As Boolean = True)
       Dim acBlkTable As BlockTable = Nothing
       Dim acBlkDef As BlockTableRecord = Nothing
       Dim acCurLyr As ObjectId
       Dim acAttRef As DatabaseServices.AttributeReference = Nothing
       Dim attFound As Boolean = False
       Dim acSpaceID As ObjectId
       Dim layoutDict As DBDictionary
       Dim dictEntry As DictionaryEntry
       Dim layout As Layout
       Dim layoutID As ObjectId

       Try


           layoutDict = acTrans.GetObject(acdb.LayoutDictionaryId, OpenMode.ForRead, False)

           'If modelSpace = False Then
           'acSpaceID = acBlkTable(BlockTableRecord.PaperSpace)
           'Else
           'acSpaceID = acBlkTable(BlockTableRecord.ModelSpace)
           ' End If

           ' acBlkDef = DirectCast(acTrans.GetObject(acSpaceID, OpenMode.ForRead), BlockTableRecord)


           If (layoutDict <> Nothing) Then

               For Each dictEntry In layoutDict

                   layoutID = dictEntry.Value
                   layout = acTrans.GetObject(layoutID, OpenMode.ForRead)

                   acBlkTable = acTrans.GetObject(acdb.BlockTableId, OpenMode.ForRead)

                   acBlkDef = DirectCast(acBlkTable(acBlkRef.Name).GetObject(OpenMode.ForRead), BlockTableRecord)

                   Dim acLyrTbl As LayerTable = acTrans.GetObject(acdb.LayerTableId, OpenMode.ForRead)
                   acCurLyr = acdb.Clayer
                   If acLyrTbl.Has("0") Then
                       acdb.Clayer = acLyrTbl("0")
                   End If

                   For Each acEntId In acBlkDef

                       Dim acEnt As Entity = acTrans.GetObject(acEntId, OpenMode.ForRead)
                       If Not IsNothing(acEnt) Then

                           If acEnt.GetType.ToString = "Autodesk.AutoCAD.DatabaseServices.AttributeDefinition" Then

                               Dim acAttDef As AttributeDefinition = DirectCast(acEnt, AttributeDefinition)

                               If Not IsNothing(acAttDef) And Not acAttDef.Constant Then
                                    
                                   acAttRef = New AttributeReference
                                   acAttRef.SetAttributeFromBlock(acAttDef, DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).BlockTransform)

                                   If acAttDef.Tag.ToString = attTag Or acAttRef.Tag.ToString = attTag.ToString Then
                                       attFound = True
                                       Exit For
                                   End If

                           End If

                       End If

                       End If

                   Next

                   If attFound = True Then
                       Exit For
                   End If
               Next
           End If

           DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).AttributeCollection.AppendAttribute(acAttRef)

           'IF THE ATTRIBUTE DOES NOT EXIST, ADD A NEW ONE...
           If Not attFound Then
               acAttRef.Tag = attTag
               acAttRef.Justify = AttachmentPoint.MiddleCenter
               acTrans.AddNewlyCreatedDBObject(acAttRef, True)
               acAttRef.UpgradeOpen()
           End If

           acAttRef.TextString = textValue

           acAttRef.DowngradeOpen()

           'acBlkDef.SynchronizeAttributes()
           acdb.Clayer = acCurLyr
       Catch ex As Exception
           MsgBox("Update Block Attribute: " & ex.Message & acAttRef.BlockName.ToString & " - " & acAttRef.Tag.ToString)

       End Try
   End Sub

 

paperspace blocks.docx

Link to comment
Share on other sites

  • 7 years later...

Hi, i try to edit the attributes in a Block reference, but i think your program work goog, but never change my private attributes. You know why?

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...