Grenco Posted October 26, 2009 Posted October 26, 2009 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 [color=red]<-FIRST ERROR)[/color] Set attributeObj = BlockObj2.AddAttribute(1, acAttributeModeInvisible, "HANDLE_ID", InsertionPnt, "HANDLE_ID", Handle) [color=red]<-SECOND ERROR)[/color] ThisDrawing.SendCommand "_ATTSYNC" & vbCr & "NAME" & vbCr & Elem.EffectiveName & vbCr End If End If End With Next Elem End Sub Can you guys help me? Quote
fixo Posted October 26, 2009 Posted October 26, 2009 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'~ Quote
Grenco Posted October 26, 2009 Author Posted October 26, 2009 Because of the AcadBlockReference and AcadBlock are two different objectsYou 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? Quote
fixo Posted October 26, 2009 Posted October 26, 2009 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? 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'~ Quote
fixo Posted October 26, 2009 Posted October 26, 2009 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? 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'~ Quote
Grenco Posted October 27, 2009 Author Posted October 27, 2009 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 Quote
SEANT Posted October 27, 2009 Posted October 27, 2009 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? Quote
SEANT Posted October 27, 2009 Posted October 27, 2009 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. Quote
Grenco Posted October 27, 2009 Author Posted October 27, 2009 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?? Quote
SEANT Posted October 27, 2009 Posted October 27, 2009 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. Quote
Grenco Posted October 27, 2009 Author Posted October 27, 2009 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. 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. Quote
SEANT Posted October 27, 2009 Posted October 27, 2009 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. Quote
SEANT Posted October 27, 2009 Posted October 27, 2009 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. Quote
Grenco Posted October 27, 2009 Author Posted October 27, 2009 So your handle stays exactly the same? Quote
Grenco Posted October 27, 2009 Author Posted October 27, 2009 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. Quote
SEANT Posted October 27, 2009 Posted October 27, 2009 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. Quote
Grenco Posted October 28, 2009 Author Posted October 28, 2009 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. Quote
Recommended Posts
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.