Author Topic: Redefine Block with VBA..  (Read 17631 times)

0 Members and 1 Guest are viewing this topic.

hardwired

  • Guest
Redefine Block with VBA..
« on: March 19, 2008, 12:04:49 PM »
Hi,

Have a program that creates a block, add a table of attiributes and then inserts it, will all works spot on now (thanks to all who helped me before)...

...but if there is already a block reference of the same type in the drawing i want to redefine it with the new information that the user enters NOT add to it, which what it seems to do...

In the program, when the userform loads, it checks if the block exists and populates the userform with its attribute values, which works fine, and this allows the user to edit the information in the block and not start over each time, but when the user finishes the program and the block is inserted, its an almagamation of the existing and new information..

Any ideas?

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: Redefine Block with VBA..
« Reply #1 on: March 19, 2008, 02:15:05 PM »
If there is already a block reference in the drawing, you can do a few different things ...

a) rename the old block reference
b) programmatically delete all objects in the old definition
c) delete the existing reference(s) and purge the drawing

Of the 3, b sees to be the most desirable
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

Bob Wahr

  • Guest
Re: Redefine Block with VBA..
« Reply #2 on: March 19, 2008, 02:18:07 PM »
don't have the time to test it right now, but try a

for each blkref in thisdwg.mspace
  if blkref.name = "x" then
    blkref.update
  end if
next blkref

Arizona

  • Guest
Re: Redefine Block with VBA..
« Reply #3 on: March 19, 2008, 03:28:31 PM »
Hi,

Have a program that creates a block, add a table of attiributes and then inserts it, will all works spot on now (thanks to all who helped me before)...

...but if there is already a block reference of the same type in the drawing i want to redefine it with the new information that the user enters NOT add to it, which what it seems to do...

In the program, when the userform loads, it checks if the block exists and populates the userform with its attribute values, which works fine, and this allows the user to edit the information in the block and not start over each time, but when the user finishes the program and the block is inserted, its an almagamation of the existing and new information..

Any ideas?

Are the users simply changing attribute information or is the graphic itself changing?
Why redefine the block definition?

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: Redefine Block with VBA..
« Reply #4 on: March 19, 2008, 04:17:40 PM »
try this function before adding your data to the block

Code: [Select]
Function CleanoutBlock(currentBlock As AcadBlock)
    Dim blkItem As AcadEntity
    For Each blkItem In currentBlock
        blkItem.Delete
    Next blkItem
End Function
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

hardwired

  • Guest
Re: Redefine Block with VBA..
« Reply #5 on: March 20, 2008, 05:58:32 AM »
Hi,

I have tried this in my program so far....

