Insert a block and set attributes using VBA

Insert a block and set attributes using VBA

Anonymous
Not applicable
10,988 Views
7 Replies
Message 1 of 8

Insert a block and set attributes using VBA

Anonymous
Not applicable

I am inserting a user selected block into a drawing, and exploding it to expose the nested blocks for editing. But I would like to set some of the attributes so the user does not have to edit them manually. I am using AutoCAD Electrical 2017 and inserting a block that contains 4 AutoCAD Electrical Blocks and I would like to change "Tag1" and 3 of them and "Tag2" on one. This is what I have so far to insert the user selected block:

 

'Insert 1st object @ 5870,230
Object1 = "1-" + Object1       'This is adding some text to the existing block selected as it get put into the first column

insertionPnt(0) = 5870: insertionPnt(1) = 230: insertionPnt(2) = 0
Set blockRefObj = ThisDrawing.ModelSpace.InsertBlock(insertionPnt, Object1, 1#, 1#, 1#, 0)
blockRefObj.Explode
blockRefObj.Delete    'I had to add this as I found this is leaving the first block "unexploded"

 

Everything is working as it should currently. I need to edit the attributes of (AutoCAD Electrical Made Blocks) "VMS1_002" Tag1, "VMS21P" Tag2, "VW01_5" Tag1, and "VMO14" Tag1. What this block contains is a three phase connection of a circuit containing a MMP, Contactor, Cable tag, and the motor. These tags change depending on what page (page 15) and what column. 15.1 means "VMS1_002" Tag1 will end up being MMP151, "VMS21P" Tag2 will be CON151, "VW01_5" Tag1 will be C151, and "VMO14 Tag1 will be M151. I put 5 of these circuit per page (So you will have 151, 153, 155, 156 & 158 on page 15) I am using IEC symbols and standards. While we do not use the database for BOMs like most do, you can presume this is not AutoCAD Electrical, just AutoCAD. While I could just insert plain text where I need it, I would rather edit the attributes.

 

Thanks so much in advance!

0 Likes
10,989 Views
7 Replies
Replies (7)
Message 2 of 8

norman.yuan
Mentor
Mentor

If I understand your case correctly, you have a block that contains nested blocks in it; the nested block has attributes that you want to update their values. 

 

According to your description, you are on the right track: insert the block; explode it; then update the target blocks' attributes.

 

Exploding block reference with code is slightly different from the command: after exploding, the original block remains unchanged, and you get an array of entities as the block's "components". It is up to you to decide what to do with the array of entities and the original block reference.

 

In your case, I assume you want to erase the original block, and go through each blocks obtained from exploding to update attributes in it.

 

Following code shows the process (you only need to do minor change to update your target attribute):

Option Explicit

Public Sub UpdateAttInNestedBlock()
    
    Dim blk As AcadBlockReference
    Set blk = SelectBlockToExplode()
    If blk Is Nothing Then Exit Sub
    
    Dim ents As Variant
    ents = blk.Explode()
    blk.Delete
    
    Dim i As Integer
    For i = 0 To UBound(ents)
        If TypeOf ents(i) Is AcadBlockReference Then
            Set blk = ents(i)
            UpdateAttributesInBlock blk
        End If
    Next
    
End Sub

Private Function SelectBlockToExplode() As AcadBlockReference

    Dim blk As AcadBlockReference
    Dim ent As AcadEntity
    Dim pt As Variant
    ThisDrawing.Utility.GetEntity ent, pt, "Select a block:"
    If Not ent Is Nothing Then
        If TypeOf ent Is AcadBlockReference Then
            Set blk = ent
            '' You may want to test block name to make sure
            '' the block is the one to be exploded here
            '' If not you would want user to re-select
        End If
    End If
    Set SelectNestedBlock = blk
    
End Function

Private Sub UpdateAttributesInBlock(blk As AcadBlockReference)

    If Not blk.HasAttributes Then
        MsgBox "Block """ & blk.EffectiveName & """ does not have attribute in it."
        Exit Sub
    Else
        MsgBox "Updating attribute in block """ & blk.EffectiveName & """..."
    End If
    
    Dim atts As Variant
    Dim i As Integer
    Dim att As AcadAttributeReference
    
    atts = blk.GetAttributes()
    For i = 0 To UBound(atts)
        Set att = atts(i)
        Select Case att.TagString
            Case "NAME"
            att.TextString = "asasaas"
            Case "TYPE"
            att.TextString = "23455"
        End Select
    Next
    
End Sub

HTH

 

Norman Yuan

Drive CAD With Code

EESignature

Message 3 of 8

Anonymous
Not applicable

Well that's close but not exactly what I need. If you look on my attached drawing, I have a drawing page 15. I have room for 5 blocks, containing 4 or 5 other blocks. When I insert the block, I explode it so the blocks are now editable. Because this is a template, they will always be inserted in the same position (from the main block with nested blocks). So I want to use the insertion point coordinates to select the block I want to edit,  then change the attribute text, then exit and go to the next block. So on the drawing page 15, you can see the first two columns of blocks (surrounded in blue) are constant so those need no manipulation. In the third set (column 15.4 & 15.5) the text I want to change are within the circles (not part of the template, I put those there so you could find them quicker). So the program would change the following (for this column only): Change MSP151 to MSP 155, change CON151 to CON155, change C151 to C155, and M151 to M155. As in the other 2 columns, the main block always has those "151" numbers in the block, and will always remain default. So far, I have the program working the way I want, I just need to change the attributes

0 Likes
Message 4 of 8

norman.yuan
Mentor
Mentor

Based on your descriptions from original post and this reply (and the picture you attached), I still think my code sample showed the correct logic to do what you wanted. The code might need some change to suit your drawing, but the logic should be about the same.

 

Unless I have the drawing, really cannot say how the code can, or cannot work against this drawing, if it does not do fully as you want.

 

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 5 of 8

Anonymous
Not applicable

Ok, well your code is fine for what you are wanting it to do, we are just not on the same page. One, I don’t want the user to select the blocks, and two, I don’t need all that code to check to see if it is a block because I know it is a block with attributes that I want to change. This program is only used once, and only once. So if the user explodes the block again, they will have to call up the template again and start over. The main block containing 3 or 4 other attributed blocks will never change.  The location (the x/y insertion point coordinates) for each block has been taken down so I know where each block is in the drawing. So I need code that will find the block I want to change the attribute with x/y coordinates, get the attributes, then change the attributes I want to change, and that’s it. Here is a better explanation (I hope) of what I am doing:

User calls up the template.

The program starts automatically, asking the user information via forms with combo-boxes and check-boxes and option buttons.

On the last form, the user hits the “create drawings” button and manipulates the drawing using the input from the forms.

The user saves the drawing in a working folder for future reference, prints it out so the shop can wire the unit.

And that’s it.

The program uses VBA to insert all the blocks I have created and explodes them afterwards in case the user has some small editing to do. All of the drawings are on one .DWG file to allow VBA to work properly. These drawings are on the same plane, one next to the other in order. The number of drawings vary due to the extreme amount of variations we could have of this particular unit, hence the push for automation. The company here wants to get away from the old way of copying existing drawings and editing them as if there is a mistake on the copy, there is a mistake on the new project. So they want a template and VBA to control the template.

These units can have anywhere between 3 minimum and 11 maximum compressors, with fan motors of 5 minimum to 33 maximum fans. So there are over 42 compressor configurations, all that can have 21 models of 460 compressors, and 21 models of 208 compressors, all with different part numbers, different amp draw which means different circuit protection, and the list goes on and on.

I can keep mistakes to a minimum (actually to zero mistakes) by creating a block that contains 3 or 4 blocks with all the proper part numbers, and insert it into 5 columns of the drawing. Each column has a page.column number that the tags of the 3-4 blocks need to reflect. So the first block on page 15, column 15.1, will make the tags have 151 in it. Same for column area 2, 3, 4 & 5. All those tags have to be changed to reflect the column it resides in per our standards. Because I know the program inserts each of the main blocks in a certain position 5 times per one drawing, in my code, the location will always be the same, and so there is no need for checking to see if it’s a block, or if it has attributes.

So in summary, I want to be able to (after the main block is exploded) select one of the blocks by insertion point coordinates, update the “Tag1” attribute with what I want it to be, and then continue the program. No checking if it’s a block, no checking if it has attributes.

Thanks!

0 Likes
Message 6 of 8

norman.yuan
Mentor
Mentor

Well, in your original post/question, it seems you have everything working and only want to know how to update attributes of nested blocks (after exploding the main block reference). So my code sample was meant to showing the logic of doing it.

 

Now, you are talking the entire workflow of your business process. It update to you to decide how much code you need to let the program to find/identify the target block so the target attributes can be updated. Naturally, if the program runs from an empty drawing and all the entities are brought in by your app, indeed you have full control as how to identify your code targets. That is, your code knows which block reference has the attributes to be updated. In this case, you only need to look

Private Sub UpdateAttributesInBlock(blk As AcadBlockReference)
....
End Sub

You can even remove "If Not blk.HasAttribute Then..." (but it would be harmless, the this piece of code could be shared in other situation - generalizing is a basic programming rule).

 

But to be honest, I am now not very certain what is your question/issue: how to update attributes of block references, which are nested in a main block to be exploded; or how to logically proceed the work as you described.

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 7 of 8

Anonymous
Not applicable

Lets try this:

How can I select a block using VBA by "having/knowing" the insertion point x/y coordinates of the block I want to edit, then updating the attribute value?

0 Likes
Message 8 of 8

norman.yuan
Mentor
Mentor

Well, to identify a block reference by its insertion point, if you know the point,you simply compare each block reference's insertion point. Something like:

Dim myPt(0 to 2) As Double

myPt(0)=1#:myPt(1)=1#:myPt(2)=0#

 

Dim ent As AcadEntity

Dim blk As AcadBlockReference

For Each ent in ThisDrawing.ModelSpace '' assume all the target blocks are in ModelSpace

  If TypeOf ent Is AcadBlockReference Then

    Set blk=ent

    If IsAtLocation(blk, myPt) Then

        '' This is the target block reference, do whatever you need to

    End If

  End If

Next

 

Private Function IsAtLocation(blk As AcadBlockReference, location As Variant) As Boolean

  Dim pt As Variant

  pt=blk.InsertionPoint

  '' Do your math to see if "pt"and "location" is the same (or very close)

  IsAtLocation = True/False

End Function

 

HTH

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes