Lisp to find out and amend properties of XREF/Block layers

Lisp to find out and amend properties of XREF/Block layers

barry2104
Collaborator Collaborator
5,066 Views
25 Replies
Message 1 of 26

Lisp to find out and amend properties of XREF/Block layers

barry2104
Collaborator
Collaborator

I use the following lisp in order to find out layer names of entities within an xref or block. It works just like the -XLIST command (much better than the standard XLIST command which only shows you the first 40-odd charachters of the layer name without the ability to copy the text out of the output window). However 90% of the time I only want to find the layer name out in order to then change its properties via the layer manager (e.g. change colour from red to black).

 

Is it possible to amend the lisp so that upon entering the command and picking the entity, it then opens up Layer Manager and has that layer selected (or filtered out) so that I can instantly change its properties and save time finding the layer?

 

If this isn't possible then I guess a consolation would be to amend the lisp so that the selected layer name is automatically added to the clipboard, with a * before and after the layer name so that I can just paste (CTRL+V) the clipboard into the layer filter within layer manager to get faster access to the layer properties. 

(defun C:XRL ()
 (setq EnL (entget (car (nentsel "\nSelect object to identify layer it is on : ")))
       LNm (cdr (assoc 8 EnL))
 )
 (princ "\n Entity layer name: ")
 (princ LNm)
(prin1))

 Thanks in advance

Running AutoCAD Architecture 2020, in German
0 Likes
5,067 Views
25 Replies
  • Lisp
Replies (25)
Message 2 of 26

daneson.marcelino
Enthusiast
Enthusiast

Hi @barry2104 ,

 

Please try this one.

 

 

(defun C:XRL ()
(setq NColor (getstring "\nEnter New Color : "))
(while
(setq EnL (entget (car (nentsel "\nSelect object to identify layer it is on : "))))
(setq LNm (cdr (assoc 8 EnL)))

(command "-layer" "c" NColor LNm "")
);end of while
)

Message 3 of 26

barry2104
Collaborator
Collaborator

Thanks for the fast response, but the colour change was just one example. Just as often I'm needing to change the transparency, linetype, line weight, etc., so running everything through the command bar with your lisp isn't ideal.

