Author Topic: Changing the properties of objects (of Text and Block)  (Read 2075 times)

0 Members and 1 Guest are viewing this topic.

iliekater

  • Mosquito
  • Posts: 9
Changing the properties of objects (of Text and Block)
« on: October 17, 2017, 05:18:03 AM »
Hi ! Many many years ago I used to write numerous lines in Lisp . However , after all this long time , I now almost don't remember anything ... That wouldn't be much of a problem , but today I have to make a small Lisp routine to change these two things :
a) Select all Text objects  (single line text)  (and regardless of their layers) and change their Height property to 0.05 .
b) Select all blocks on the specific layer "Point" and change their Scale properties (that is Scale X , Scale Y and Scale Z) to the value of 0.001 .

As far as concerning (a) , I know that I can select all Text objects by this :
( setq EverythingTEXT ( ssget "X" '( ( 0 . "TEXT" ) ) ) )
Unfortunately I no longer remember how can I set a property to a desired value ... I think it was with assoc and it had to do something with the structure of an onion ! (if I recall it well from a book by a guy called Omura , which I read when I was young ! ... ) .

As far as concerning (b) , I don't even remember how I even select blocks , not to mention on a specific layer ..

So , could you please help an old guy like me ?  :-) make these Lisps ?

David Bethel

  • Swamp Rat
  • Posts: 656
Re: Changing the properties of objects (of Text and Block)
« Reply #1 on: October 17, 2017, 05:34:15 AM »
Maybe these will help
Code: [Select]
(defun c:t05 (/ ss en ed i)
    (and (setq ss (ssget "X" (list (cons 0 "TEXT"))))
         (setq i 0)
         (while (setq en (ssname ss i))
                (setq ed (entget en))
                (entmod (subst (cons 40 0.05) (assoc 40 ed) ed))
                (setq i (1+ i))))
    (prin1))
Code: [Select]
(defun c:b01 (/ ss en ed i)
    (and (setq ss (ssget "X" (list (cons 0 "INSERT"))))
         (setq i 0)
         (while (setq en (ssname ss i))
                (setq ed (entget en))
                (foreach g '(41 42 43)
                  (setq ed (subst (cons g 0.001) (assoc g ed) ed)))
                (entmod ed)
                (setq i (1+ i))))
    (prin1))

Untested

-David
R12 Dos - A2K

iliekater

  • Mosquito
  • Posts: 9
Re: Changing the properties of objects (of Text and Block)
« Reply #2 on: October 17, 2017, 06:39:07 AM »
Well , at least as far as concerning (a) , I managed to find it in my old codes . Here's a much quicker way :
  ( setq EverythingTEXT ( ssget "X" '( ( 0 . "TEXT" ) ) ) )
  ( command "SCALETEXT" EverythingTEXT "" "" 0.05 )

Now I'll try to see if I find anything better for (b) . No matter what however , thanks for the reply !

Edit :
Now , in order to select all blocks in the specific layer POINT , one may use this :
( setq BlocksOnLayerPOINT  ( ssget "X" ( list ( cons 0 "INSERT" ) ( cons 8 "POINT" ) ) ) )
Now , what I cannot find (but I hope will ! ) is how I access the properties of the blocks . I think they were called "Group codes" or something like that . But then again , as I said , it's been a long time since I last dealed with Lisp ...  :-(
« Last Edit: October 17, 2017, 07:04:14 AM by iliekater »

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Changing the properties of objects (of Text and Block)
« Reply #3 on: October 17, 2017, 11:20:02 PM »
Quote
Here's a much quicker way :
Quicker in what way? If it happens in the blink of an eye how do you know it quicker?

David has pointed you in the direction for (b) as well.

Welcome to the Swamp.
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

iliekater

  • Mosquito
  • Posts: 9
Re: Changing the properties of objects (of Text and Block)
« Reply #4 on: October 18, 2017, 03:00:22 PM »
Quote
Quicker in what way? If it happens in the blink of an eye how do you know it quicker?
That's because I can see faster than the blinking of an eye ! 8-) That's a joke of course !

Quote
Welcome to the Swamp.

Thanks ! I was in the swamp before . For years ! Now that I came back , though , my account had been terminated . But that's no problem . And the truth is i remember you ; yes , with the cab picture ! Oh , by the way , is Keith Blackie still around ? I knew him long before coming to the Swamp ; although I can't remember the name of the previous glorious site  :-( .

Any way , as far as concerning the coding :
I didn't mean "faster" as far as concerning the time needed for the code to get executed . I was referring to the number of the lines . Of course what I thing of "faster" is personal ; there was no offense to David , who afterall kindly wrote down those codes .

I also tried to work it a little myself . I managed to find out that I can set the value of a property of an entinity (specifically here the Scale X , Y and Z factor of a Block object) by this :

( setq ObjectToChange ( ssget ":S" ) )
( setq PROPSsausage ( entget ( ssname ObjectToChange 0 ) ) )    ;(retrieve the sausage as it currently is)
( setq PROPSsausage ( subst ( cons 41 0.001 ) ( assoc 41 PROPSsausage) PROPSsausage) )  ;substitute the list with the new
( setq PROPSsausage ( subst ( cons 42 0.001 ) ( assoc 42 PROPSsausage) PROPSsausage) )  ;then for Scale Y
( setq PROPSsausage ( subst ( cons 43 0.001 ) ( assoc 43 PROPSsausage) PROPSsausage) )  ;then for Scale Z
( entmod PROPSsausage)

In which 41 is the characteristic number in the list of the property (for Scale X) and 0.001 is the new value .
Now all this made me happy for making me remember some of the old Lisp ! But soon I found out that this is not enough ! ... This code only works if you specifically select a single object ... But what about when there are a dozen of such blocks that need to be changed ? Well this is hard for me . Selecting them is easy (with SSget X) , but how will I set the value to each of the block ? I thing I'll have to somehow use the foreach function . And I see that David has already used it . So I'll try to see if I can adopt it to my own code . Afterall , that's why I like programing : it's like Mathematics ; you can do the same thing through various of ways !  :-) However , any suggestion will be welcomed !

« Last Edit: October 18, 2017, 03:08:33 PM by iliekater »

dubb

  • Swamp Rat
  • Posts: 1105
Re: Changing the properties of objects (of Text and Block)
« Reply #5 on: October 18, 2017, 03:15:15 PM »
This might be of help.
I copied and modified this script. It allows you to select more than one block of the same name.

Type "BLS" to run the command.

Code: [Select]
;blockselect function
(defun bls (/ s blk bn opt selection )
(vl-load-com)
  (while (not
      (progn
        (initget "N")
        (setq blk (entsel "\nSelect Block/N for Block name:"))
        (cond
          ((null blk) (prompt "\n<<Null selection>>"))
          ((eq blk "N")
           (while (not
                    (and (Setq bn (getstring "\nEnter Block Name: "))
                         (tblsearch "Block" bn)
                    )
                  )
             (princ (Strcat "\n<< " bn " Invalid block name>>"))
             
           ) T
          )
          ((setq s (car blk))
           (if (eq (cdr (Assoc 0 (entget s))) "INSERT")
             (setq bn (vla-get-EffectiveName (vlax-ename->vla-object s)))
             (prompt "\n<<Invalid Object>>")
           )
          )
        )
      )
    )
  )
  (princ (Strcat "\nBlock Name Filter: " (Strcase BN)))
  (initget  "A W")
  (setq opt (cond ((getkword
                     (strcat "\n Choose option [Window/All] <Window>: ")
                   )
                  )
                  ("W")
            )
  )
  (setq selection
         (ssget (if (eq opt "A") "_X" "_:L")
                (list '(0 . "insert")
                      (cons 2 (strcat bn ",`*U*"))
                                      )
         )
  )
(sssetfirst nil selection)
  (princ)
  )
(defun c:bls()
  (bls)
  (princ)
  )

Quote
Quicker in what way? If it happens in the blink of an eye how do you know it quicker?
That's because I can see faster than the blinking of an eye ! 8-) That's a joke of course !

Quote
Welcome to the Swamp.

Thanks ! I was in the swamp before . For years ! Now that I came back , though , my account had been terminated . But that's no problem . And the truth is i remember you ; yes , with the cab picture ! Oh , by the way , is Keith Blackie still around ? I knew him long before coming to the Swamp ; although I can't remember the name of the previous glorious site  :-( .

Any way , as far as concerning the coding :
I didn't mean "faster" as far as concerning the time needed for the code to get executed . I was referring to the number of the lines . Of course what I thing of "faster" is personal ; there was no offense to David , who afterall kindly wrote down those codes .

I also tried to work it a little myself . I managed to find out that I can set the value of a property of an entinity (specifically here the Scale X , Y and Z factor of a Block object) by this :

( setq ObjectToChange ( ssget ":S" ) )
( setq PROPSsausage ( entget ( ssname ObjectToChange 0 ) ) )    ;(retrieve the sausage as it currently is)
( setq PROPSsausage ( subst ( cons 41 0.001 ) ( assoc 41 PROPSsausage) PROPSsausage) )  ;substitute the list with the new
( setq PROPSsausage ( subst ( cons 42 0.001 ) ( assoc 42 PROPSsausage) PROPSsausage) )  ;then for Scale Y
( setq PROPSsausage ( subst ( cons 43 0.001 ) ( assoc 43 PROPSsausage) PROPSsausage) )  ;then for Scale Z
( entmod PROPSsausage)

In which 41 is the characteristic number in the list of the property (for Scale X) and 0.001 is the new value .
Now all this made me happy for making me remember some of the old Lisp ! But soon I found out that this is not enough ! ... This code only works if you specifically select a single object ... But what about when there are a dozen of such blocks that need to be changed ? Well this is hard for me . Selecting them is easy (with SSget X) , but how will I set the value to each of the block ? I thing I'll have to somehow use the foreach function . And I see that David has already used it . So I'll try to see if I can adopt it to my own code . Afterall , that's why I like programing : it's like Mathematics ; you can do the same thing through various of ways !  :-) However , any suggestion will be welcomed !

iliekater

  • Mosquito
  • Posts: 9
Re: Changing the properties of objects (of Text and Block)
« Reply #6 on: October 18, 2017, 05:09:12 PM »
I think I made it . Instead of trying to access the properties of each block (and change the properties Scale X , Y , Z)  ,  I tried accessing the block itself and scale it with AutoCAD's SCALE command !
First I select all the desired objects (this is no big deal) :
Code: [Select]
( setq BlocksOnLayerPOINT  ( ssget "X" ( list ( cons 0 "INSERT" ) ( cons 8 "POINT" ) ) ) )Then I tried the foreach function in order to scale each object based on its insertion point :
Code: [Select]
( foreach element BlocksOnLayerPOINT
    ( command "SCALE" element "" ( cdr ( assoc 10 ( entget element ) ) ) 0.5 )
    ( setq index ( + index 1 ) ) )
The problem is that the entget function needs names and not the entinities themselves .
So I tried the while function :
Code: [Select]
( setq index 0 )
( while ( < index ( sslength BlocksOnLayerPOINT ) )
    ( command "SCALE" ( ssname BlocksOnLayerPOINT index ) "" ( cdr ( assoc 10 ( entget ( ssname BlocksOnLayerPOINT index ) ) ) ) 0.5 )
    ( setq index ( + index 1 ) ) )

Finally it works !  :-)

ronjonp

  • Needs a day job
  • Posts: 7526
Re: Changing the properties of objects (of Text and Block)
« Reply #7 on: October 19, 2017, 09:06:07 AM »
I think I made it . Instead of trying to access the properties of each block (and change the properties Scale X , Y , Z)  ,  I tried accessing the block itself and scale it with AutoCAD's SCALE command !
First I select all the desired objects (this is no big deal) :
Code: [Select]
( setq BlocksOnLayerPOINT  ( ssget "X" ( list ( cons 0 "INSERT" ) ( cons 8 "POINT" ) ) ) )Then I tried the foreach function in order to scale each object based on its insertion point :
Code: [Select]
( foreach element BlocksOnLayerPOINT
    ( command "SCALE" element "" ( cdr ( assoc 10 ( entget element ) ) ) 0.5 )
    ( setq index ( + index 1 ) ) )
The problem is that the entget function needs names and not the entinities themselves .
So I tried the while function :
Code: [Select]
( setq index 0 )
( while ( < index ( sslength BlocksOnLayerPOINT ) )
    ( command "SCALE" ( ssname BlocksOnLayerPOINT index ) "" ( cdr ( assoc 10 ( entget ( ssname BlocksOnLayerPOINT index ) ) ) ) 0.5 )
    ( setq index ( + index 1 ) ) )

Finally it works !  :)
FWIW .. I'd recommend NOT using commands whenever possible. They are generally slower and can have issues between versions.

Code - Auto/Visual Lisp: [Select]
  1. (defun c:foo (/ e o s)
  2.   (if (setq s (ssget "_X" '((0 . "INSERT") (8 . "POINT"))))
  3.     (while (> (sslength s) 0)
  4.       ;; Still need to check for locked layers...
  5.       (vlax-invoke
  6.         (setq o (vlax-ename->vla-object (setq e (ssname s 0))))
  7.         'scaleentity
  8.         (vlax-get o 'insertionpoint)
  9.         0.5
  10.       )
  11.       (ssdel e s)
  12.     )
  13.   )
  14.   (princ)
  15. )

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

David Bethel

  • Swamp Rat
  • Posts: 656
Re: Changing the properties of objects (of Text and Block)
« Reply #8 on: October 19, 2017, 12:11:57 PM »
Just for kicks I searched my .lsp file and found 3,835 uses of "(ssget"

If I haven't learned to type that snippet from memory I'm ready for the loony bin !
R12 Dos - A2K