Author Topic: Writing Block Attributes to Active Model Space  (Read 3283 times)

0 Members and 1 Guest are viewing this topic.

FRaccie

  • Guest
Writing Block Attributes to Active Model Space
« on: January 25, 2012, 09:41:53 PM »
Hi,

I'm trying to figure out how to update attributes from a modeless windows loaded from a vb.net plugin (written in .NET)
(Code below also runs from the AutoCAD Command Line using "ALLATTRIBSTOTEST")

After a lot of trying and pulling my hair, I can't seem to find the answer.
I googled my *** off and found some answers but nothing seems to work for me.
So let's hope someone can help out.

The Sub Routine below iterates through all the blocks in the active document model space and does some checks.
(Using the TEST DWG - Resulting in 8 blocks of which we read out all the attributes block per block to a message box)

Getting all the attributes is no problem but how do I write to the TEXTSTRING
And update the active model space with the new values.

Just for testing I want to write TEST to all of the attribute values regardless of TAG
And update the Model Space so I can view the changes in the property window after the routine has finished.


I've added a DWG (AutoCAD 2010) so people who are willing to help can test. (I use AutoCAD 2012 but I don't know if it matters for the API)

Greets FRaccie

Code - vb.net: [Select]
  1.  <CommandMethod("ALLATTRIBSTOTEST")> _
  2.         Public Sub SetAllBlockAttributesToTest()
  3.             '' Initiate empty string for logging purposes
  4.             Dim log As String = ""
  5.             '' Get the current document and database
  6.             Dim acDoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
  7.             Dim acCurDb As Database = acDoc.Database
  8.  
  9.             ''Lock The Document because we are working from a modeless window
  10.             Using acLckDoc As DocumentLock = acDoc.LockDocument()
  11.                 '' Start a transaction
  12.                 Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
  13.                     '' Open the Block table for read
  14.                     Dim acBlkTbl As BlockTable = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead)
  15.                     '' Open the Block table record Model space for read
  16.                     Dim acBlkTblRec As BlockTableRecord = acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), OpenMode.ForRead)
  17.                     '' Step through the Block table record
  18.                     For Each acObjId As ObjectId In acBlkTblRec
  19.                         ''Check if the block is of the INSERT type - ignore LINE, CIRCLE, POLYGON ...
  20.                         If acObjId.ObjectClass().DxfName = "INSERT" Then
  21.                             'If TRUE create Log Entry with DXF name, ObjectID and Handle
  22.                             log = log + vbLf & "DXF name: " & acObjId.ObjectClass().DxfName
  23.                             log = log + vbLf & "ObjectID: " & acObjId.ToString()
  24.                             log = log + vbLf & "Handle: " & acObjId.Handle.ToString()
  25.                             log = log + vbLf
  26.  
  27.                             ''Open Block Reference of Current Block for Read
  28.                             Dim BlocRef As BlockReference = acObjId.GetObject(OpenMode.ForRead)
  29.                             ''Check if the NAME of the Block currently Referenced start with Callens
  30.                             ''(Others are not necessary for the Equipment List)
  31.                             If BlocRef.Name.StartsWith("Callens") Then
  32.  
  33.                                 'Get the Attribute Collection of the Block that is currently in use by our Block Reference
  34.                                 Dim BlocRefAttrCollection As AttributeCollection = BlocRef.AttributeCollection
  35.                                 'If there are no attributes, do nothing
  36.                                 'MsgBox(BlocRefAttrCollection.Count)
  37.                                 If BlocRefAttrCollection.Count > 0 Then
  38.  
  39.                                     For Each BlocRefAttrID As ObjectId In BlocRefAttrCollection
  40.                                         '' Go through all AttributesReferences in the AttributesCollection
  41.                                         Dim BlocRefAttr As New AttributeReference
  42.                                         BlocRefAttr = acTrans.GetObject(BlocRefAttrID, OpenMode.ForRead)
  43.                                         log = log + vbLf & "Tag:        " & BlocRefAttr.Tag.ToString()
  44.                                         log = log + vbLf & "Textstring: " & BlocRefAttr.TextString()
  45.                                         log = log + vbLf
  46.  
  47.                                         ''OPEN THE ATTRIBUTEREFERENCE FOR WRITE AND SET "TEST" TO ATTRIBUTE TEXTSTRING
  48.                                         ''
  49.                                         'BlocRefAttr = acTrans.GetObject(BlocRefAttrID, OpenMode.ForWrite)
  50.                                         'BlocRefAttr.TextString = "TEST"
  51.                                         ''
  52.                                         ''
  53.                                         ''
  54.                                     Next
  55.  
  56.                                     MsgBox(log) ''Show log in Message Box
  57.                                     log = "" ''Clear log for next block
  58.  
  59.                                 End If '' End BlocRefAttrCollection.Count
  60.                             End If '' End BlocRef.Name StartsWith Callens
  61.                         End If '' End DXFName is INSERT
  62.                         'acTrans.Commit()
  63.                     Next
  64.                     '' Dispose of the transaction
  65.                 End Using
  66.                 ''Unlock Document
  67.             End Using
  68.             ''Update Current Active Document with Changes
  69.             'Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument = acDoc
  70.         End Sub
  71.  