Is it possible to have Layermanager open up and have the selected layer filtered (copy the name of the selected/embedded layer and paste it (along with * before and after) into the "all layers" layer manager filter?

Running AutoCAD Architecture 2020, in German
0 Likes
Message 4 of 26

pbejse
Mentor
Mentor

@barry2104 wrote:

 

Is it possible to have Layermanager open up and have the selected layer filtered (copy the name of the selected/embedded layer and paste it (along with * before and after) into the "all layers" layer manager filter?


 

You mean  "XREF name|layer name*" or  "XREF name|*layer name*" ?

 

0 Likes
Message 5 of 26

barry2104
Collaborator
Collaborator

For Xrefs "XREF name|layer name*" would suffice

For blocks, the "XREF name|" prefix doesn't apply. Can the amended lisp cater for this?

If so, then I assume one could use this lisp command to "jump" to any object's layer in Layermanager (not just nested Xref / Block layers, but also locally drawn lines, circles, text, etc)?

Running AutoCAD Architecture 2020, in German
0 Likes
Message 6 of 26

Kent1Cooper
Consultant
Consultant

Are you willing to do it at the command line, rather than in the Layer Manager?  This seems to work, that way.

 

Start the ALP command, and select an object [nested or not], and you will be offered the Layer command-line prompt listing all the options.  Type in an option name or abbreviation, then a value for it, and it will be applied to that Layer.  You can keep going, and change more than one property, but if you do, you won't see the changes [those that are visible, such as color or linetype] until you finish by hitting Enter/space for the <exit> default when it's asking for another option.

 

(defun C:ALP (/ EnL LNm opt); = Assign Layer Properties
  (setq
    EnL (entget (car (nentsel "\nSelect object to identify layer it is on : ")))
    LNm (cdr (assoc 8 EnL))
  ); setq
  (command "_.layer")
  (while (/= (setq opt (getstring "\nOption or abbreviation, or <exit>: ")) "")
    (command opt pause LNm); User input of value, then apply to Layer
  ); while
  (command ""); end Layer command
  (princ)
); defun

 

[I took out the prompt of the Layer name, since if you have only a few lines showing at the Command line, it disappears scrolling up for the command-line Layer prompt.]

 

Be aware that this works for options that take entering of a single value  before applying it to the Layer(s) [such as Color, Linetype, Plot status, LWeight, etc.], not  those that want only  Layer names to be applied to [such as Off, Freeze, Lock], nor that need more than one input [such as Rename].

 

EDIT:  Another thing to be aware of is that (nentsel) finds the deepest-nested  Layer of what you pick on.  So if you pick on a Block, even a Block nested inside an Xref, and the Block's piece that you pick on was drawn on Layer 0 [as is common practice], the change(s) will be applied not to the Layer the Block is inserted on, nor the Layer the Xref is referenced on, but to Layer 0.  With more code, it would be possible to detect the Layer being 0, and step up through nesting Layers until it encounters a non-0 Layer, and apply the change to that -- see one way to do that in LayerQuellPick.lsp, available >here<.

Kent Cooper, AIA
0 Likes
Message 7 of 26

barry2104
Collaborator
Collaborator

Thanks Kent but in my case I see that as being less user-friendly than just having the Xref|layer name (or in the case of a local object/block, just the "Layer name") of the picked object simply being copied to clipboard so that I can paste (Ctrl+V) it into the layer manager filter box.

Not everyone knows the colour palette off by heart, let alone the colour codes for True Colours! Doing it this way I'd also see instant changes rather than having to wait until your lisp has completed all the individual inputs/changes.

 

Which line of code would be needed to be added to my original lisp to get the layer name to be copied to clipboard? Would this need a couple of lines to cover both Xref- and Non-Xref-Layers?

Running AutoCAD Architecture 2020, in German
0 Likes
Message 8 of 26

pbejse
Mentor
Mentor

@barry2104 wrote:

For Xrefs "XREF name|layer name*" would suffice


 

 

(defun c:xlf ( / xdict dict name xrecname fltername)
    (setq xdict
        (vlax-vla-object->ename
            (vla-getextensiondictionary 
                (vla-get-layers 
                    (vla-get-activedocument (vlax-get-acad-object))
                )
            )
        )    
    )
    
    (setq dict
        (if (setq dict (dictsearch xdict "ACAD_LAYERFILTERS"))
            (cdr (assoc -1 dict))
            (dictadd xdict "ACAD_LAYERFILTERS"
                (entmakex
                   '(
                        (0 . "dictionary")
                        (100 . "AcDbDictionary")
                        (280 . 0)
                        (281 . 1)
                    )
                )
            )
        )
    )   
   	(if (setq p
		(vl-string-search "|"
		  (setq name (cdr (assoc 8 (entget(car (nentsel "\nSelect Xref object: "))))))
		  )
		  )
	  (progn
		(if (not (dictsearch dict (setq xrecname (substr name (+ 2 p)))))
		  (dictadd dict xrecname
	                    (entmakex
	                        (append
	                           '(
	                                (0 . "xrecord")
	                                (100 . "AcDbXrecord")
	                                (280 . 1)
	                            )    
	                            (list (cons 1 xrecname))
	                            (list (cons 1 name))						                                   
				    '(
	                                (1 . "*")
	                                (1 . "*")
	                                (70 . 0)
	                                (1 . "*")
	                                (1 . "*")
				     )
				     (list
	                                (list -3          
	                                    (list   "ACAD"
	                                        (cons 1000  (Strcat "( NAME== \"" name "\" )"))
	                                    )         
	                                )
	                            )    
	                        )
	                    )
	                )
	  )
   	(initdia) (command ".layer")
	    )
	 )	    
   )

 

 

HTH

 

Overall, whay you are asking for is easy. a layer filter dialogue that will work not only for XREFS but for all. only thing is adding ALL properties would be difficult especially if you want a GUI to go with it.