(The SSetX is a SelectionSet it creates on UserForm loading, to check for existing blocks..

Code: [Select]
'Redefine current block info if chart exists..
Dim BlK As AcadBlockReference
Dim EntX As AcadEntity

If SSetX.Count > 0 Then
    For Each BlK In SSetX
        If BlK.Name = "Fixings_Chart" Then
            For Each EntX In BlK
                EntX.Delete
            Next EntX
        End If
    Next BlK
End If

......it flags an error says object doesn't support this method, which obviously is refereing to the BlockRef, which if i want to access entities in it, should be a Block not a BlockRef....so where do i go from here?


I also, like Keith's Function:

Code: [Select]
Function CleanoutBlock(currentBlock As AcadBlock)
    Dim blkItem As AcadEntity
    For Each blkItem In currentBlock
        blkItem.Delete
    Next blkItem
End Function

.....but how do i call the function from the code just before i add the new data?

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: Redefine Block with VBA..
« Reply #6 on: March 20, 2008, 08:31:12 AM »
I don't know your exact situation, but your code has some potential issues that perhaps we can resolve.

Using the code you provided, you are evidently selecting all of the blocks in the drawing and then iterating through them all. If you want to edit the block references, you have to edit the block definition. If you edit the block definition, it wil automatically reflect in all of the block references, thereby negating the need to iterate through all of the block references in the drawing. Using the code you provided, if it worked, it would redefine the same block over and over again for each instance the block was inserted in the drawing. This is not necessary and is needless repetition of the same procedure.

Earlier you stated that you have code that puts items into the block, but you didn't have code to remove items from the block. The code I provided removes all items from the block you pass as an argument to the function .. but you have to pass the AcadBlock not the AcadBlockReference.

download the module I posted in the previous thread and import it into your project (right click in the project explorer and click import file) then add this code to your form load event
Code: [Select]
Dim Blk As AcadBlock

If acBlock.BlockExists("Fixings_Chart").Exists = True Then
  Set Blk = ThisDrawing.Blocks.Item("Fixings_Chart")
  CleanoutBlock Blk '<-- call the CleanoutBlock function here
End If
'Add code here to put the new entities in the block
'Blk.Addxxx functions to add the entities as needed

Add this code to your form as a new function

Code: [Select]
Function CleanoutBlock(currentBlock As AcadBlock)
    Dim blkItem As AcadEntity
    For Each blkItem In currentBlock
        blkItem.Delete
    Next blkItem
End Function

You could provide a little more code and we can give you pointers about where you are going wrong.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

hardwired

  • Guest
Re: Redefine Block with VBA..
« Reply #7 on: March 20, 2008, 09:06:55 AM »
Thanks Keith, for taking the time out for this (and to everyone else for that matter)..

I have done exactly as you said and the new instance it inserts looks exactly how it should, not a mix of the old elements and the new.....the only thing is that all existing block inserts haven't changed and still look as they did before running the program again..



Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: Redefine Block with VBA..
« Reply #8 on: March 20, 2008, 09:11:49 AM »
Thanks Keith, for taking the time out for this (and to everyone else for that matter)..

I have done exactly as you said and the new instance it inserts looks exactly how it should, not a mix of the old elements and the new.....the only thing is that all existing block inserts haven't changed and still look as they did before running the program again..


Then you have something else going on ... have these perhaps been edited and saved as dynamic blocks? if so, they may not be updated properly ... or maybe you should regen all views
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

hardwired

  • Guest
Re: Redefine Block with VBA..
« Reply #9 on: March 20, 2008, 09:41:19 AM »
ah, if i regen then the graphical nature of the block is updated but not the attributes, if the user removes the number of attributes from the list then these still remain in the blocks, so that the table has the correct number of rows, but not the correct number of attributes (some overrun down past the extents of the table)..

I would post my full code but it exceeds the character limit for each post. Maybe, it would help anyway, post the code in sections on different posts..

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Redefine Block with VBA..
« Reply #10 on: March 20, 2008, 10:28:51 AM »
attributes don't update.
It's easier to find each blockref and replace it with  a new one, matching the properties first

hardwired

  • Guest
Re: Redefine Block with VBA..
« Reply #11 on: March 20, 2008, 11:30:00 AM »
But surely, using the function Keith supplied, which deletes all entities in the block, there wouldn't be any attributes that won't update, so the only the new attributes will be present and shown?

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: Redefine Block with VBA..
« Reply #12 on: March 20, 2008, 11:44:50 AM »
Ah .. now I more fully understand the nature of your request ...

To my knowledge, the only method to update the attributes if you change the number of the attributes, is to attsync the block references. You could alternatively insert the blocks with VBA and then grab the attributes and modify them.

In VBA you can only attach attributes to a block, modelspace or paperspace, there is no addattributereference method to add a reference to an attribute in the block.

Presuming you are adding the attributes back to the block with AddAttribute, you must then go through each AcadBlockReference, grab the origin, scale, rotation, layer etc that you want to keep the same, then insert a new block with the same information and then update the attributes as needed.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

hardwired

  • Guest
Re: Redefine Block with VBA..
« Reply #13 on: March 20, 2008, 12:15:39 PM »
oh right, so even adding:

Code: [Select]
' Checks if table exists and redefines (clearsout) the block of all data..
Function CleanoutBlock(currentBlock As AcadBlock)
    Dim blkItem As AcadEntity
    [color=red]Dim blkAtt As AcadAttribute[/color]
    For Each blkItem In currentBlock
        blkItem.Delete
    Next blkItem
[color=red]    For Each blkAtt In currentBlock
        blkAtt.Delete
    Next blkAtt[/color]
End Function
...to your function won't work?

I tried it, but still nothing. All i want to do is delete the attributes (and all block entities) from the block, so its empty and then put back all the stuff the program does in the block, so if there any blocks the user has inserted anywhere, the blocks will reflect what the user chooses in the program..

Here's a brief lowdown an what the program does: It creates a fixings chart / table from user defined data (the user can also pick a fixing from an inserted block in a drawing and it will enter the block name in the textbox for that chosen fixing. There are 10 possible rows to create, each one selected / deselected by checkbox. When run, it adds two types of attribute for each row to the table / chart, one is the reference number for the item (a constant) (ie: FX1, FX2 etc), the second is the description (a normal) which the user can edit in the text boxes on the userform. When loaded (userform_Initialise), the program searches for any existing insert of the table and populates the userform with that data, so the user can edit / add to / delete from etc.. and when completed, it inserts the block (if new / no existing table was found) or just updates the existing..

Now with my code (and Keith's addition), it works 99% but just won't delete the existing normal attributes (it DOES however delete the constant attributes (the reference ones)..

I thought, as it deletes these constant attributes (all attributes in this program created by Block.AddAttribute by the way) it would also delete the normal ones too, but it doesn't. Is this because of the 'constant' property of the attribute?


Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: Redefine Block with VBA..
« Reply #14 on: March 20, 2008, 01:51:43 PM »
You are not understanding ....

a) When you edit a block with VBA, you only edit the attributes in the block table. It does not affect the block references

b) If you use attsync after using your command, all of the attributes that don't exist in the block, but are attached to the block reference will be removed from the block reference and all attributes in the block, but not in the block reference will be added to the block reference.

c) VBA does not have a mechanism to do this with code, so, you have to create your own.

