Iterate Code By Element Type

Iterate Code By Element Type

ebsoares
Collaborator Collaborator
1,071 Views
8 Replies
Message 1 of 9

Iterate Code By Element Type

ebsoares
Collaborator
Collaborator

Hi, everyone.

 

Would like to learn how to iterate through types of selected elements with Lisp code.

 

Suppose we've got a selection set containing blocks, texts, and mleaders. Now how would we write code to do this:

(selection set with blocks, texts, and mleaders)
    (go through both blocks and texts)
        (do this with blocks and texts)
    (go through mleaders)
        (do this with mleaders)

 

Any help would be greatly appreciated!

 

Thanks,

 

Edgar

0 Likes
Accepted solutions (2)
1,072 Views
8 Replies
Replies (8)
Message 2 of 9

Ranjit_Singh
Advisor
Advisor

@ebsoares wrote:

Hi, everyone.

 

Would like to learn how to iterate through types of selected elements with Lisp code.

 

Suppose we've got a selection set containing blocks, texts, and mleaders. Now how would we write code to do this:

(selection set with blocks, texts, and mleaders)
    (go through both blocks and texts)
        (do this with blocks and texts)
    (go through mleaders)
        (do this with mleaders)

 

Any help would be greatly appreciated!

 

Thanks,

 

Edgar


There are probably many ways. Use repeat, while, foreach (ssnamex will convert selection set to list) etc. Cond is another option

(cond 
((= (cdr (assoc 0 (entget ent))) "MULTILEADER") (. . process multileaders. .)) (t (. .for everything else do this. . .)))

ent is the subject entity in selection set and I assumed that you have no other type of entity (except mleader, insert and text) in there. If you are unsure, then add one more test block in the cond to test for insert/text and then add a t to catch everything else

 

Message 3 of 9

ebsoares
Collaborator
Collaborator

Hi, Ranjit. Thanks coming to the rescue again 🙂

 

I've used the cond code you mentioned (I like those), but it doesn't work - it goes as far as asking for the angle, but then it give me an error message: "; error: bad argument type: lentityp nil".

 

Here's the code I have - the blue is from the code you wrote, the red is what I'm trying to do each time:

 

(defun c:RotMultBase ( / ss ang )
    (vl-load-com)    ; start VLisp
    (setq ss (ssget "_:L" '((0 . "Insert,Text,MText,MultiLeader"))))

    ; Main code
    (setq ang (getangle "\nSpecify Rotation Angle: ")) ; allows for 2-point cursor input
    (cond 
        ((= (cdr (assoc 0 (entget ent))) "MultiLeader") ; isolate multileaders and do the following:
            (mapcar '(lambda (x) (setpropertyvalue x "MText/Rotation" (+ (getpropertyvalue x "MText/Rotation") ang)))
                (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))
            )
        )
        (t ; for the rest (Insert,Text,MText), do this:
            (
                (lambda ( i / e o )
                    (while (setq e (ssname ss (setq i (1+ i))))
                        (vla-put-rotation (setq o (vlax-ename->vla-object e))
                            (+ (vla-get-rotation o) ang)
                        )
                    )
                )
                -1
            )
        )
    )
    (princ)
)

 

 

 

Each code works individually - the one you made (and dbroad) and the one that rotates blocks, texts, and mtexts (from Lee Mac). I'd just like to have them in a single set of code...

 

Any chance you can spot where I made a mistake?

 

Edgar

0 Likes
Message 4 of 9

Ranjit_Singh
Advisor
Advisor

You are processing the selection sets twice in each block in cond and also ent is not defined. Plus there are other issues. See if you can use this. I have not tested.

(defun c:rotmultbase  (/ ent ss ang i)
 (setq ang (getangle "\nSpecify Rotation Angle: ")
       ss  (ssget "_:L"
                  '((0 . "insert,text,mtext,multileader")))
       i   -1)
 (while (setq ent (ssname ss (setq i (1+ i))))
  (cond ((= (cdr (assoc 0 (entget ent)))
            "MULTILEADER")
         (setpropertyvalue ent
                           "MText/Rotation"
                           (+ (getpropertyvalue ent "MText/Rotation")
                              ang)))
        (t
         (setpropertyvalue ent
                           "Rotation"
                           (+ (getpropertyvalue ent "Rotation")
                              ang)))))
 (princ))
0 Likes
Message 5 of 9

ebsoares
Collaborator
Collaborator

Thanks for that, Ranjit.

 

For some reason, it only worked with blocks, but it ignored the others in the selection set, and gave me an erro message: "; error: ADS request error".

 

Also, this iteration does not work with existing selections, like the previous codes - If there's anything selected, it deselects them, then asks for an angle input, then asks for a brand new selection.

 

 

0 Likes
Message 6 of 9

Kent1Cooper
Consultant
Consultant
Accepted solution

You could try something like this:

 

    (setq ss (ssget "_:L" '((0 . "Insert,Text,MText,MultiLeader")))); from yours

    (setq ssML (ssget "_P" '((0 . "MultiLeader")))); separate set of just the MLeaders from the full set [Previous selection]

    (sssetfirst nil ss); re-establishes full ss as "Previous" for next (ssget)

    (command "_.regen"); un-highlights [may be expendable, depending on what you do subsequently]

    (setq ssBT (ssget "_P" '((0 . "Insert,Text,MText")))); separate set of just the Blocks/Text

 

Then you have each category in its own separate selection set that you can process in its own way.

Kent Cooper, AIA
Message 7 of 9

Ranjit_Singh
Advisor
Advisor
Accepted solution

@ebsoares wrote:

Also, this iteration does not work with existing selections, like the previous codes  


I accidentally reversed the order of setq for ang and ssget. See if reversing it helps.

(defun c:rotmultbase  (/ ent ss ang i)
 (setq  ss  (ssget "_:L"
                  '((0 . "insert,text,mtext,multileader")))
        ang (getangle "\nSpecify Rotation Angle: ")
        i   -1)
 (while (setq ent (ssname ss (setq i (1+ i))))
  (cond ((= (cdr (assoc 0 (entget ent)))
            "MULTILEADER")
         (setpropertyvalue ent
                           "MText/Rotation"
                           (+ (getpropertyvalue ent "MText/Rotation")
                              ang)))
        (t
         (setpropertyvalue ent
                           "Rotation"
                           (+ (getpropertyvalue ent "Rotation")
                              ang)))))
 (princ))
Message 8 of 9

ebsoares
Collaborator
Collaborator

Wow, thanks for the explanation, Kent!

 

I ended up using Ranjit's code (thanks again, Ranjit!), but yours already gave me some ideas for new ones.

 

And I eally appreciate you taking the time to explain the code - that's priceless Smiley Happy

 

Edgar

0 Likes
Message 9 of 9

ebsoares
Collaborator
Collaborator

Ranjit, your code works fantastically - everything is just as expected!

 

Really appreciate you giving off your time to help me on this Smiley Happy

 

Edgar

 

0 Likes