.NET
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic to the Top
- Bookmark
- Subscribe
- Printer Friendly Page
All blocks by name
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
Hi All,
I know I am missing something very simple here (and i am sure I have done this before, but cannot find the code), but I basically need to get all blocks (dynamic in this case) with a particular name.
I can do it easily by searching through all blocks in the drawing, but it's a bit slow:
Dim acDoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument 'Declare document lock Dim acDocLock As DocumentLock = acDoc.LockDocument Dim acCurDb As Database = acDoc.Database 'Start a transaction to open the recently copied title-block file and edit the attributes Using acTrans As Transaction = acDoc.TransactionManager.StartTransaction Try 'Get the blocktable from the current open drawing Dim acBT As BlockTable = acCurDb.BlockTableId.GetObject(OpenMode.ForRead) 'Iterrate through block table to determine if they are layouts or not For Each btrObjId As ObjectId In acBT Dim btr As BlockTableRecord = btrObjId.GetObject(OpenMode.ForRead) If btr.IsLayout Then Continue For End If Dim objIdColl As ObjectIdCollection = btr.GetBlockReferenceIds(True, True) For Each objId In objIdColl Dim acBref As BlockReference = objId.GetObject(OpenMode.ForWrite) Dim myAttValsTB As New Dictionary(Of String, String) If acBref.Name = "ECDT_IssueStatus" Then 'Do stuff to attributes here... End If If acBref.IsDynamicBlock = True Then Dim acBlkDef As BlockTableRecord = acBref.DynamicBlockTableRecord.GetObject(OpenMode. ForRead) Dim acDynObjId As ObjectId = acBref.DynamicBlockTableRecord Dim dynBtr As BlockTableRecord = CType(acTrans.GetObject(acDynObjId, OpenMode.ForRead, False), BlockTableRecord) If dynBtr.Name = "ECDT_IssueStatus" Then 'Do stuff to dynamic properties here... Dim strDynParameterName As String = "Visibility1" Dim strDynValue As String = strSubState Dim acDynBref As BlockReference = objId.GetObject(OpenMode.ForRead) For Each myDynamProp As DynamicBlockReferenceProperty In _ acDynBref.DynamicBlockReferencePropertyCollection( ) If myDynamProp.PropertyName.Equals( _ strDynParameterName, StringComparison.OrdinalIgnoreCase) = True Then myDynamProp.Value = strDynValue End If Next End If End If Next Next Finally End Try actrans.commit() acDocLock.Dispose() End Using
Again, the above works with no problems other than being slow.
So I figured since I already know the block name, I can just use it to get all of the blocks in the drawing. But for some reason, with the code below, the collection (btrids) is never populated. What am I doing wrong?
Dim Blockname As String = "ECDT_IssueStatus" Dim acDoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument 'Declare document lock Dim acDocLock As DocumentLock = acDoc.LockDocument Dim acCurDb As Database = acDoc.Database Using acTrans As Transaction = acDoc.TransactionManager.StartTransaction Try Dim BT As BlockTable = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) If BT.Has(Blockname) Then Dim btr As BlockTableRecord = acTrans.GetObject(bt(Blockname), OpenMode.ForRead) Dim btrIDs As ObjectIdCollection = btr.GetBlockReferenceIds(True, False) For Each id As ObjectId In btrIDs If Not id.IsEffectivelyErased Then Dim acBref As BlockReference = id.GetObject(OpenMode.ForWrite) 'Do stuff to block attributes here... If acBref.IsDynamicBlock = True Then Dim acBlkDef As BlockTableRecord = acBref.DynamicBlockTableRecord.GetObject(OpenMode. ForRead) Dim acDynObjId As ObjectId = acBref.DynamicBlockTableRecord Dim dynBtr As BlockTableRecord = CType(acTrans.GetObject(acDynObjId, OpenMode.ForRead, False), BlockTableRecord) If dynBtr.Name = "ECDT_IssueStatus" Then 'Do stuff to dynamic properties here... End If End If End If Next End If acTrans.Commit() acDocLock.Dispose() Finally End Try End Using
Solved! Go to Solution.
Re: All blocks by name
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
OK... tested this with a normal block, so it has something to do with the fact that it is a dynamic block. So how can I get all of the dynamic block references in the drawing using the blockname?
Re: All blocks by name
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
When you insert a dynamic block and change a dynamic propertty then a anonymous block is created.
BlockTableRecord.GetBlockReferenceIds should only contain the blockreferences that have not had any changes to dynamic properties(default state)
You can use BlockTableRecord.GetAnonymousBlockIds to get anonymous block ids.
Also you can use BlockTableRecord.IsDynamicBlock Property to check at the definition level.
Here is a little code to help explain
<CommandMethod("ChangeVisState")> _
Public Sub ChangeVisState()
Dim Blockname As String = "C"
Dim doc As Document = Application.DocumentManager.MdiActiveDocument
Dim db As Database = doc.Database
Dim ed As Editor = doc.Editor
Using trx As Transaction = db.TransactionManager.StartTransaction
Dim bt As BlockTable = trx.GetObject(db.BlockTableId, OpenMode.ForRead)
If bt.Has(Blockname) Then
Dim btr As BlockTableRecord = trx.GetObject(bt(Blockname), OpenMode.ForRead)
Dim btrIDs As ObjectIdCollection = btr.GetBlockReferenceIds(True, False)
If btr.IsDynamicBlock Then
For Each id As ObjectId In btr.GetAnonymousBlockIds
Dim anonBlock As BlockTableRecord = trx.GetObject(id, OpenMode.ForRead)
For Each anonId As ObjectId In anonBlock.GetBlockReferenceIds(True, False)
btrIDs.Add(anonId)
Next
Next
End If
For Each id As ObjectId In btrIDs
If Not id.IsEffectivelyErased Then
Dim bref As BlockReference = id.GetObject(OpenMode.ForWrite)
For Each dynProp As DynamicBlockReferenceProperty In bref.DynamicBlockReferencePropertyCollection
If dynProp.PropertyName = "Visibility1" Then
dynProp.Value = "VisibilityState3"
End If
Next
End If
Next
End If
trx.Commit()
End Using
End Sub
Re: All blocks by name
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
This is C# but might help.
http://www.theswamp.org/index.php?topic=31859.msg4
Re: All blocks by name
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
Excellent! Works great and good reading!!!
I have been able to work with dynamic blocks in the past with no isses, but only after processing them with a user pick. Never tried to do it by itterating the block table so I was not sure how to do it (with a name).
Taking this a step further... how can I filter this down to only pulling the dynamic blocks (by a certain name) from the current layout?
I use the following for a standard block reference and then filter for the name later, but not sure how in this case:
acBtr = acCurDb.CurrentSpaceId.GetObject(OpenMode.ForRead)
How do I filter that with a dynamic block name?
Re: All blocks by name
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
You could itterate the space and make sure it's BlockReference.DynamicBlockTableRecord property match or checking a blockreference's BlockId to see if it matches Database.CurrentSpaceId
Re: All blocks by name
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
Got it! Thanks for the tip!
Re: All blocks by name
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
Now that I have all of the blocks in the drawing by particular name, I need to keep only those that are currently inserted in ModelSpace.
Can someone kindly give me some advice on doing this? I am struggling with it a bit!
TIA
Re: All blocks by name
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
A little more information... I thought this was working correctly for the last couple of months until I discovered this issue!!! ![]()
The problem I am running into is that the code reads the entire database. It even searches within other blocks! So for example, if I code to get all blocks with the name of "ABLOCK" it searches the entire database and adds every instance of that block to my collection. The real problem is that it will search for instances of "ABLOCK" nested in a block that has a block table record, but is not inserted in the drawing.
So in other words, if I create a new block called "BBLOCK" that contains a nested "ABLOCK", then I delete the "BBLOCK" but do not purge the drawing, the code will still count the "ABLOCK". I have coded for .IsErased and IsEffectivelyErased, but I think this is something different.
So... how can I get all blocks named "ABLOCK" by name that are BlockReferences (Inserts) in ModelSpace only? And, not as important, but how do I stop it from searching for nested blocks?
The code I am using is below:
Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction
Try
Dim acBt As BlockTable = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead)
If acBt.Has(blkName) Then
Dim acBtr As BlockTableRecord = acTrans.GetObject(acBt(blkName), OpenMode.ForRead)
Dim objIdColl As ObjectIdCollection = acBtr.GetBlockReferenceIds(True, False)
If acBtr.IsDynamicBlock Then
For Each id As ObjectId In acBtr.GetAnonymousBlockIds
If Not id.IsEffectivelyErased Then
If Not id.IsErased Then
Dim anonBlock As BlockTableRecord = acTrans.GetObject(id, OpenMode.ForRead)
For Each anonId As ObjectId In anonBlock.GetBlockReferenceIds(True, False)
objIdColl.Add(anonId)
Next
End If
End If
Next
End If
For Each objId As ObjectId In objIdColl
Dim acEnt As Entity = objId.GetObject(OpenMode.ForRead) 'added
If Not objId.IsEffectivelyErased Then
If Not objId.IsErased Then
Dim acBref As BlockReference = objId.GetObject(OpenMode.ForRead)
'<Snip>
Maybe I should start a new thread on this "sub" topic as this thread is a couple of months old?
Re: All blocks by name
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
Have not tested, but
For both cases of counting inserts with the block nested or not.
To not count the instance's inserted in other definitions you could check if the blockreference's OwnerId or BlockId is equal to ModelSpace's ObjectId
So to get the refereneces in model space that are nested set the first argument of GetBlockReferenceIds to false or true if not wanting the nested references, but for both cases excluded the blockreference's where OwnerId or BlockId do not match a modelspace or any of the spaces Objectid