d) The code I posted earlier does in fact delete the attributes from the block, but not the block reference. There is no method to do that in VBA

You can do one of the following:

1) Execute attsync at the command line after running your program
Quote from: AutoCAD command line
Command: attsync
Enter block name or ? for list <select block>: Fixings_Chart
Command:

2) Delete all occurences of Fixings_Chart in the drawing and replace them with new block references

Code: [Select]
    Dim OldBlkRef As AcadBlockReference
    Dim NewBlkRef As AcadBlockReference
   
    For Each OldBlkRef In ThisDrawing.ModelSpace
        With OldBlkRef
            If UCase(.Name) = "FIXINGS_CHART" Then
                Set NewBlkRef = ThisDrawing.ModelSpace.InsertBlock(.InsertionPoint, .Name, .XScaleFactor, .YScaleFactor, .ZScaleFactor, .Rotation)
                NewBlkRef.layer = .layer
                NewBlkRef.Color = .Color
                NewBlkRef.Linetype = .Linetype
                NewBlkRef.LinetypeScale = .LinetypeScale
                NewBlkRef.Lineweight = .Lineweight
                NewBlkRef.Normal = .Normal
                NewBlkRef.Visible = .Visible
                ' transfer all of the attribute tag values over in this area
                ' if you want to keep the existing values in the attributes
                .Delete
            End If
        End With
    Next OldBlkRef

Now the important thing to remember is that if you utilize the code to replace the existing block references, you will need to manually fill in all of the attributes unless you set the attribute value with a default value in the block.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

hardwired

  • Guest
Re: Redefine Block with VBA..
« Reply #15 on: April 08, 2008, 12:20:23 PM »
Hey Keith,

Me again, lol..

I've added you code to mine and when i run the program, which first checks if the block exists, which works, then i edit the userform as i'm meant to, then hit go and it errors out on the For Each OldBlkRef In ThisDrawing.PaperSpace line, with a Type Mismatch error even though there are blatantly other blocks (of the same name) in paperspace - would could be wrong?


Code: [Select]
'If Insert Chart (and update existing ones) is chosen..
ElseIf want1OPT.Caption = " Insert Chart (and update existing ones).." Then
[color=red]For Each OldBlkRef In ThisDrawing.PaperSpace[/color]
    With OldBlkRef
        If .Name = "Fixings_Chart" Then
            Set NewBlkRef = ThisDrawing.PaperSpace.InsertBlock(.InsertionPoint, .Name, .XScaleFactor, .YScaleFactor, .ZScaleFactor, .Rotation)
            NewBlkRef.Layer = .Layer
            NewBlkRef.color = .color
            NewBlkRef.Linetype = .Linetype
            NewBlkRef.LinetypeScale = .LinetypeScale
            NewBlkRef.Lineweight = .Lineweight
            NewBlkRef.Normal = .Normal
            NewBlkRef.Visible = .Visible
            .Delete
        End If
    End With