edit:kdub - code formatted
« Last Edit: January 25, 2012, 10:26:43 PM by Kerry »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Writing Block Attributes to Active Model Space
« Reply #1 on: January 26, 2012, 12:48:55 AM »
Welcome to theSwamp.

You nearly had it.
There are a couple of things :

The AttributeReference should be opened ForWrite
Set the TextString property

Commit the transaction when done

I'd also revise the code that sets the log value  ... just to save memory
better yet, use a stringbuilder
This could still use some refinement, but have a play
Code - C#: [Select]
  1. using System.Windows.Forms;
  2. using AllBlockAttributesToTest;
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.DatabaseServices;
  5. using Autodesk.AutoCAD.Runtime;
  6. using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
  7.  
  8. [assembly: CommandClass(typeof (MyCommands))]
  9.  
  10. namespace AllBlockAttributesToTest
  11. {
  12.     public class MyCommands
  13.     {
  14.         [CommandMethod("TEST01")]
  15.         public void SetAllBlockAttributesToTest()
  16.         {
  17.             //' Initiate empty string for logging purposes
  18.             string log = string.Empty;
  19.  
  20.             Document doc = AcadApp.DocumentManager.MdiActiveDocument;
  21.             Database db = doc.Database;
  22.  
  23.             //'Lock The Document because we are working from a modeless window
  24.             using (DocumentLock acLckDoc = doc.LockDocument())
  25.             {
  26.                 using (Transaction tr = db.TransactionManager.StartTransaction())
  27.                 {
  28.                     //' Open the Block table for read
  29.                     var bt = (BlockTable) tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  30.  
  31.                     //' Open the Block table record Model space for read
  32.                     var modelSpaceRecord =
  33.                         (BlockTableRecord) tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
  34.                     //' Step through the Block table record
  35.                     foreach (ObjectId acObjId in modelSpaceRecord)
  36.                     {
  37.                         //'Check if the block is of the INSERT type - ignore LINE, CIRCLE, POLYGON ...
  38.                         if (acObjId.ObjectClass.DxfName == "INSERT")
  39.                         {
  40.                             //If TRUE create Log Entry with DXF name, ObjectID and Handle
  41.                             log = "\nDXF name: " + acObjId.ObjectClass.DxfName
  42.                                   + "\nObjectID: " + acObjId.ToString()
  43.                                   + "\nHandle: " + acObjId.Handle.ToString()
  44.                                   + "\n";
  45.  
  46.                             //'Open Block Reference of Current Block for Read
  47.                             var BlocRef = (BlockReference) acObjId.GetObject(OpenMode.ForRead);
  48.  
  49.                             //'Check if the NAME of the Block currently Referenced start with Callens
  50.                             //'(Others are not necessary for the Equipment List)
  51.  
  52.                             if (BlocRef.Name.StartsWith("Callens"))
  53.                             {
  54.                                 //Get the Attribute Collection of the Block
  55.                                 // that is currently in use by our Block Reference
  56.                                 AttributeCollection BlocRefAttrCollection = BlocRef.AttributeCollection;
  57.  
  58.                                 //If there are no attributes, do nothing
  59.                                 if (BlocRefAttrCollection.Count > 0)
  60.                                 {
  61.                                     foreach (ObjectId BlocRefAttrID in BlocRefAttrCollection)
  62.                                     {
  63.                                         //' Go through all AttributesReferences in the AttributesCollection
  64.  
  65.                                         var BlocRefAttr = (AttributeReference)
  66.                                                           tr.GetObject(BlocRefAttrID, OpenMode.ForWrite);
  67.                                         log = log + "\nTag:        "
  68.                                               + BlocRefAttr.Tag
  69.                                               + "\nTextstring: "
  70.                                               + BlocRefAttr.TextString
  71.                                               + "\n";
  72.  
  73.                                         //'OPEN THE ATTRIBUTEREFERENCE FOR WRITE
  74.                                         // AND SET "TEST" TO ATTRIBUTE TEXTSTRING
  75.                                         BlocRefAttr.TextString = "TEST";
  76.                                     }
  77.                                     MessageBox.Show(log);
  78.                                     //'Show log in Message Box
  79.                                     log = string.Empty;
  80.                                 }
  81.                             }
  82.                         }
  83.                     }
  84.                     tr.Commit();
  85.                 }
  86.             }
  87.         }
  88.     }
  89. }
« Last Edit: January 26, 2012, 12:53:46 AM by Kerry »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

FRaccie

  • Guest
Re: Writing Block Attributes to Active Model Space
« Reply #2 on: January 26, 2012, 10:59:54 AM »
Tnx man.
Did the job perfectly.

Indeed I was almost there.
Goodbye NullPointerException :p

Tnx A LOT.