Jump to content

Filter By Multileader Style


ksperopoulos

Recommended Posts

I can't find a dxf code for mleaders that specifies the name of the mleader style being used. I am trying to find all mleaders in my drawing with a particular style. If I use (entget (car (entsel))), there is nothing listed. Could someone point me in the right direction of where to find this information please?

Link to comment
Share on other sites

  • Replies 39
  • Created
  • Last Reply

Top Posters In This Topic

  • cwake

    21

  • ksperopoulos

    16

  • Lee Mac

    2

  • hmsilva

    1

To make a selection set of multileaders of a certain style using vanilla LISP you could use the dictionary approach...

 

(defun mleadersel ( style / a b dict )
 (if (and (setq dict (dictsearch (namedobjdict) "ACAD_MLEADERSTYLE"))
          (setq dict (dictsearch (cdr (assoc -1 dict)) style))
          (setq dict (member '(102 . "{ACAD_REACTORS") dict))
          )
   (while (/= (caar (setq dict (cdr dict))) 102)
     (if (= (cdr (assoc 0 (entget (setq a (cdar dict))))) "MULTILEADER")
       (setq b (cons a b))
       )
     )
   )
 b
 )

(Which to be specific returns a list of entity names, not a selection set. But you could modify it to return a selection set)

 

Alternatively you could make a selection set of all MULTILEADERS and filtering them yourself by processing them all, comparing their stylename (obtained using the VisualLISP approach as Henrique suggests) to the stylename you are looking for.

Link to comment
Share on other sites

Good code cwake, innovative solution :thumbsup:

 

Perhaps another way to write it:

(defun mleadersel ( mls / dic )
   (if (setq dic (dictsearch (namedobjdict) "acad_mleaderstyle"))
       (vl-remove-if-not '(lambda ( x ) (= "MULTILEADER" (cdr (assoc 0 (entget x)))))
           (mapcar 'cdr
               (cdr
                   (member '(102 . "}")
                       (reverse
                           (cdr
                               (member '(102 . "{ACAD_REACTORS")
                                   (dictsearch (cdr (assoc -1 dic)) mls)
                               )
                           )
                       )
                   )
               )
           )
       )
   )
)

Link to comment
Share on other sites

Thanks Lee.

 

I did think about cutting out the bottom codes like you have with the reverse / member approach... it wasn't until I saw how you had written your code that I wondered if doing so might offer a speed advantage?... Especially if you have a large number of multileaders, as mine repeatedly performs the cdr with every 330 code present. I can't help but feel a little childishly "academic" about doing so, especially after seeing the results... but since I'm trying to improve in this "art" - I tested them with benchmark LOL.

 

I won't post anything, because the results varied under different circumstances, i.e. number of multileaders, whether the session of autocad was new or old...

In the end, I would say that trimming off the codes by using reverse / member like you did in yours was more frequently quicker, so next time I think I will use that approach. But the difference between the two was never more than 3%, which is why I'm amused by my academic curiosity. :roll: LOL. Now off to work in the real world. :cry:

Link to comment
Share on other sites

Since we're being academic, I suppose my approach would be considered a form of functional programming, whereas your method errs towards imperative programming. I doubt that there is much difference in the performance of each code since both methods are already reasonably efficient, but thank you for taking the time to run some tests.

 

My post wasn't really suggesting a 'better' method, just having some fun with the code :)

Link to comment
Share on other sites

I've never been trained in programming as such, but I'm curious as to what those terms mean in practice (still being academic - sigh). I have noticed, for example, that a lot of your code will introduce a lamda function rather than creating another variable with setq. And lately I find myself mimicking that, without necessarily knowing if there is an advantage. Likewise once I discovered that you can feed a recursive lambda function into another lambda function as an argument, I've been doing that more as well. If you have any links or information explaining those terms or methods, or even where each is best applied I'd love to learn more. Perhaps a PM if it would hijack this thread too much? But only if you have the time. I can always do a little research myself.

Link to comment
Share on other sites

Actually, don't worry about the terms Lee. I've found enough information to get a grasp of what you are talking about. And I tend to agree, that I do err toward imperative. I can think of several reasons for why that is so. I am noticing, however, that my coding approach has been evolving over the last couple of months, especially for some tasks. I think it's too early for me to say that the shift is toward functional programming, but I do sometimes look back on code I wrote a couple of years ago and chuckle. :lol:

Link to comment
Share on other sites

cwake - here is the description straight from the birds mouth.

 

As far as filtering the mleaders, it seems like I am bouncing around with my code. I am getting a selection set of all mleaders in the drawing. Then I want to only get the mleaders that are a part of a particular mleader style. Am I wrong in doing something like this or is there a better way?

 

(setq ss1 (ssget "x" '((0 . "MULTILEADER")))
       ent (ssname ss1 0)
       obj (vlax-ename->vla-object ent)
       mls (vlax-get-property obj 'StyleName)
        lst (vl-string->list mls)
)
(if (member <[i]My Multileader Style Name[/i]>  lst)....

Link to comment
Share on other sites

You would need to do something like this Kyle. In posting this, I am amused by the fact that this code couldn't be any more imperative if I tried. LOL. I have a couple of ideas to play with in constructing the selection set differently, but I'd rather post something to answer your question first then just play for my "academic curiosity".

 

(defun mleadersel ( style / ent mldrs ss1 sscnt )
 (if (setq ss1 (ssget "X" '((0 . "MULTILEADER"))))
   (progn
     (setq mldrs (ssadd))
     (repeat (setq sscnt (sslength ss1))
       (if (= (vla-get-stylename (vlax-ename->vla-object (setq ent (ssname ss1 (setq sscnt (1- sscnt)))))) style)
         (ssadd ent mldrs)
         )
       )
     (if (< 0 (sslength mldrs)) mldrs)
     )
   )
 )

 

As for the link to Lee's tutorial, thanks for that. I'm familiar with the more generic uses of mapcar and lambda like that, especially when lists are involved. But sometimes Lee will apply lambda in ways I've never seen or heard of before, and sometimes it appears that he uses lambda to avoid introducing another variable. I like it, and I'm using that kind of approach more. Like I said above, I especially like the recursive lambda function trick. That has heaps of potential.

Edited by cwake
Link to comment
Share on other sites

Thank you Clint. Whether your code is "academic", "functional", or "imperative" - at least it is something in the category of "good". Mine is just embarrassing and rarely works!!!

 

I have a question about the code above. You have an argument named style. Should I replace that with my mleader style name? I ran everything up to that point. The vla-get-stylename returns the value of every style there is in ss1. Since you are checking to see if the returned value is equal to something, I would have to replace STYLE with my mleader style right? After that, it will add it to a new selection set named mldrs.

 

(I know you know what this is doing, but I want to make sure I understand it as well.)

 

Thanks again.

Link to comment
Share on other sites

Exactly right, Kyle. vla-get-stylename returns a text string. Then the = function compares it to the supplied string (the style name you want), and if it matches the rest makes a selection set. I wrote it in the form of a sub function with an argument which you could copy like massoc if you want, but because it is not recursive like massoc, you could always take away the defun and place it in the body of your main function. Just feed it the multileader style where it has "style" (and add the same variables to your list of localised variables that I did).

Link to comment
Share on other sites

Oh!! And if you did that, you would take away the last if statement as well. The only reason that is there is so the function returned nil if no multileaders in the drawing matched.

Link to comment
Share on other sites

What about the variable "sscnt"? Since you are decrementing this variable, if I need to use (sslength mldrs) later in the code, does it need to be reestablished by setting this function to another variable? I am trying to look for a particular mleader style and then get the attributes from each mleader and place them in a table (which is part of another thread located here).

Link to comment
Share on other sites

Just re-read your last comment Kyle. I really like that you want to code, and want to learn. Like I do. It's very rewarding when the code you write saves you time and gives you the results you want... it makes all the effort worthwhile.

Link to comment
Share on other sites

I'm confused. The comment about getting the attributes from a particular mleader style or about reestablishing the variable for sslength?

Link to comment
Share on other sites

I was about to answer, but it's almost reached a point where posting your whole code to date might help to see your question in context. The role that variable is playing is to work systematically through the selection set from the last entity to the first. Once completed, it will be 0 and of no real use for anything. You could certainly reuse that variable later in your routine as a counter for populating your table. But I guess the key is to know that it's value is the integer 0 once the repeat has finished.

Link to comment
Share on other sites

Sorry, I'm doing this on the phone. Takes a while to type. I was referring to the comments in #11. But certainly post what you have if my last comment doesn't help, then I can see everything in context.

Link to comment
Share on other sites

Here is the code Clint. The selection set ss1 in this code is looking for all mleaders (no matter what style). It then finds out how many mleaders there are, stepping through them one at a time and returning their block's attribute value. I am using this value to put in a table, but the only value I am getting to go into the table is the last returned value. Like I mentioned in my post #11, my code is typically embarrassing and does not work.

 

(defun c:WMT ( / *error* ss1 int dec ename att ots doc ps pt numr numc rowht colwd tbl cell)
 (defun *error* (msg)
   (if (not (member msg '("Function cancelled" "quit / exit abort")))
       (princ (strcat "\nError: " msg))
   )
   (princ)
 )
 (defun massoc ( key lst / item )
   (if (setq item (assoc key lst))
       (cons (cdr item) (massoc key (cdr (member item lst))))
   )
 )
 (if (setq ss1 (ssget "x" '((0 . "MULTILEADER"))))
   (progn
     (setq int (sslength ss1)
           dec (1- int)
     )
     (while (<= 0 dec)
       (setq ename (ssname ss1 dec)
               att (nth 1 (massoc 302 (entget ename)))
               dec (1- dec)
       )
       (print att)
     )
   )
 )
 (vl-load-com)
 (setq ots (getvar "ctablestyle"))
 (setvar "ctablestyle" "MMC-Weld Map Table")
 (setq doc (vla-get-activedocument (vlax-get-acad-object))
        ps (vla-get-paperspace doc)
        pt (vlax-3d-point '(15.0 10.5 0.0))
      numr (+ 2 int)
      numc 2
     rowht 0.25
     colwd 0.75
       tbl (vla-addtable ps pt numr numc rowht colwd)
      cell 2
 )
 (repeat int
   (vla-settext tbl 0 0 "WELD MAP TABLE")
   (vla-settext tbl 1 0 "WELD ID")
   (vla-settext tbl 1 1 "WELDER")
   (vla-settext tbl cell 0 att)
   (setq cell (+ cell 1))
 )
 (setvar "ctablestyle" ots)
 (princ)
)

Link to comment
Share on other sites

Darn!! Now I have to get up and go to the computer!! Lol. It's early morning here in Australia and that's why I'm on my back with the phone. I'll start looking at it now and get back to you

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...