Next OldBlkRef
' Check if table exists and redefine (clearout) the block of all data before creating and inserting the new instance..
Dim Blk1 As AcadBlock
If acBlock.BlockExists("Fixings_Chart").Exists = True Then
  Set Blk1 = ThisDrawing.Blocks.Item("Fixings_Chart")
  CleanoutBlock Blk1 '<-- call the CleanoutBlock function here
End If
    CREATEChart
    INSERTChart


Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: Redefine Block with VBA..
« Reply #16 on: April 08, 2008, 03:46:24 PM »
The problem is that there are more than block references in the drawing paperspace. You have to filter the object types to make it work.

Code: [Select]
    Dim OldBlkRef As AcadEntity ' AcadBlockReference is implied, but we cannot specify if other types are present in the collection
    Dim NewBlkRef As AcadBlockReference
   
    For Each OldBlkRef In ThisDrawing.PaperSpace
        With OldBlkRef
            ' filter for block references only
            If OldBlkRef.ObjectName = "AcDbBlockReference" Then
                If UCase(.Name) = "FIXINGS_CHART" Then
                    Set NewBlkRef = ThisDrawing.PaperSpace.InsertBlock(.InsertionPoint, .Name, .XScaleFactor, .YScaleFactor, .ZScaleFactor, .Rotation)
                    NewBlkRef.Layer = .Layer
                    NewBlkRef.color = .color
                    NewBlkRef.Linetype = .Linetype
                    NewBlkRef.LinetypeScale = .LinetypeScale
                    NewBlkRef.Lineweight = .Lineweight
                    NewBlkRef.Normal = .Normal
                    NewBlkRef.Visible = .Visible
                    ' transfer all of the attribute tag values over in this area
                    ' if you want to keep the existing values in the attributes
                    .Delete
                End If
            End If
        End With
    Next OldBlkRef
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

hardwired

  • Guest
Re: Redefine Block with VBA..
« Reply #17 on: April 09, 2008, 10:26:17 AM »
Hi Keith,

Done what you suggested and it doesn't error now on that bit, doesn't error at all. What it doesn't do either is update the blocks and attribute values, well not first time anyway. If i hit the Update Chart button to run the program once, it updates the blocks but not the attribute values, and if i hit the button again it seems to do the correct job and update the attributes aswell. Why would this be? And how can i get it to do it on first hit of the button?

Code snippet is below:

Code: [Select]
For Each OldBlkRef In ThisDrawing.PaperSpace
With OldBlkRef
    If OldBlkRef.ObjectName = "AcDbBlockReference" Then
        If .Name = "Fixings_Chart" Then
            Set NewBlkRef = ThisDrawing.PaperSpace.InsertBlock(.InsertionPoint, .Name, .XScaleFactor, .YScaleFactor, .ZScaleFactor, .Rotation)
            NewBlkRef.Layer = .Layer
            NewBlkRef.color = .color
            NewBlkRef.Linetype = .Linetype
            NewBlkRef.LinetypeScale = .LinetypeScale
            NewBlkRef.Lineweight = .Lineweight
            NewBlkRef.Normal = .Normal
            NewBlkRef.Visible = .Visible
            '.Delete
            ' Check if table exists and redefine (clearout) the block of all data before creating and inserting the new instance..
            If acBlock.BlockExists("Fixings_Chart").Exists = True Then
                Set Blk1 = ThisDrawing.Blocks.Item("Fixings_Chart")
                CleanoutBlock Blk1 '<-- call the CleanoutBlock function here
            End If
        End If 'If block is Fixings_Chart..
    End If 'If block..
End With
    CREATEChart
Next OldBlkRef


....the CleanoutBlock was the function you posted:

Code: [Select]
Function CleanoutBlock(currentBlock As AcadBlock)
    Dim blkItem As AcadEntity
    Dim blkAtt As AcadAttribute
    For Each blkItem In currentBlock
        blkItem.Delete
    Next blkItem
    For Each blkAtt In currentBlock
        blkAtt.Delete
    Next blkAtt
