Need a lisp routine that deletes all layers with the word NODE in them...

Need a lisp routine that deletes all layers with the word NODE in them...

Evan_NewmanD62FQ
Observer Observer
413 Views
14 Replies
Message 1 of 15

Need a lisp routine that deletes all layers with the word NODE in them...

Evan_NewmanD62FQ
Observer
Observer

Just as the title implies. I'm working on a larger routine that converts surveys to our company standard. The surveys we get have a million NODE layers. Normally LAYDEL would be the way to go, but I need this to happen within the routine I'm making. It would be cool if it could just find layers with that word, but if I need to plug all the specific layers into the routine, that's fine too, as I have them all in an excel file and can paste them. I just don't know how to write it. Thanks.

0 Likes
414 Views
14 Replies
Replies (14)
Message 2 of 15

pendean
Community Legend
Community Legend
0 Likes
Message 3 of 15

BlackBox_
Advisor
Advisor

Here's one way of doing it; you just need to decide if you want to supply an explicit search string, or modify this to work with WCMATCH:

 

(defun _DeleteLayers (pattern / *error* acDoc oLayers deleteLayers
                     layerNames ss)

  ;; Example: (_DeleteLayers "NODE")
  (defun *error* (msg)
    (if ss (vla-delete ss))
    (if acDoc (vla-endundomark acDoc))
    (cond ((not msg))                                                   ; Normal exit
          ((member msg '("Function cancelled" "quit / exit abort")))    ; <esc> or (quit)
          ((princ (strcat "\n** Error: " msg " ** ")))                  ; Fatal error, display it
    )
    (princ)
  )

  (setq pattern (strcase pattern))
  (setq oLayers
         (vla-get-layers
           (setq acDoc
                  (vla-get-activedocument (vlax-get-acad-object))
           )
         )
  )
  (vlax-for x oLayers
    (if (vl-string-search
          pattern
          (strcase (setq layerName (vla-get-name x)))
        )
      (progn
        (setq deleteLayers (cons x deleteLayers))
        (setq layerNames (cons layerName layerNames))
        (vla-put-lock x :vlax-false)
      )
    )
  )
  (if
    (ssget "_x"
           (list
             (cons
               8
               (vl-string-right-trim
                 ","
                 (apply
                   'strcat
                   (mapcar
                     (function
                       (lambda (s) (strcat s ","))
                     )
                     layerNames
                   )
                 )
               )
             )
           )
    )
     (progn
       (vla-startundomark acDoc)
       (vlax-for x (setq ss (vla-get-activeselectionset acDoc))
         (vla-delete x)
       )
     )
  )
;;  (foreach layer deleteLayers (vla-delete layer))
  (foreach layer deleteLayers
    (if (vl-catch-all-error-p
          (vl-catch-all-apply
            'vla-delete
            (list layer)
          )
        )
      (prompt (strcat "\n >> Unable to delete \""
                      (vla-get-name layer)
                      "\" \n"
              )
      )
    )
  )

  (*error* nil)
)

 


"How we think determines what we do, and what we do determines what we get."

Sincpac C3D ~ Autodesk Exchange Apps

0 Likes
Message 4 of 15

Evan_NewmanD62FQ
Observer
Observer

This makes sense but I'm having trouble getting it to run. I don't know how to 'activate' it without defun c: (my lisp knowledge is limited)

0 Likes
Message 5 of 15

Evan_NewmanD62FQ
Observer
Observer

I like what he's got here, but it has two issues. You have to manually input V-NODE as the prefix during the command, so it's not automated. And it's not deleting nested layers, that are inside of a block.

 

(defun delbylayer (layname / *error* adoc umark sset sslen)
  ; Loads the vl library
  (vl-load-com)

  ; Define error handler function
  (defun *error* (msg)
    ; Undo previous changes if there is an error
    (if umark (progn (vla-endundomark adoc)(setq umark nil)))
    ; If the error is 'Function cancelled' or 'quit / exit abort', do nothing
    (if (or (= msg "Function cancelled")(= msg "quit / exit abort"))
      (princ)
      ; Otherwise, print the error message
      (princ (strcat "\nError: " msg))
    )
  )

  ; Get the active AutoCAD document
  (setq adoc (vla-get-activedocument (vlax-get-acad-object)))

  ; Execute different actions depending on whether a selection set is returned or not
  (cond
    ( (setq sset (ssget "_X" (list (cons 8 layname))))
      ; Set current layer to "0" and start an undo mark
      (setvar 'clayer "0")
      (progn (vla-startundomark adoc)(setq umark T))

      ; Delete all the entities on the specified layer and get the count of the deleted entities
      (setq sslen
        (length
          (mapcar
            'entdel
            (setq sslst
              (vl-remove-if
                'listp
                (mapcar 'cadr (ssnamex sset))
              )
            )
          )
        )
      )

      ; End the undo mark and print the count of deleted entities
      (progn (vla-endundomark adoc)(setq umark nil))
      ;(princ (strcat "\nErased " (itoa sslen) " items."))
    )

  )
  ; Return nil
  (princ)
)

(defun c:dellaysbyprefix ( / lay lays prefix )
  ; Loads the vl library
  (vl-load-com)

  ; Get the active AutoCAD document
  (setq adoc (vla-get-activedocument (vlax-get-acad-object)))

  ; Loop through all layers in the drawing and store their names in a list
  (while (setq lay (tblnext "LAYER" (not lay)))
    (setq lays (cons (cdr (assoc 2 lay)) lays))
  )

  ; Prompt user to input the prefix of layers to be removed
  (setq prefix (strcase (getstring "\nSpecify prefix of layers to remove from DWG : ")))

  ; Loop through the list of layer names and delete all layers that start with the specified prefix
  (foreach lay lays
    (if (wcmatch (strcase lay) (strcat prefix "*"))
      (progn
        ; Print the name of the layer being deleted and call the 'delbylayer' function to delete the layer's contents
        (princ "\n")
        (princ lay)
        (delbylayer lay)
      )
    )
  )
  (vla-purgeall adoc)
  ; Return nil
  (princ)
)

 

0 Likes
Message 6 of 15

BlackBox_
Advisor
Advisor

@Evan_NewmanD62FQ wrote:

This makes sense but I'm having trouble getting it to run. I don't know how to 'activate' it without defun c: (my lisp knowledge is limited)


With the function I posted above loaded, this should do the trick: 

 

(defun c:DeleteNodeLayers ()
  (_DeleteLayers "NODE")
  (princ)
)

 


"How we think determines what we do, and what we do determines what we get."

Sincpac C3D ~ Autodesk Exchange Apps

Message 7 of 15

Kent1Cooper
Consultant
Consultant

It seems to me this can be a lot simpler, unless I misunderstand.  This will take out Layers containing NODE [not case-sensitive] anywhere in their name, unlike @pendean 's link that [from the URL it looks like] will only remove those that start with the designated string.  Minimally tested.

(defun C:NoNodeLayers (/ layername)
  (command "_.layer" "_thaw" "0" "_set" "0" "")
  (while (setq layername (cdr (assoc 2 (tblnext "Layer" (not layername)))))
    (if (wcmatch (strcase layername) "*NODE*")
      (command "_.laydel" "_name" layername "" "_yes")
    ); if
  ); while
  (prin1)
)

You should be able to just remove the first and last lines and stick it inside the routine you're making, if in an appropriate place.  I would add layername to the localized variables list in that routine.

Kent Cooper, AIA
0 Likes
Message 8 of 15

evannB2AWD
Enthusiast
Enthusiast

this actually did exactly what I was hoping for. Is there a way to do it and suppress the command window? Petty ask, considering the command works. But throughout the life of it the command line flashes a few hundred times. Thank you either way though!

0 Likes
Message 9 of 15

BlackBox_
Advisor
Advisor

 


@Kent1Cooper wrote:

It seems to me this can be a lot simpler, unless I misunderstand.  This will take out Layers containing NODE [not case-sensitive] anywhere in their name, unlike @pendean 's link that [from the URL it looks like] will only remove those that start with the designated string.  Minimally tested.

(defun C:NoNodeLayers (/ layername)
  (command "_.layer" "_thaw" "0" "_set" "0" "")
  (while (setq layername (cdr (assoc 2 (tblnext "Layer" (not layername)))))
    (if (wcmatch (strcase layername) "*NODE*")
      (command "_.laydel" "_name" layername "" "_yes")
    ); if
  ); while
  (prin1)
)

You should be able to just remove the first and last lines and stick it inside the routine you're making, if in an appropriate place.  I would add layername to the localized variables list in that routine.


@Kent1Cooper your approach is definitely simpler, but does repeat the LAYDEL Command. 

 

The OP was obviously exaggerating, but they stated 'The surveys we get have a million NODE layers.' so we posted solutions that are faster than repeated Command calls. 

 

A LISP that uses ent* functions, which are LispFunctions written in ARX, would be much faster than ActiveX particularly for large data sets. 

 

[Edit] - You may also want to unlock all layers before attempting the LAYDEL calls. 

 

Cheers

 


"How we think determines what we do, and what we do determines what we get."

Sincpac C3D ~ Autodesk Exchange Apps

0 Likes
Message 10 of 15

Sea-Haven
Mentor
Mentor

Re, run on load rather than type command just add what ever your defun name is as last line eg (C:NoNodeLayers) this will call the defun. can have C: or not as defun name.

 

0 Likes
Message 11 of 15

Kent1Cooper
Consultant
Consultant

@evannB2AWD wrote:

.... Is there a way to do it and suppress the command window? ....


Look into the CMDECHO System Variable.  Save the initial value, set, run stuff, reset as with the others.

Kent Cooper, AIA
0 Likes
Message 12 of 15

komondormrex
Mentor
Mentor

@Evan_NewmanD62FQ

ccheck this one, a function thou. 

(defun del_layers_masked (source_layers_mask / active_layer_name layers_filtered)
  (setvar 'cmdecho 0)
  (setq active_layer_name (vla-get-name (vla-get-activelayer (vla-get-activedocument (vlax-get-acad-object)))))
  (vlax-map-collection (vla-get-layers (vla-get-activedocument (vlax-get-acad-object)))
    '(lambda (layer) (if (and (wcmatch (strcase (setq layer_name (vla-get-name layer))) (strcase source_layers_mask))
                (zerop (vlax-get layer 'lock))
                (not (equal layer active_layer_name))
             )
               (setq layers_filtered (append layers_filtered (list layer_name)))
              )
     )
  )
  (if layers_filtered
  (progn
      (command "_-laydel")
      (foreach layer_name layers_filtered (command "_na" layer_name))
      (command "" "_y")
  )
  (alert "None layers selected to delete")
  )
  (setvar 'cmdecho 1)
  (princ)
)

to run it load it and type like 

(del_layers_masked "*node*, *someting*, *else*, *etc*")

in the command line and hit <Enter>

0 Likes
Message 13 of 15

evannB2AWD
Enthusiast
Enthusiast

I like this. But is there a way for me to add this action to a larger routine that does a couple of other things as well? The end result is a command that includes 

(del_layers_masked "*NODE*,*MATC*,*NPLT*,*V-ANNO"). As it is, it works really well standalone.

0 Likes
Message 14 of 15

BlackBox_
Advisor
Advisor

@evannB2AWD wrote:

I like this. But is there a way for me to add this action to a larger routine that does a couple of other things as well? The end result is a command that includes 

(del_layers_masked "*NODE*,*MATC*,*NPLT*,*V-ANNO"). As it is, it works really well standalone.


I previously gave you a sub-function to do exactly that:

 

Example: (_DeleteLayers "*NODE*,*MATC*,*NPLT*,*V-ANNO")

 

https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/need-a-lisp-routine-that-deletes-all...

 

This works with active drawing, and can easily be modified to support ObjectDBX for batch processing.


"How we think determines what we do, and what we do determines what we get."

Sincpac C3D ~ Autodesk Exchange Apps

0 Likes
Message 15 of 15

komondormrex
Mentor
Mentor

as it is a function, you for sure could use it inside a larger routine. to do so it needs to be loaded at the time of calling. just put it in the place you want it to run like you wrote.

(del_layers_masked "*NODE*,*MATC*,*NPLT*,*V-ANNO").

hth.

0 Likes