Something like this.

 

layfilter.jpg

 

 

 

 

0 Likes
Message 9 of 26

barry2104
Collaborator
Collaborator

@Anonymous that code doesn't seem to work (for me). Upon picking an object, my command line spits out:

Select Xref object: nil

Running AutoCAD Architecture 2020, in German
0 Likes
Message 10 of 26

Kent1Cooper
Consultant
Consultant

@barry2104 wrote:

....

Not everyone knows the colour palette off by heart, let alone the colour codes for True Colours! ....

 

Which line of code would be needed to be added to my original lisp to get the layer name to be copied to clipboard? Would this need a couple of lines to cover both Xref- and Non-Xref-Layers?


On the color part, this version at least takes care of that, bringing up the color dialog box when you choose that option:

(defun C:ALP (/ EnL LNm opt); = Assign Layer Properties
  (setq
    EnL (entget (car (nentsel "\nSelect object to modify properties of Layer it is on : ")))
    LNm (cdr (assoc 8 EnL))
  ); setq
  (prompt (strcat "\n Entity layer name: " LNm))
  (command "_.layer")
  (while (/= (setq opt (getstring "\nOption or abbreviation, or <exit>: ")) "")
    (if (wcmatch (strcase opt) "C*"); color option
      (command opt (acad_colordlg (cdr (assoc 62 (tblsearch "layer" LNm))) nil) LNm)
      (command opt pause LNm)
    ); if
  ); while
  (command ""); end Layer command
  (princ)
); defun

But no, it doesn't show you such a change immediately.

 

I don't work with communication to the clipboard in code enough to know how to send it there, but others may chime in, or you can probably find examples with a Search.  It shouldn't require different handling for nested or non-nested Layers -- the Layer name returned from the selection will already include what it needs to know the difference.

Kent Cooper, AIA
0 Likes
Message 11 of 26

pbejse
Mentor
Mentor

@barry2104 wrote:

@Anonymous that code doesn't seem to work (for me). Upon picking an object, my command line spits out:

Select Xref object: nil


 

As i've been doing lately, NOT reading and understanding the TOPIC , I always end up with a half baked code 😄

I will update the code in a few.

 

 

0 Likes
Message 12 of 26

pbejse
Mentor
Mentor

The way it works is, it creates the layer filter after nested object selection

Refer to attached lisp BlockXrefFilter.LSP

 

Here is the mod