End Function

.....and the CREATEChart is my sub for creating the block and setting the attribute values..


Any ideas?

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Redefine Block with VBA..
« Reply #18 on: April 09, 2008, 10:37:33 AM »
1) Update the block
2) Update the blockrefs

in that order

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: Redefine Block with VBA..
« Reply #19 on: April 09, 2008, 10:44:42 AM »
1) Update the block
2) Update the blockrefs

in that order
Indeed
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

hardwired

  • Guest
Re: Redefine Block with VBA..
« Reply #20 on: April 09, 2008, 12:07:15 PM »
Ok, tried that, won't work either, must be something in my code i am doing wrong. Could someone please take a look at moy code and run the program and let me know what might be wrong, would appreciate it muchly..

Oh, forgot to say, run it once to create and insert a chart to begin with, then run the program again and it should catch that there is already a chart(s) inserted..

hardwired

  • Guest
Re: Redefine Block with VBA..
« Reply #21 on: April 09, 2008, 12:22:15 PM »
Ok, sorry, changed the code about a bit more and it works perfectly..

Only thing now is if there NO INSERTED references BUT one in the collection, when you run the program it merges the two (the existing in the collection and the new updated one). Is there a way to purge out just that block (only if noreferences are INSERTED) before the program runs that part of the program?

When i purge out that block ref manually, and re-run the program it works, it just doesn't like any refs in the collection..

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: Redefine Block with VBA..
« Reply #22 on: April 09, 2008, 01:32:12 PM »
When I get some more time I'll look at it
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

hardwired

  • Guest
Re: Redefine Block with VBA..
« Reply #23 on: April 10, 2008, 08:10:54 AM »
Right, tested it (using the same code as the one i upload on my last post) and came up with the following problems:

  • When first run, and the chart is inserted for the first time (NO inserted refs or ones in the blocks collection), everything runs perfectly, except that it insertes to 0,0,0 and not the coords in the X and Y textboxes..
  • When first run, and the chart is inserted and there are NO other inserted BUT the block is in the block collection (ie: ran the program once, created the chart, deleted the inserted chart, ran the program again), it merged the block in the collection with the newly inserted one and its all a mess..
  • When run with charts already inserted (the program catches this and loads the attribute info to the form), and the UPDATE EXISTING CHARTS ONLY option is chosen, the charts update as they should visually, but i noticed that instead of deleting the existing attributes, or updating them, it adds more (each time you run it), so it has multiple instances of the same attibute, so instead of maximum of 10, it has 20 or so, which can be seen if you check the properties of the chart..
  • When run with charts already inserted and the INSERT CHART (AND UPDATE CHARTS ONES) option is chosen, the chart updates (but with same multiple attributes problem) but also the new chart is not inserted..

Sorry to be a PITA about all this Keith, but i can't get my head around it all and wanna get this one sorted..

Thanks for the help and for being patient :)

hardwired

  • Guest
Re: Redefine Block with VBA..
« Reply #24 on: April 10, 2008, 10:02:49 AM »
Ahhh, right on more tests (damn this thing, its really working my nips now!!)..

  • If there are more than one charts on a layout, the child (copied) blocks have the multiple attribute problem but the main parent one doesn't and it seems to do multiply by however many instances are inserted on that layout. The second block will have twice as many attributes (copies of the originals) and the third will have 3 times as many, and so on....
  • Also, it doesn't update other inserted references on OTHER layouts - well it does do the geometry, but not the attributes - so if there are any on another layout, then these will graphically (line etc) look right but they might have the attributes going out of the bottom of the chart or too few with empty spaces in the chart..

I would just do this with text in the block not attributes and be doen with it, but i won't be able to access the text and populate the form if the chart already exists - or will i? Can i use text instead of attributes and still have the same functionality of the program? Grrrrrrr

hardwired

  • Guest
Re: Redefine Block with VBA..
« Reply #25 on: May 29, 2008, 06:24:08 AM »
Hi,

I know this is an old one now, but can anyone take a look at this when they have time and point me home. Its 99ish% done and seems silly not to finish it..

Check out the last few threads for what the program is and isn't doing right and download the last posted dvb file..

Thanks in advance to anybody who cares, lol