Change text width of text inside all blocks

Change text width of text inside all blocks

roland.r71
Collaborator Collaborator
4,725 Views
10 Replies
Message 1 of 11

Change text width of text inside all blocks

roland.r71
Collaborator
Collaborator

Hi guys,

 

 

Been trying to create a routine to change the text width on ALL regular single line text (not mtext, although I wouldn't mind) and attributes.


So far I got it to work on both, but I just can't get it to work on plain text inside all blocks.

 

 

My knowledge of (auto)lisp is still a bit limited but usually I manage. Not in the least thanks to this forum, but I'm stuck on selecting & changing text entities inside/belonging to blocks.

 

 

My guess is that while working thru the selection set with blocks, to change the attributes, I 'need' to select some type of text entities belonging to that block as well, but I have no clue on how to get to the entity data.

 

 

Any routine to do just that, will be appreciated. I'll manage to implement it into the rest of my code. Only found one that will do so on a selected block, but I've been unable to translate that to work with an entire selection set containing blocks. [ím using: (setq ss (ssget "X" '((0 . "INSERT")))) if I need a different selection set, let me know]

 

 

I'm using preset values stored inside an .ini file, so there's no need to ask for user input. (setq ssw "1.0") will do.

 

 

Note: Usually I try to avoid using VL. As I know even less about it as AutoLISP.

0 Likes
Accepted solutions (1)
4,726 Views
10 Replies
Replies (10)
Message 2 of 11

Anonymous
Not applicable

Hi,

   Try "BATTMAN" command

STM

0 Likes
Message 3 of 11

SeeMSixty7
Advisor
Advisor

Working with Blocks and inserts. These are two different things you will need to work with.

Block = Definition of the block itself (Block Table)

Insert = an instance of the block in your drawing. (entity)

 

If you have text inside a block it is part of the definition. You will need to update the block definition and it will update all inserts of that block.

Attributes are actually attached to the inserts. ATTDEFS are part of the block. Redefining the block definition's ATTDEFS will not affect anything but new inserts. You will need to run BATTMAN or some routine to update the inserts attributes. This is where SSGET will be used to get the inserts and then look to see if they have attributes attached.

 

Hopefully that helps clear up the confusion.

 

TEXT inside block, must be updated in Block definition

 

ATTRIBUTES attached to insert must be updated at the insert level, unless redefining ATTDEFS and running something to update all the INSERTS (Think BATTMAN)

 

Good luck.

0 Likes
Message 4 of 11

roland.r71
Collaborator
Collaborator

I guess you misunderstood the question. I'm not looking for a way to manage my block attributes. I want to manage TEXT inside blocks.

 

As I created a "no more as needed" test drawing, containing 1 block with 1 TEXT entity (& a rectangle), all BATTMAN will do for me is report:

"This drawing contains no attributed blocks."

 

...which I already knew 😛

 

 

0 Likes
Message 5 of 11

roland.r71
Collaborator
Collaborator

@SeeMSixty7 wrote:

Working with Blocks and inserts. These are two different things you will need to work with.

Block = Definition of the block itself (Block Table)

Insert = an instance of the block in your drawing. (entity)

 

If you have text inside a block it is part of the definition. You will need to update the block definition and it will update all inserts of that block.

<snip>

 


Thanks!

That brings me a bit closer as I was working with the INSERTS the whole time.

Message 6 of 11

Kent1Cooper
Consultant
Consultant

@roland.r71 wrote:

.... a routine to change the text width on ALL regular single line text (not mtext, although I wouldn't mind) and attributes. ... inside all blocks.

....


I swiped some code I already had that steps through all objects in all Block definitions [originally to do something else to them] and adjusted it to change the width factor of Text and Attributes.  In fairly simple terms, and lightly tested:

 

;;  BlockTextWidth.lsp [command name: BTW]
;;  To change the Width of all Text and Attribute objects in all Block definitions
;;    in the drawing, including nested Block definitions [but not Xrefs].
;;  Kent Cooper, 25 April 2017

(vl-load-com)
(defun C:BTW ; = Block Text Width
  (/ width blk ent)
  (setq width (getreal "\nWidth factor for all Text/Attributes: "))
  (setq blk (tblnext "block" t)); first one in Table
  (while blk
    (if (= (logand 20 (cdr (assoc 70 blk))) 0); not an Xref [4] or Xref-dependent [16]
      (progn ; then -- process this Block
        (setq ent (cdr (assoc -2 blk))); first object in Block definition
        (while ent
          (if (wcmatch (cdr (assoc 0 (entget ent))) "TEXT,ATTDEF")
            (vlax-put (vlax-ename->vla-object ent) 'ScaleFactor width)
          ); if
          (setq ent (entnext ent)); next object
        ); while
      ); progn
    ); if
    (setq blk (tblnext "block")); next one in Table
  ); while
  (command "_.attsync" "_name" "*"); update width in Block Attributes, if any
  (princ)
); defun

It could be made with a built-in width factor, rather than asking the User for it [in place of the 'width' variable here], if that's more appropriate to your usage.  Also, it could use error handling and the other usual enhancements.

 

Kent Cooper, AIA
0 Likes
Message 7 of 11

roland.r71
Collaborator
Collaborator
Accepted solution

@Kent1Cooper wrote:

I swiped some code I already had that steps through all objects in all Block definitions [originally to do something else to them] and adjusted it to change the width factor of Text and Attributes.  In fairly simple terms, and lightly tested:

 

...code...

 

It could be made with a built-in width factor, rather than asking the User for it [in place of the 'width' variable here], if that's more appropriate to your usage.  Also, it could use error handling and the other usual enhancements.

 


Thanks. It might have done the trick, but i just finnished my own bit of code, after being put in the right direction.

 

(defun c:bdtw ( bn_list tw / i bd el en)

; bn_list = blockname list
; tw      = text width [ string "1.0" ]

   (setq i 0)
   (while (< i (length bn_list))
      (if (setq bd (tblobjname "block" (nth i bn_list)))
         (while (setq bd (entnext bd))
            (setq el (entget bd))
            (setq en (cdr (assoc 0 el)))
            (if (= en "TEXT")
               (progn
                  (setq el (subst (cons 41 (atof tw))(assoc 41 el)el))
                  (entmod el)
               ) ; end progn
            ) ; end if
         ) ; end while
      ) ; end if
      (setq i (1+ i))
   ) ; end while
   (princ)
) ; end defun

(setq i 0)
(setq bn_list nil)
(setq ss (ssget "X" (list (cons 0 "INSERT"))))
(while (< i (sslength ss))
   (setq bn (cdr (assoc 2 (entget (ssname ss i)))))
   (if (not (member bn bn_list))
      (setq bn_list (append bn_list (list bn)))
   ) ; end if
   (setq i (1+ i))
) ; end while

(c:bdtw bn_list "1.0")
(setq i nil bn_list nil ss nil bn nil)
(command "regenall")

The function is what i was looking for, the rest of it is for reference / testing / completeness.

 

As i was already going thru all the INSERT's for some other changes, i collect the blocknames into a list and use that to edit all the block definitions.

 

the list is unique, as there can be multiple inserts of the same blockdef. No need to process the same blockdef 100x 😉

 

So, all you need is a list of blocknames to process and a width for all nested text entities.

 

Message 8 of 11

Kent1Cooper
Consultant
Consultant

@roland.r71 wrote:

...

As i was already going thru all the INSERT's for some other changes, i collect the blocknames into a list and use that to edit all the block definitions.

the list is unique, as there can be multiple inserts of the same blockdef. No need to process the same blockdef 100x 😉

So, all you need is a list of blocknames to process and a width for all nested text entities.


The problem I see with that approach is that if I'm reading it right, it will not process any Block definitions you have in the drawing that currently do not happen to be Inserted anywhere.  So you could later Insert some Block with Text/Attribute content that won't have had that width factor applied, and you'll have to run your routine again to apply the width to that Block's contents.  Mine will apply it in all Block definitions, whether Inserted or not, since it gets its Block names from the Block table, not from whatever insertions of Blocks there may be in the drawing.  And since it gets them that way, it also doesn't have any reason at all to even think about processing the same definition more than once.

Kent Cooper, AIA
0 Likes
Message 9 of 11

roland.r71
Collaborator
Collaborator

@Kent1Cooper wrote:

The problem I see with that approach is that if I'm reading it right, it will not process any Block definitions you have in the drawing that currently do not happen to be Inserted anywhere.  So you could later Insert some Block with Text/Attribute content that won't have had that width factor applied, and you'll have to run your routine again to apply the width to that Block's contents.  Mine will apply it in all Block definitions, whether Inserted or not, since it gets its Block names from the Block table, not from whatever insertions of Blocks there may be in the drawing.  And since it gets them that way, it also doesn't have any reason at all to even think about processing the same definition more than once.

Yes. that is correct....but it's not a problem, in this case.

 

Although for the function it doesn't matter how you get that list of blocknames. (so it might as well be all of them)

The selection is done elsewhere, in my case, and based on all inserted blocks. (for now)

 

The reason for this approach is that i don't care about the non-inserted blocks. (they get purged anyways 😉 ) but only the visual ones.

My own blocks (can) get redefined, so there's no problem there. (as those are the only ones being added)

 

I need it to adjust old / third party / non-acad drawings. (non-acad being dwg's exported from eplan, elcad, etc. from various sources) with all sorts of different blocks & settings & manual changes.

 

This way i can apply different settings to (groups of) blocks, if needed. (i'm sure to find some exceptions that i don't want to change 😉 )

 

So i'm actually avoiding any future problem with modifying more as i need or want to.

 

& the function is easy to expand with more settings to change, should the need arise, to a given set of blocknames.

Allowing for changing different sets of blocks with different settings within the same drawing, or just a limited set of blocknames.

Even a fixed list of blocknames, regardless if they exist inside the current drawing.

 

So this approach gives me way more flexibility and fits my needs much better, for the situation at hand.

0 Likes
Message 10 of 11

Designer_1E
Enthusiast
Enthusiast

Can you post your lisp?

 

I tried the one above, but it doesn't work.

0 Likes
Message 11 of 11

roland.r71
Collaborator
Collaborator

I'm currently working for a client using another (electrical engineering) program, so I don't have my lisps with me and I can't test the code as posted (to see if, and if so what is wrong)

 

I'll have a look when I get home.

0 Likes