..
  (and
	 (setq blockOrXref (entsel "\nSelect Xref object: "))
         (setq nobj (car (nentselp (cadr blockOrXref))))
	 (eq "INSERT" (cdr (assoc 0  (entget (Car blockOrXref)))))
	 (not (member  (setq name (cdr (assoc 8 (entget nobj)))) '("0" "Defpoints")))
	 )
	  (progn
	    (setq ent (Car blockOrXref)
		  name (cdr (assoc 8 (entget nobj))))	    	 

	    (setq xrecname
		   (if (setq p (vl-string-search "|" name))
		     (substr name (+ 2 p))
		     name
		   )
	    )	    
...

 

Works for XREFS and blocks

 

pBe

 

0 Likes
Message 13 of 26

barry2104
Collaborator
Collaborator

I don't know whether it's perhaps because I'm running a German version of AutoCAD (2021), but that modded lisp also doesn't work.

I get the same command line error as before, regardless as to whether I select a lokal element (block or non-block) or an Xref element. Nothing gets copied to clipboard either.

However, I noticed that the Layer M anager opened up upon selecting an Xref object (but also didn't have anything copied to the clipboard and didn't filter out/show the selected layer in Layer Manager).

Running AutoCAD Architecture 2020, in German
0 Likes
Message 14 of 26

pbejse
Mentor
Mentor

@barry2104 wrote:

I don't know whether it's perhaps because I'm running a German version of AutoCAD (2021), but that modded lisp also doesn't work.


Dont worry about @barry2104, This is the  way is was supposed to work, there will be no need to create a new filter and paste the clipboard value on layer manager, the program will already create the filter with the same name as the selected layername, all you need to do select the Name on the filter list.

 

I soon realized that the name of the filter should remain the same as "USER SELECTED LAYER" or something similar, that way the user can  always identify filter name on the filter list and it will show the filtered layer.

 

 

(defun c:xlf ( / xdict dict name xrecname fltername blockOrXref)
;;;		pBe MAy 2020		;;;
    (setq xdict
        (vlax-vla-object->ename
            (vla-getextensiondictionary 
                (vla-get-layers 
                    (vla-get-activedocument (vlax-get-acad-object))
                )
            )
        )    
    )
    
    (setq dict
        (if (setq dict (dictsearch xdict "ACAD_LAYERFILTERS"))
            (cdr (assoc -1 dict))
            (dictadd xdict "ACAD_LAYERFILTERS"
                (entmakex
                   '(
                        (0 . "dictionary")
                        (100 . "AcDbDictionary")
                        (280 . 0)
                        (281 . 1)
                    )
                )
            )
        )
    )   
(if
  (and
	 (setq blockOrXref (entsel "\nSelect Xref object: "))
         (setq nobj (car (nentselp (cadr blockOrXref))))
	 (eq "INSERT" (cdr (assoc 0  (entget (Car blockOrXref)))))
	 (not (member  (setq name (cdr (assoc 8 (entget nobj)))) '("0" "Defpoints")))
	 )
	  (progn    
		(if (setq xflter (dictsearch dict (setq xrecname "USER SELECTED LAYER")))
		  	(dictremove dict xrecname))
		  
			  (dictadd dict xrecname
		                    (entmakex
		                        (append
		                           '(
		                                (0 . "xrecord")
		                                (100 . "AcDbXrecord")
		                                (280 . 1)
		                            )    
		                            (list (cons 1 xrecname))
		                            (list (cons 1 name))
					    '(
		                                (1 . "*")
		                                (1 . "*")
		                                (70 . 0)
		                                (1 . "*")
		                                (1 . "*")
					     )
					     (list
		                                (list -3          
		                                    (list   "ACAD"
		                                        (cons 1000  (Strcat "( NAME== \"" name "\" )"))
		                                    )         
		                                )
		                            )    
		                        )
		                    )
		                )
		  
   	(initdia) (command ".layer")
	    )
	 )
  (princ)
   )

 

 

Only for XREFS/Blocks

 

When the Layer Manager opens, look for USER SELECTED LAYER: 

xlf.JPG

On some PC, a resresh is required[ iupper right corner ]

refresh.jpg

 

HTH <-- not my name 🙂 [ Hope this helps ]

pBe

 

0 Likes
Message 15 of 26

barry2104
Collaborator
Collaborator

thanks again for your efforts but it still doesn't seem to work properly (for me at least).

Running AutoCAD Architecture 2020, in German
0 Likes
Message 16 of 26

pbejse
Mentor
Mentor

@barry2104 wrote:

thanks again for your efforts but it still doesn't seem to work properly (for me at least).


 

Not a problem barry, listen, can you post a drawing that i can test, perhaps its not CAD version issue but I  maybe misunderstanding your requirements.

 

 

 

0 Likes
Message 17 of 26

barry2104
Collaborator
Collaborator

so to be more specific, it seemed to work okay on blocks within my drawing (once) but not at all on Xrefs.

I documented the following on my first run, selecting a local block element

1) Layer Manager automatically pops open

2) The USER SELECTED LAYER filter can be seen in the filter list on the left hand side, but unfortunately isn't automatically selected. Instead, the previously selected layerfilter was still selected, so I have to manually click on USER SELECTED LAYER where I then see the selected block-layer. I can then change individual properties of that layer, as desired.

 

3) Upon repeating the command to edit another block layer, nothing seemed to work. After picking the element, Layermanager didn’t open up, so I did that manually. I could still see the USER SELECTED LAYER filter but upon selecting it, ALL of the available layers (local and xref layers) were shown, so the filter didn’t work. I then tried refreshing the filter list with the two arrowed circle in the top right corner of the LMan, but that didn’t change anything.

