View Full Version : Adding new attribute to each block in this drawing
Grenco
26th Oct 2009, 02:51 pm
Hi all,
How can I search thisdrawing for blocks wich don't have an attribute named "Handle_ID". If they don't, then add a tribute in the block.
I got this:
Sub test2()
Dim attributeObj As AcadAttribute
Dim BlockObj As AcadBlockReference
Dim BlockObj2 As AcadBlock
For Each Elem In ThisDrawing.ModelSpace
With Elem
If StrComp(.EntityName, "AcDbBlockReference", 1) = 0 Then
If ((Elem.HasAttributes) And (Left(Elem.EffectiveName, 3) = "G_B") Or (Left(Elem.EffectiveName, 3) = "G_E") Or _
(Left(Elem.EffectiveName, 3) = "G_I") Or (Left(Elem.EffectiveName, 3) = "G_L")) Then
Handle = Elem.Handle
Dim InsertionPnt(0 To 2) As Double
InsertionPnt(0) = 0#: InsertionPnt(1) = 0#: InsertionPnt(2) = 0#
Set BlockObj = Elem
Set BlockObj2 = BlockObj <-FIRST ERROR)
Set attributeObj = BlockObj2.AddAttribute(1, acAttributeModeInvisible, "HANDLE_ID", InsertionPnt, "HANDLE_ID", Handle) <-SECOND ERROR)
ThisDrawing.SendCommand "_ATTSYNC" & vbCr & "NAME" & vbCr & Elem.EffectiveName & vbCr
End If
End If
End With
Next Elem
End Sub
Can you guys help me? :)
fixo
26th Oct 2009, 03:10 pm
Because of the AcadBlockReference and AcadBlock are two different objects
You can get AcadBlock from Block collection like this:
Set BlockObj2 = ThisDrawing.Blocks(BlockObj.Name)
or
Set BlockObj2 = ThisDrawing.Blocks(BlockObj.EffectiveName)
for dynamic block
HTH
~'J'~
Grenco
26th Oct 2009, 04:07 pm
Because of the AcadBlockReference and AcadBlock are two different objects
You can get AcadBlock from Block collection like this:
Set BlockObj2 = ThisDrawing.Blocks(BlockObj.Name)
or
Set BlockObj2 = ThisDrawing.Blocks(BlockObj.EffectiveName)
for dynamic block
HTH
~'J'~
Thanks for your response. But can you put it in a working procedure wich also checks if the Handle_ID is present? And if not, it's added to the block? :oops:
fixo
26th Oct 2009, 06:27 pm
Thanks for your response. But can you put it in a working procedure wich also checks if the Handle_ID is present? And if not, it's added to the block? :oops:
You need to check on existing attribute name (TagString)
instead of check on Handle
Just iterate trough attributes - see Gettributes in the help file
There are a lot of code examples on this forum too :)
From other hande you can use Selection with filter instead
of looping trough all drawing objects
Sorry I haven't enough time to write complete solution for you now
~'J'~
fixo
26th Oct 2009, 09:23 pm
Thanks for your response. But can you put it in a working procedure wich also checks if the Handle_ID is present? And if not, it's added to the block? :oops:
Ok, I have a few minutes so I've tryed to write it quick and dirty
Just I can't test it without dynamic blocks though
Hope this will get you some idea
Option Explicit
Sub test2()
Dim attributeObj As AcadAttribute
Dim BlockObj As AcadBlockReference
Dim BlockObj2 As AcadBlock
Dim elem As AcadEntity
Dim Handle As String
Dim blockName As String
Dim collNames As New Collection
Dim i As Integer
Dim j As Integer
'collect just unique block names into collection
For Each elem In ThisDrawing.ModelSpace
If (TypeOf elem Is AcadBlockReference) Then
Set BlockObj = elem
With BlockObj
If ((.HasAttributes) And (Left(.EffectiveName, 3) = "G_B") Or (Left(.EffectiveName, 3) = "G_E") Or _
(Left(.EffectiveName, 3) = "G_I") Or (Left(.EffectiveName, 3) = "G_L")) Then
On Error Resume Next ' to bypass error on duplicate name
collNames.Add .EffectiveName, .EffectiveName
End If
End With
End If
Next elem
Dim InsertionPnt(0 To 2) As Double
InsertionPnt(0) = 0#: InsertionPnt(1) = 0#: InsertionPnt(2) = 0#
' iterate trough collection
For i = 1 To collNames.Count
blockName = collNames.Item(i)
Set BlockObj2 = ThisDrawing.Blocks(blockName)
Set attributeObj = BlockObj2.AddAttribute(1, acAttributeModeInvisible, "New prompt", InsertionPnt, "NEW_TAG", "0")
With ThisDrawing
.SetVariable "CMDECHO", 0
.SendCommand "_ATTSYNC _N " & blockName & vbCr
.SetVariable "CMDECHO", 1
.Regen acAllViewports
End With
Next i
ThisDrawing.Regen acAllViewports
Dim ftype(1) As Integer
ftype(0) = 0: ftype(1) = 2
Dim fdata(1) As Variant
fdata(0) = "INSERT"
' iterate trough collection again
For i = 1 To collNames.Count
blockName = collNames.Item(i)
fdata(1) = "`*," & blockName
Dim oSset As AcadSelectionSet
With ThisDrawing.SelectionSets
While .Count > 0
.Item(0).Delete
Wend
Set oSset = .Add("$Blocks$")
End With
oSset.Select acSelectionSetAll, , , ftype, fdata
For Each elem In oSset
Set BlockObj = elem
Handle = elem.Handle
Dim atts() As AcadAttributeReference
Dim att As AcadAttributeReference
With BlockObj
atts = .GetAttributes()
For j = 0 To UBound(atts)
Set att = atts(j)
If att.TagString = "NEW_TAG" Then
att.TextString = CStr(Handle)
'//Exit For
End If
Next j
Exit For
End With
Next elem
'//oSset.Delete
Next i
MsgBox "Get to work!"
End Sub
~'J'~
Grenco
27th Oct 2009, 08:41 am
Thnx! I also tried something and it works also... I guess i'm not so bad at it at all :wink:
Sub test2()
Dim attributeObj As AcadAttribute
Dim BlockObj As AcadBlock
Dim InsertionPnt(0 To 2) As Double
InsertionPnt(0) = 0#: InsertionPnt(1) = 0#: InsertionPnt(2) = 0#
For Each Elem In ThisDrawing.ModelSpace
With Elem
If StrComp(.EntityName, "AcDbBlockReference", 1) = 0 Then
If ((Elem.HasAttributes) And (Left(Elem.EffectiveName, 3) = "G_B") Or (Left(Elem.EffectiveName, 3) = "G_E") Or _
(Left(Elem.EffectiveName, 3) = "G_I") Or (Left(Elem.EffectiveName, 3) = "G_L")) Then
Handle = Elem.Handle
Found = False
REDO_ACTION:
Attributen = Elem.GetAttributes
For Count = LBound(Attributen) To UBound(Attributen) 'Read attributes from block
If Attributen(Count).TagString = "HANDLE_ID" Then
If Attributen(Count).TextString = "" Then
Attributen(Count).TextString = Handle
End If
Found = True
Exit For
End If
Next Count
If Found = False Then
Set BlockObj = ThisDrawing.Blocks(Elem.EffectiveName)
Set attributeObj = BlockObj.AddAttribute(1, acAttributeModeInvisible, "HANDLE_ID", InsertionPnt, "HANDLE_ID", "")
attributeObj.Layer = "Attrib-Hidden"
ThisDrawing.SendCommand "_ATTSYNC" & vbCr & "NAME" & vbCr & Elem.EffectiveName & vbCr
ThisDrawing.Regen (acActiveViewport) 'NODIG??
GoTo REDO_ACTION
End If
End If
End If
End With
Next Elem
End Sub
Except it look a lot simple then yours :P
SEANT
27th Oct 2009, 09:56 am
Grenco,
This thread appears to relate directly to the thread “Whats Up with the Handle?”
The issues discussed in these threads, as well as the one RK McSwain posted, will be important to anyone attempting to coordinate an AutoCAD drawing to an outside database.
I will say the process posted above is a clever way to resolve a non persistent handle issue, but it is discouraging to accept that such an issue actually exists. The customization docs have always stated that Handles are unique, and remain constant, within a document.
I don’t doubt your statement about a coordination break between drawing and database; what would provide some comfort, however, is if there was some common element with the drawings in which this break occurred.
Is there anything different between where this did and did not occur?
SEANT
27th Oct 2009, 10:18 am
That http://discussion1.autodesk.com/forums/thread.jspa?threadID=729961 link, despite the rather antagonistic undertone (or should I say overtone) is pretty informative, and lists a couple of possible causes for Handle change.
WBLOCKing is certainly a likely candidate, and could be addressed without too much difficulty.
Also:
RECOVERing may be another possible cause, though I’d be a bit annoyed if that did actually change the Handles.
If the re-Handle-ing isn’t document wide, i.e., only a subset of the drawing is changing, then Cut and Paste, or even Lisp/VBA/etc., procedures may need examination.
Grenco
27th Oct 2009, 11:33 am
The only thing I know is that all handles in a drawing are changed but I can't reproduce it. It doesn't happend often. Only with some of my colleagues. Probably when they are doing something unusual.
I'm busy reconstructing the VBA-routine because it's slow with dynamic blocks and some features aren't working properly. We also thought it was the cause of empty databases. Except, it happend to me too!
If you look at the attached image you can see how my database is filled. I ONLY ADD a record to it when there is a new item (new handle) in my drawing.
The records with Note_2 = !!DELETED!! are the items with a handle (unique Object_ID in Database) wich isn't found in the drawing. So if I delete an item, the database sets the Note_2 to !!DELETED!!. You can see that for the first record (Object_ID=1A83B) the Type and Group are "P" and "355". This is the original item with his original Handle.
Some how the handle is changed to 1C431. I haven't copied, cut, paste, wblock or what so ever. It's a unchanged block in the same drawing. When my database is updated, the changed handle is for my database seen as new, so it adds it to itself. You can find "P" and "355" back in this record because these are added according the attributes of that particular block. This item is only once in my drawing offcourse.
As you can see, this happend for every item and its added again to the database. The other information (descrip, supplier type_dim etc) is added in the database so this data isn't added to the new record.
Before I was rebuilding the routine we didn't know the cause of the problem because the records where instantly removed from the database. Now I know the problem (changed handle), so I want to make a back up of each item its handle by adding it to his own attributes and in the database. Now I can check if there is a changed handle. If there is, the original record is replaced by the new handle.
If I build it correct, no more empty databases, but there is one thing left... Why/when were my handles changed?? :?
SEANT
27th Oct 2009, 12:21 pm
You have put me on alert. I’ve designed a game plan based on an immutable HANDLE but will now watch it closely.
Quite frankly, I’m hoping to keep it as such based on a few of the issues raised by Tony Tanzillo in the Autodesk.Discussion link. Most predominantly, the ability to copy objects without duplicating IDs. An important issue if additional work is performed subsequent to initial database construction.
I did think of one thing you could check with the Handle-Attribute methodology. Does the mere act of adding an additional attribute to a Block/BlockReference change an entity’s handle? That may be likely with the Block; probably not so much with the references.
Grenco
27th Oct 2009, 01:46 pm
You have put me on alert. I’ve designed a game plan based on an immutable HANDLE but will now watch it closely.
Quite frankly, I’m hoping to keep it as such based on a few of the issues raised by Tony Tanzillo in the Autodesk.Discussion link. Most predominantly, the ability to copy objects without duplicating IDs. An important issue if additional work is performed subsequent to initial database construction.
I did think of one thing you could check with the Handle-Attribute methodology. Does the mere act of adding an additional attribute to a Block/BlockReference change an entity’s handle? That may be likely with the Block; probably not so much with the references.
If I correctly understand what you're saying. :oops:
The AddAttribute action is added after I discoverd that my handle was changed. Even tough, when I use addattribute, the handle of the block stays the same.
Just to be sure: i'm not interested in the handle of the attribute. I'm interested in the block his handle wich contains several attributes. :)
SEANT
27th Oct 2009, 02:41 pm
Actually, that part of the post wasn’t so much a possible cause of the Handle change as something to investigate as you go forward.
I’m not exactly sure what constitutes a “new” object in AutoCAD. For instance, a circle could be created and acquire a handle. It can be moved, perhaps even scaled, yet the handle would remain constant. If a section of the circle were trimmed, however, that circle may constitute a new entity (ARC), thus acquiring a new Handle.
A Block object may consider itself “changed” as soon as an element is added or subtracted, thus acquiring a new Handle.
It sounds like you are only interested in Block References, though, so what happens at the Block level may not matter.
I guess the bottom line is if I plan to employ a Handle based coordination system I should have a comprehensive understanding of what AutoCAD does with the handles behind the scenes.
It may be beneficial to set up some persistent, Event Monitor that I can use for a trial period - to see how and when handles are modified. I suspect it will be a bit of a pain to work with, but could be quite informative.
SEANT
27th Oct 2009, 03:16 pm
Well, after setting up a down and dirty routine, I can say that a circle trimmed to an arc does not cause an immediate Handle change. Apparently handles are an "Object" based property and, regardless of what else changed, an arc is still an object. :)
Grenco
27th Oct 2009, 03:18 pm
So your handle stays exactly the same?
SEANT
27th Oct 2009, 03:19 pm
Yes, at least for the short term.
Grenco
27th Oct 2009, 04:58 pm
What do you think of my solution?
Adding Block his handle to a seperate attribute in the same block, so I can compare the Block.Handle with the Attribute wich has the original Handle value. If these values aren't equal, I change the record in my database and change it in the new handle. I also change the original Handle value in the attribute to the new handle. This way I can keep the unique handle in my database up to date with the handle in my drawing.
SEANT
27th Oct 2009, 10:33 pm
What do you think of my solution?
Adding Block his handle to a seperate attribute in the same block, so I can compare the Block.Handle with the Attribute wich has the original Handle value. If these values aren't equal, I change the record in my database and change it in the new handle. I also change the original Handle value in the attribute to the new handle. This way I can keep the unique handle in my database up to date with the handle in my drawing.
That process seems sensible enough, though I suppose it would depend on exactly how and why handles change.
If in the course of a day’s work tagged elements are copied, along with the drawing suffering a handle “update”, then none of the elements would have matching handle/attribute. There may be problems determining which element was the original and maintaining a coordinated outside database.
If the handle change could be determined to only happen at drawing-open, then coordinating the outside database should probably be relegated to that time.
Grenco
28th Oct 2009, 09:26 am
My plan was when there are object added to a drawing (acaddocument_objectadded(ByVal object As Object)) to fill in the attribute with the new object's handle value. This way when I copy/paste (or other commands), the attribute with handle gets refreshed by his own value and not the older (when pasting) value.
Powered by vBulletin™ Version 4.1.2 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.