Jump to content

changing attribute text width without having to select the block...


chauncy274

Recommended Posts

Hey guys I'm running in to a problem and I don't quite have time to sit down and figure it out and I don't know where else to look.

 

I have a block in many drawings that I managed to auto fill with information from our database using a lisp routine from Lee Mac (you're a genius lol) but the entries for one of the attributes is just slightly too long and I need a lisp routine (or if anyone has any other idea) where I can just type the known block name and attribute tag and the new text width that's wanted and when I call up the lisp routine it just goes in and does it without any prompting. This way I could batch the lisp routine across these thousand plus drawings. It would also be great if it could manage to not crap out if the drawing doesn't have an instance of that block since there are a handful of drawings that don't have the block in the drawing, but I can work around that.

 

I've tried writing a script that redefines the block and that works fine but it won't change the text width of the attribute, it only affects the changes I make to the lines of the block. Weird.

 

Any ideas?

Link to comment
Share on other sites

I've tried writing a script that redefines the block and that works fine but it won't change the text width of the attribute, it only affects the changes I make to the lines of the block. Weird.

 

Attribute References are associated with a Block Reference and their appearance is driven by the properties of the corresponding Attribute Definitions, however they are considered separate to and can be manipulated independently of the Block Definition, enabling Attribute References to hold differing values & properties between multiple Block References.

 

Therefore, if you perform modifications to the properties of the Attribute Definition within the Block Definition, these changes will not be reflected across all references of the block until an ATTSYNC operation is performed.

 

Alternatively, you can try the following code:

(defun c:changeattribwidth ( / blk idx obj sel tag wid )

   (setq blk "MyBlock" ;; Block Name(s) - allows wildcards
         tag "MyTag"   ;; Attribute Tag(s) to Modify - allows wildcards
         wid 0.5       ;; New Attribute Width
   )
   (if (setq sel (ssget "_X" (list '(0 . "INSERT") '(66 . 1) (cons 2 blk))))
       (repeat (setq idx (sslength sel))
           (if
               (or
                   (and
                       (vlax-property-available-p (setq obj (vlax-ename->vla-object (ssname sel (setq idx (1- idx))))) 'effectivename)
                       (wcmatch (strcase (vla-get-effectivename obj)) (strcase blk))
                   )
                   (wcmatch (strcase (vla-get-name obj)) (strcase blk))
               )
               (foreach att (vlax-invoke obj 'getattributes)
                   (if
                       (and
                           (wcmatch (strcase (vla-get-tagstring att)) (strcase tag))
                           (vlax-write-enabled-p att)
                       )
                       (vla-put-scalefactor att wid)
                   )
               )
           )
       )
   )
   (vlax-for def (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
       (if (wcmatch (strcase (vla-get-name def)) (strcase blk))
           (vlax-for obj def
               (if 
                   (and
                       (= "AcDbAttributeDefinition" (vla-get-objectname obj))
                       (wcmatch (strcase (vla-get-tagstring obj)) (strcase tag))
                       (vlax-write-enabled-p obj)
                   )
                   (vla-put-scalefactor obj wid)
               )
           )
       )
   )
   (princ)
)
(vl-load-com) (princ)

Link to comment
Share on other sites

Attribute References are associated with a Block Reference and their appearance is driven by the properties of the corresponding Attribute Definitions, however they are considered separate to and can be manipulated independently of the Block Definition, enabling Attribute References to hold differing values & properties between multiple Block References.

 

Therefore, if you perform modifications to the properties of the Attribute Definition within the Block Definition, these changes will not be reflected across all references of the block until an ATTSYNC operation is performed.

 

Brilliant like always Lee Mac. I really appreciate this it worked beautifully.

 

I've ben reading up on the attsync command but still haven't gotten it to work. I have 1 instance of this block (called "DCS 1") in a thousand different drawings. I created the block in a template drawing file and then we've been making copies of this template file to create all these new drawings. If I were to change the width in the original file and then ATTSYNC it would update all drawings? Or run ATTSYNC in all drawings would update all of the drawings accordingly? Or does ATTSYNC only sync them within that one drawings?

 

I appreciate the advice greatly. Thanks.

Link to comment
Share on other sites

Ok, I think I understand a bit more about the attsync command, and if I'm not mistaken I can even do this through a script file?

 

as in:

-INSERT

oldblock=newblock.dwg

Y

(COMMAND \e "RESUME")

attsync

name

oldblock

 

So attsync sync up the attributes to what ever they are on the official block definition, which only changes if you redefine the actual block definition by insert= or editing the block in the drawing?

Link to comment
Share on other sites

Brilliant like always Lee Mac. I really appreciate this it worked beautifully.

 

Excellent to hear.

 

I have 1 instance of this block (called "DCS 1") in a thousand different drawings. I created the block in a template drawing file and then we've been making copies of this template file to create all these new drawings.

 

If I were to change the width in the original file and then ATTSYNC it would update all drawings? Or run ATTSYNC in all drawings would update all of the drawings accordingly? Or does ATTSYNC only sync them within that one drawings?

 

Firstly, when a drawing is created using a drawing template, the settings from the template file are merely copied to the new drawing - there is absolutely no associativity between the template and new drawing (you cannot determine which template was used to create a drawing), and so making changes to the template will not affect any existing drawings.

 

The ATTSYNC command will only operate on blocks within the active drawing.

 

Ok, I think I understand a bit more about the attsync command, and if I'm not mistaken I can even do this through a script file?

 

as in:

-INSERT

oldblock=newblock.dwg

Y

(COMMAND \e "RESUME")

attsync

name

oldblock

 

So attsync sync up the attributes to what ever they are on the official block definition, which only changes if you redefine the actual block definition by insert= or editing the block in the drawing?

 

Yes, this is another way to modify the blocks, however, be aware that the ATTSYNC command will restore all properties (including geometric properties) of all attribute references held by the block to match those held by the corresponding attribute definitions within the block definition - this includes the position of attribute references relative to the block reference (if the 'Lock Position' property is not enabled).

Link to comment
Share on other sites

Excellent to hear.

 

Firstly, when a drawing is created using a drawing template, the settings from the template file are merely copied to the new drawing - there is absolutely no associativity between the template and new drawing (you cannot determine which template was used to create a drawing), and so making changes to the template will not affect any existing drawings.

That's what I've always thought, I was just trying to figure out the command and it's the only thing I could think of atm. Thanks for clearing it up.

The ATTSYNC command will only operate on blocks within the active drawing.

 

Yes, this is another way to modify the blocks, however, be aware that the ATTSYNC command will restore all properties (including geometric properties) of all attribute references held by the block to match those held by the corresponding attribute definitions within the block definition - this includes the position of attribute references relative to the block reference (if the 'Lock Position' property is not enabled).

Right. That makes sense. Unfortunately for me that does bring up a certain problem for me. There is one attribute in the block that has been shrunk down to numerous different widths to fit with whatever tag number has been placed in it. So if I re-insert and attsync on all drawings some of the tags will be either too wide, or I'll have to make them all on the smaller side so they fit.

 

 

I think your lisp routine that you typed up for me is the best option for this scenario. Thanks so much for all the help.

Link to comment
Share on other sites

Lee-Mac,

 

I've been going over your code just to get a better understanding of it and I'm trying to figure out the logic of a part of it. I'm hoping you can explain the purpose of it?

 

           (if
               (or
                   (and
                       (vlax-property-available-p (setq obj (vlax-ename->vla-object (ssname sel (setq idx (1- idx))))) 'effectivename)
                       (wcmatch (strcase (vla-get-effectivename obj)) (strcase blk))
                   )
                   (wcmatch (strcase (vla-get-name obj)) (strcase blk))
               )
               (foreach att (vlax-invoke obj 'getattributes)
                   (if
                       (and
                           (wcmatch (strcase (vla-get-tagstring att)) (strcase tag))
                           (vlax-write-enabled-p att)
                       )
                       (vla-put-scalefactor att wid)
                   )
               )
           )

The (or(and section of the code, is it so that it will work on dynamic blocks as well? As in "vla-get-effectivename" gets you the name of a dynamic block and "vla-get-name" gets you the name from a standard block? I can't find much info on either of those commands and I'm not sure why you'd need both of them unless it was something like that?

Link to comment
Share on other sites

The (or(and section of the code, is it so that it will work on dynamic blocks as well? As in "vla-get-effectivename" gets you the name of a dynamic block and "vla-get-name" gets you the name from a standard block?

 

The ActiveX effectivename property is required to obtain the 'true' name of a dynamic block (as dynamic blocks reference anonymous block definitions when the dynamic block parameters differ from the dynamic block definition).

 

The effectivename property will return the correct block name for both dynamic blocks and standard blocks, however, this property will not be available in AutoCAD versions in which dynamic blocks are not available, hence the vlax-property-available-p test is required to account for this, with the alternative of obtaining the ActiveX name property.

 

I can't find much info on either of those commands and I'm not sure why you'd need both of them unless it was something like that?

 

See:

Effective Block Name

Get Anonymous References

Link to comment
Share on other sites

The ActiveX effectivename property is required to obtain the 'true' name of a dynamic block (as dynamic blocks reference anonymous block definitions when the dynamic block parameters differ from the dynamic block definition).

 

The effectivename property will return the correct block name for both dynamic blocks and standard blocks, however, this property will not be available in AutoCAD versions in which dynamic blocks are not available, hence the vlax-property-available-p test is required to account for this, with the alternative of obtaining the ActiveX name property.

 

That makes perfect sense. Thank you so much.

Link to comment
Share on other sites

   (if (setq sel (ssget "_X" (list '(0 . "INSERT") '(66 . 1) (cons 2 blk))))
       (repeat (setq idx (sslength sel))
           (if
               (or
                   (and
                       (vlax-property-available-p (setq obj (vlax-ename->vla-object (ssname sel (setq idx (1- idx))))) 'effectivename)
                       (wcmatch (strcase (vla-get-effectivename obj)) (strcase blk))
                   )
                   (wcmatch (strcase (vla-get-name obj)) (strcase blk))
               )
               (foreach att (vlax-invoke obj 'getattributes)
                   (if
                       (and
                           (wcmatch (strcase (vla-get-tagstring att)) (strcase tag))
                           (vlax-write-enabled-p att)
                       )
                       (vla-put-scalefactor att wid)
                   )
               )
           )
       )
   )

 
   (vlax-for def (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
       (if (wcmatch (strcase (vla-get-name def)) (strcase blk))
           (vlax-for obj def
               (if 
                   (and
                       (= "AcDbAttributeDefinition" (vla-get-objectname obj))
                       (wcmatch (strcase (vla-get-tagstring obj)) (strcase tag))
                       (vlax-write-enabled-p obj)
                   )
                   (vla-put-scalefactor obj wid)
               )
           )
       )
   )

Lee-Mac,

 

I'm still studying the code in my spare time so forgive the stupid questions lol. I'm really trying to learn.

Why do you need both of these? As far as I can tell, the first bit of code gets the blocks, gets the attributes, and changes the width "(vla-put-scalefactor att wid)". I have commented off the entire bottom section of code and ran the program and it still worked just fine. But I'm going over the bottom code and it seems like it's purpose is the exact same as the above, just written differently? But if I comment off the top code, the program runs but changes nothing. It seems to not work. What's the difference and why is the bottom part needed?

 

Thanks!

Link to comment
Share on other sites

I have commented off the entire bottom section of code and ran the program and it still worked just fine.

 

Hint: try using ATTSYNC after running the program in this state.

Link to comment
Share on other sites

Oh, you sneaky dog you.

 

So:

(ssget "_X" (list '(0 . "INSERT") '(66 . 1) (cons 2 blk))) = gets all actual block entities inside the drawing that also have attributes

 

(vla-get-blocks (vla-get-activedocument (vlax-get-acad-object))) = get all block definitions inside the drawing

 

Correct?

Link to comment
Share on other sites

Oh, you sneaky dog you.

 

o:)

 

(ssget "_X" (list '(0 . "INSERT") '(66 . 1) (cons 2 blk))) = gets all actual block entities inside the drawing that also have attributes

 

Correct, the expression retrieves a selection set of all attributed block references with the given block name [looking back over the code, (cons 2 blk) should actually be (cons 2 (strcat "`*U*," blk)) ]

 

(vla-get-blocks (vla-get-activedocument (vlax-get-acad-object))) = get all block definitions inside the drawing

 

Returns the ActiveX Blocks Collection, which, as you correctly note, contains all Block Definitions (including Modelspace & Paperspace definitions).

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...