4) I also tried deleting the USER SELECTED LAYER filter before doing everything again, but had the same result as step (3).

5) I then tried it on an XREF Layer on a different (clean) drawing but had the same problem as above in step (3)

 

I tried all these steps on multiple drawings and always get a result like in step (3), sometimes step (2) works once though, sometimes not.

 

Attached is an ETRANSMIT with a basic block and an Xref containing a zigzag polyline and a few other blocks. Does it work for you?

Again, I’m running 2021 Architecture.

 

Running AutoCAD Architecture 2020, in German
0 Likes
Message 18 of 26

pbejse
Mentor
Mentor

@barry2104 wrote:

so to be more specific, it seemed to work okay on blocks within my drawing (once) but not at all on Xrefs.

I documented the following on my first run, selecting a local block element

1) Layer Manager automatically pops open

2) The USER SELECTED LAYER filter can be seen in the filter list on the left hand side, but unfortunately isn't automatically selected. Instead, the previously selected layerfilter was still selected, so I have to manually click on USER SELECTED LAYER where I then see the selected block-layer. I can then change individual properties of that layer, as desired.


 

I remember there was a time that you were only too happy just to have the layername in a clipboard and pasting it on a filter list, i given much more.

-selected layer name is automatically added to the clipboard, with a * before and after the layer name so that I can just paste (CTRL+V) the clipboard into the layer filter within layer manager-

 


@barry2104 wrote:

3) Upon repeating the command to edit another block layer, nothing seemed to work. After picking the element, Layermanager didn’t open up.

One reason this happens is when the user selected an entity on either layer 0 or Defpoints. I soon realized that there is something off about the selection, I made a quick hack on the code and is now corrected on the attached lsp file.

 


@barry2104 wrote:

...I could still see the USER SELECTED LAYER filter but upon selecting it, ALL of the available layers (local and xref layers) were shown, so the filter didn’t work. I then tried refreshing the filter list with the two arrowed circle in the top right corner of the LMan, but that didn’t change anything.Does it work for you?


Yes it does. probably has something to do with your settings. i wlll look into Layer Settings/Dialog Settings /Apply layer filter to layer toolbar or anything related to layer notification.

 


@barry2104 wrote:

4) I also tried deleting the USER SELECTED LAYER filter before doing everything again, but had the same result as step (3).

5) I then tried it on an XREF Layer on a different (clean) drawing but had the same problem as above in step (3)


We will know soon enough when you try this ammended lsip

Here is a screencast on how it behaves on my PC.


@barry2104 wrote:

 

Again, I’m running 2021 Architecture.


And I am running out of ideas 😄

 

 

0 Likes
Message 19 of 26

barry2104
Collaborator
Collaborator

don't get me wrong - i really do appreciate your input!

The new lisp also seems to not work for me. The only difference between old and new is that I get a pop-up dialog when selecting a layer=0 entity (e.g. typically within a block). Otherwise it doesn't work my for non-layer-0 local blocks and also not for xrefs.

Nothing is copied to the clipboard either, which would help, but that's probably working for you, just not me. Which settings could it be? I run my system in German, not English!

 

PS: there is no hyperlink to your screencast

Running AutoCAD Architecture 2020, in German
0 Likes
Message 20 of 26

barry2104
Collaborator
Collaborator

I just discovered that the USER SELECTED LAYER filter (sometimes) DOES work, but it takes at least 5 minutes for the selected layer to show up! Until that time, the previously filtered layer in USER SELECTED LAYER is shown.

I've tried closing and reopening LMan, clicking the refresh button, switching from USER SELECTED LAYER to ALL and back to USER SELECTED LAYER and nothing gets it to refresh quickly, I just have to wait. Or maybe a different action I perform when working a drawing somehow gets it to refresh?

Very Weird.

 

Running AutoCAD Architecture 2020, in German
0 Likes