3dwannab Posted March 3, 2023 Posted March 3, 2023 I have this LISP below to select objects based on a selection set. Only trouble is, is it's a bit slow when there's a lot of objects in the drawing. I was wondering if there was a way to speed things up a bit. Cheers in advance. (defun c:QSLAYERS_SELECTED_QUICK (/ idx lay lst ss1) (princ "Filter select all on selected object/s Layer/s :\n") (if (setq ss1 (cond ((ssget "_I")) ; preselection, if any ((ssget)) ; User selection if no pre-selection ) ) (progn (repeat (setq idx (sslength ss1)) (if (not (member (setq lay (cdr (assoc 8 (entget (ssname ss1 (setq idx (1- idx))))))) lst)) (setq lst (vl-list* "," lay lst)) ) ) (setq ss1 (ssget "_X" (list (cons 8 (apply 'strcat (cdr lst)))))) (princ (strcat "\n: ------------------------------\n\t\t<<< " (itoa (sslength ss1)) (if (> (sslength ss1) 1) " <<< objects" " <<< object") " selected.\n: ------------------------------\n")) ;; (command "_.zoom" "_O" ss1 "") (sssetfirst nil ss1) (command "_.regen" "_.pselect" "_p" "") ) ) ) Quote
marko_ribar Posted March 3, 2023 Posted March 3, 2023 Do you know how to use QSELECT command... Start it, set filter of desired Layer and click for BricsCAD yellow square, and for AutoCAD OK button from dialog box... 1 Quote
3dwannab Posted March 3, 2023 Author Posted March 3, 2023 I could try write something using SELECTSIMILAR when I'm in work on Monday. Just set the option of SELECTSIMILAR to selects layers and no other properties. Will probably be much faster that way. Quote
Steven P Posted March 3, 2023 Posted March 3, 2023 So to speed up what you have you want to make the repeat loop more efficient. Just quick testing, it looks like you can just use: (setq lst (vl-list* "," (cdr (assoc 8 (entget (ssname ss1 (setq idx (1- idx)))))) lst)) taking away the 'if' line, might make it a little quicker. Also for me, I'd make the name something more snappy like QSQ - saves half a second of typing! 1 Quote
3dwannab Posted March 3, 2023 Author Posted March 3, 2023 Thanks Steven. I'll give that a shot on Monday. I've this mapped to a keyboard shortcut with Ctrl+L (Bit handier ;). I've all my Quick select lisps starting with QS then the auto fill kicks in to populate the command list. QSL.. Are all my layer functions, QSH... are hatches and so on. 1 Quote
3dwannab Posted March 6, 2023 Author Posted March 6, 2023 (edited) On 3/3/2023 at 7:31 PM, Steven P said: So to speed up what you have you want to make the repeat loop more efficient. Just quick testing, it looks like you can just use: (setq lst (vl-list* "," (cdr (assoc 8 (entget (ssname ss1 (setq idx (1- idx)))))) lst)) taking away the 'if' line, might make it a little quicker. Also for me, I'd make the name something more snappy like QSQ - saves half a second of typing! I tried that but still slow. This is in a drawing that has 18k objects. This seems to do the business, it's more or less instant. Not sure why it says "*Invalid selection*" in the command line though.... (defun c:QSLAYERS_SELECTED_QUICK (/ *error* var_cmdecho var_osmode var_selectsimilarmode ss1) (defun *error* (errmsg) (and acDoc (vla-EndUndoMark acDoc)) (and errmsg (not (wcmatch (strcase errmsg) "*CANCEL*,*EXIT*")) (princ (strcat "\n<< Error: " errmsg " >>\n")) ) (setvar 'cmdecho var_cmdecho) (setvar 'osmode var_osmode) (setvar 'selectsimilarmode var_selectsimilarmode) ) (setq acDoc (vla-get-ActiveDocument (vlax-get-acad-object))) (or (vla-EndUndoMark acDoc) (vla-StartUndoMark acDoc)) (setq var_cmdecho (getvar 'cmdecho)) (setq var_osmode (getvar 'osmode)) (setq var_selectsimilarmode (getvar 'selectsimilarmode)) (setvar 'cmdecho 0) (setvar 'osmode 0) (setvar 'selectsimilarmode 2) ; Select by layer (princ "Filter select all on selected object/s Layer/s :\n") (setq ss1 (cond ((ssget "_I")) ; preselection, if any ((vl-cmdf "_.selectsimilar" pause)) ; User selection if no pre-selection ) ) (if ss1 (vl-cmdf "_.selectsimilar" "")) ;; If the ss1 variable is a selection set (*error* nil) (princ) ) ; (c:QSLAYERS_SELECTED_QUICK) Edited March 6, 2023 by 3dwannab 1 Quote
Steven P Posted March 6, 2023 Posted March 6, 2023 Not sure how to put this in here yet, just an idea, and no clue if it would work Very quick testing and it didn't have Invalid Selection, was thinking try to do the selection with an ssget like you had above, and see what happens.. needs a loop in the selectsimilar line for a selection set to work here (setq MyEnt1 (car (entsel))) (setq MyEnt2 (car (entsel))) (setq ss1 (vl-cmdf "_.selectsimilar" MyEnt1 MyEnt2 "")) Quote
3dwannab Posted March 7, 2023 Author Posted March 7, 2023 This is working for me. (defun c:QSLAYERS_SELECTED_QUICK (/ *error* var_cmdecho var_osmode var_selectsimilarmode ss1) (defun *error* (errmsg) (and acDoc (vla-EndUndoMark acDoc)) (and errmsg (not (wcmatch (strcase errmsg) "*CANCEL*,*EXIT*")) (princ (strcat "\n<< Error: " errmsg " >>\n")) ) (setvar 'cmdecho var_cmdecho) (setvar 'osmode var_osmode) (setvar 'selectsimilarmode var_selectsimilarmode) ) (setq acDoc (vla-get-ActiveDocument (vlax-get-acad-object))) (or (vla-EndUndoMark acDoc) (vla-StartUndoMark acDoc)) (setq var_cmdecho (getvar 'cmdecho)) (setq var_osmode (getvar 'osmode)) (setq var_selectsimilarmode (getvar 'selectsimilarmode)) (setvar 'cmdecho 0) (setvar 'osmode 0) (setvar 'selectsimilarmode 2) ; Select by layer (princ "Filter select all on selected object/s Layer/s :\n") (setq ss1 (ssget "_I")) (if ss1 (vl-cmdf "_.selectsimilar") (vl-cmdf "_.selectsimilar" pause) ) (*error* nil) (princ) ) 1 Quote
3dwannab Posted March 9, 2023 Author Posted March 9, 2023 Mmmh, I thought this was working but setting the selectsimilarmode variable to 2 isn't selecting layers. Even when issuing the command after changing the variable. Attached is a sample drawing. Just select either of the dims which are both in the same layer and the selectsimilar command won't work. Two Different Dim Types.dwg Quote
Tsuky Posted March 9, 2023 Posted March 9, 2023 And in this form, would it suit you? (defun c:dyn_filter ( / ss n lst_lay lst_typ dxf_ent lay typ m_filt) (cond ((setq ss (cond ((ssget "_I")) ((ssget)) ) ) (setq lst_lay "" lst_typ "") (repeat (setq n (sslength ss)) (setq dxf_ent (entget (ssname ss (setq n (1- n))))) (if (not (vl-string-search (setq lay (cdr (assoc 8 dxf_ent))) lst_lay)) (setq lst_lay (strcat lay "," lst_lay)) ) (if (not (vl-string-search (setq typ (cdr (assoc 0 dxf_ent))) lst_typ)) (setq lst_typ (strcat typ "," lst_typ)) ) ) (setq m_filt (list (cons 0 lst_typ) (cons 8 lst_lay) (cons 67 (if (= 1 (getvar "CVPORT")) 1 0)) (cons 410 (getvar "CTAB")) ) ) (if (zerop (getvar "PICKFIRST")) (setvar "PICKFIRST" 1)) (sssetfirst nil nil) (setq ss (ssget "_X" m_filt)) (princ (strcat "\n" (itoa (sslength ss)) " selected similar objects.")) (sssetfirst nil ss) ) (T (princ "\nNo selection")) ) (prin1) ) Quote
3dwannab Posted March 10, 2023 Author Posted March 10, 2023 Thanks @Tsuky, much faster. I've taken out type. (defun c:dyn_filter (/ ss n lst_lay dxf_ent lay typ m_filt) (cond ((setq ss (cond ((ssget "_I")) ((ssget)) ) ) (setq lst_lay "") (repeat (setq n (sslength ss)) (setq dxf_ent (entget (ssname ss (setq n (1- n))))) (if (not (vl-string-search (setq lay (cdr (assoc 8 dxf_ent))) lst_lay)) (setq lst_lay (strcat lay "," lst_lay)) ) ) (setq m_filt (list (cons 8 lst_lay) (cons 67 (if (= 1 (getvar "CVPORT")) 1 0)) (cons 410 (getvar "CTAB")) ) ) (if (zerop (getvar "PICKFIRST")) (setvar "PICKFIRST" 1)) (sssetfirst nil nil) (setq ss (ssget "_X" m_filt)) (princ (strcat "\n" (itoa (sslength ss)) " selected similar objects.")) (sssetfirst nil ss) ) (T (princ "\nNo selection")) ) (prin1) ) Quote
3dwannab Posted March 10, 2023 Author Posted March 10, 2023 I've just found what was slowing it down from my original post. This line. (command "_.regen" "_.pselect" "_p" "") Taking this out is fast now. But I've had issues with the grips not showing which is why I've added this in the first place. Quote
barristann Posted March 11, 2023 Posted March 11, 2023 Is it possible to modify this to select Blocks? Thank you. Quote
BIGAL Posted March 11, 2023 Posted March 11, 2023 Just look up help about ssget filters examples (ssget '((0 . "INSERT"))) (ssget '((0 . "LWPOLYLINE"))) (ssget '((0 . "LWPOLYLINE")(8 . "Mylayer")) 1 Quote
3dwannab Posted March 14, 2023 Author Posted March 14, 2023 (edited) On 3/11/2023 at 6:49 PM, barristann said: Is it possible to modify this to select Blocks? Thank you. Here's a mod of something LeeMac originally wrote. (vl-load-com) ;; ;; Select Blocks by same name ;; Updated by 3dwannab on 2022.03.30. ;; ;; I updated this on the 2022.03.30 to use the SELECTSIMILAR command by setting ;; the SELECTSIMILARMODE to 128 which is to select similar by name. ;; Along with a filter for the selection of blocks, after this it's pretty simple. ;; ;; Initial code was here by Lee Mac: http://www.theswamp.org/index.php?topic=49667.msg548516#msg548516 ;; (defun c:QSBlocks_Same (/ *error* acDoc def lst ss1 ss2 var_cmdecho var_osmode var_selectsimilarmode) (princ "Filter select all similar Blocks by name :\n") (defun *error* (errmsg) (and acDoc (vla-EndUndoMark acDoc)) (and errmsg (not (wcmatch (strcase errmsg) "*CANCEL*,*EXIT*")) (princ (strcat "\n<< Error: " errmsg " >>\n")) ) (setvar 'cmdecho var_cmdecho) (setvar 'osmode var_osmode) (setvar 'selectsimilarmode var_selectsimilarmode) ) (setq acDoc (vla-get-ActiveDocument (vlax-get-acad-object))) (or (vla-EndUndoMark acDoc) (vla-StartUndoMark acDoc)) (setq var_cmdecho (getvar 'cmdecho)) (setq var_osmode (getvar 'osmode)) (setq var_selectsimilarmode (getvar 'selectsimilarmode)) (setvar 'cmdecho 0) (setvar 'osmode 0) ; Code by Lee Mac http://www.cadtutor.net/forum/showthread.php?92638-Simple-fix-%28LISP-noob%29-Syntax-problem&p=633824&viewfull=1#post633824 ;; Iterate over the block table and compile a list of xref blocks to exclude (while (setq def (tblnext "block" (not def))) (if (= 4 (logand 4 (cdr (assoc 70 def)))) (setq lst (vl-list* "," (cdr (assoc 2 def)) lst)) ) ) ;; Attempt to retrieve a selection of blocks (but not xrefs) (setq ss1 (ssget (cons '(0 . "INSERT") (if lst (vl-list* '(-4 . "<NOT") (cons 2 (apply 'strcat (cdr lst))) '((-4 . "NOT>"))))))) ;; Set selectsimilarmode to use the name of an object. (setvar 'selectsimilarmode 128) ;; If ss1 one is valid then do this (if ss1 (progn (vl-cmdf "_.selectsimilar" ss1 "") (setq ss2 (ssget)) ;; Create a new selection set for to zoom and reselect as the zoom objects will do this ;; (command "_.zoom" "_O" ss2 "") (sssetfirst nil ss2) (command "_.regen") (princ (strcat "\n: ------------------------------\n\t\t<<< " (itoa (sslength ss2)) (if (> (sslength ss2) 1) " <<< INSERTS objects" " <<< INSERT object") " selected\n: ------------------------------\n")) ) (princ "\n: ------------------------------\n\t\t*** Nothing selected ***\n: ------------------------------\n") ) (*error* nil) (princ) ) Edited March 14, 2023 by 3dwannab Added (vl-load-com) 1 Quote
barristann Posted March 15, 2023 Posted March 15, 2023 3dwannab, I've tested this today several times and it works 100%. You have amazing skills sir! Thank you 3dwannab and Lee Mac for saving my job! 1 Quote
Recommended Posts
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.