Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How does tblsearch and member actually work.

22 REPLIES 22
SOLVED
Reply
Message 1 of 23
emilio24DRY
1105 Views, 22 Replies

How does tblsearch and member actually work.

I have the code below that works, but I am not completely sure why it works. For example, line 6, the tblsearch command returns what exactly (I have looked here, but it is not enough information for my understanding). Within the condition statement between lines 5 and 8 how is that telling the code that the layer exists.

 

I have the same question about the member command in line 64. What exactly is happening with the code? Again, I have checked that it wo...

 

Is there a more extensive description of how tblsearch and member work with all the arguments that can be passed through it?

 

Thanks!

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun ECR:deleteLayer ( LAYER / )
;; CHECKS IF LAYER EXISTS BEFORE DELETING LAYER
	;; ADD TEXT TO ADD IF IT DOESN'T EXIST (CONDITION ELSE?)
	(cond
		((tblsearch "layer" LAYER)
			(command "-laydel" "name" LAYER "" "yes")  
		);LAYER EXISTS
		(t
			(princ (strcat "\n-\n" LAYER " does not exist to be deleted\n-\n"))
		);ELSE
	);COND
(princ)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun ECR:setCurrentLayer ( LAYER / )
;; SET CURRENT LAYER
	;; ADD SOME ERROR CHECKING TO CHECK IF THE LAYER EXISTS
	;; ADD TEXT TO ADD IF IT DOESN'T EXIST
	(cond
		((tblsearch "layer" LAYER)
			(command "-layer" "set" LAYER "")
		); LAYER EXISTS
		(t
			(command "-layer" "set" "1-DUMP" "")
			(princ (strcat "\n-\n" LAYER " does not exist to be set to current (setCurrentLayer). Layer ''1-DUMP'' Set to current\n-\n"))
		);ELSE
	);COND
(princ)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun ECR:thawLayer ( LAYER / )
;; SET CURRENT LAYER
	;; ADD SOME ERROR CHECKING TO CHECK IF THE LAYER EXISTS
	;; ADD TEXT TO ADD IF IT DOESN'T EXIST
	(cond
		((tblsearch "layer" LAYER)
			(command "-layer" "THAW" LAYER "")
		);LAYER EXISTS
		(t
			(princ (strcat "\n-\n" LAYER " does not exist to be thawed (thawLayer).\n-\n"))
		);ELSE
	);cond
(princ)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun ECR:setTab ( TAB / )
;; CHANGE TABS AND DO ZOOM EXTENTS ON THAT TAB
	(cond
		((member TAB (layoutlist))
			(setvar "ctab" TAB)
			(command "zoom" "extents")
		);LAYOUT NAME EXISTS
		(t
			(princ (strcat "\n-\n" TAB " does not exist to be set (setTab).\n-\n"))
		);ELSE
	);COND
(princ)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun ECR:deleteTab ( TAB / )
;; DELETES TAB BUT FIRST CHECK IF THE TAB EXISTS BEFORE TRYING TO DELETE
	(cond
		((member TAB (layoutlist))
			(command "-layout" "delete" TAB)
		);LAYOUT NAME EXISTS
		(t
			(princ (strcat "\n-\n" TAB " does not exist to be deleted (deleteTab).\n-\n"))
		);ELSE
	);COND
(princ)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun ECR:renameTab ( OLD_TAB NEW_TAB / )
;; RENAME TAB BUT FIRST CHECK IF THE TAB EXISTS BEFORE TRYING TO RENAME
	(cond
		((member OLD_TAB (layoutlist))
			(command "-layout" "Rename" OLD_TAB NEW_TAB)
		);LAYOUT NAME EXISTS
		(t
			(princ (strcat "\n-\n" OLD_TAB " does not exist to be renamed (renameTab).\n-\n"))
		);ELSE
	);COND
(princ)
)

 

Labels (2)
22 REPLIES 22
Message 2 of 23
paullimapa
in reply to: emilio24DRY
Message 3 of 23
Kent1Cooper
in reply to: emilio24DRY

The AutoLisp Reference entry for (member) is pretty clear if you read both the description at the top and the Return Values entry further down.  It returns the rest of the list starting with the item searched for, or nil if it's not in there.

 

For (tblsearch) it's a little less clear, not describing except by illustration what the "entry" is that it returns.  There are more properties of a Layer that it could include, but doesn't -- it's only "highlights," and you need (entget (tblobjname "layer" ...)) to get the more complete list.  But in the case of your code example, because it never actually uses any of the returned information, all you really need to know is that if there is no Layer by the name it's looking for, it returns nil.

Kent Cooper, AIA
Message 4 of 23
dbroad
in reply to: emilio24DRY

For tblsearch, see:

AutoCAD 2023 Help | tblsearch (AutoLISP) | Autodesk
https://help.autodesk.com/view/ACD/2023/ENU/index.html?guid=GUID-2AEB84A6-E3D0-4DD9-A29C-54D4099ED92...

Returns basic information about a table entry as an association list. For the cond function in your example, any non-nil return value means that the layer exists.

Ex:

(tblsearch "layer" "0")

((0 . "LAYER") (2 . "0") (70 . 0) (62 . 7) (6 . "CONTINUOUS"))

(entget(tblobjname "layer" "0"))

((-1 . <Entity name: xxx-xxxxxxxx>) (0 . "LAYER") (5 . "7") (102 . "{ACAD_XDICTIONARY") (360 . <Entity name: xxx-xxxxxxxx>) (102 . "}") (330 . <Entity name: 2408272e1d0>) (100 . "AcDbSymbolTableRecord") (100 . "AcDbLayerTableRecord") (2 . "0") (70 . 0) (62 . 7) (6 . "CONTINUOUS") (290 . 1) (370 . -3) (390 . <Entity name: 240827310a0>) (347 . <Entity name: 240827310d0>) (348 . <Entity name: 0>))

This wouldn't be helpful in your program but in other more advanced programs, it would give access to manipulating more properties the layer. 

 

Information on other symbol tables can be found here:

https://help.autodesk.com/view/ACD/2025/ENU/?guid=GUID-7B91F774-B0CD-4F5B-9FFA-1130443E659B

(

 

For member, see:

AutoCAD 2023 Help | member (AutoLISP) | Autodesk
https://help.autodesk.com/view/ACD/2023/ENU/index.html?guid=GUID-A2B08751-D966-44F5-9B02-1AAC4DA6AF5...

Architect, Registered NC, VA, SC, & GA.
Message 5 of 23
emilio24DRY
in reply to: emilio24DRY

So essentially, tblsearch and member return a value if it exists. How does line 6 actually work. Why don't you have to put for example:

-tblsearch equals a certain value or does not equal nil. 

-Why does putting (tblsearch...) work without either equal to (eq) or does not equal (<>?) nil-or some other comparison statement to compare what you expect vs what comes out of tblsearch or member?

Message 6 of 23
paullimapa
in reply to: emilio24DRY

There's nothing like trying the code yourself.

At the AutoCAD command prompt just enter the code and you'll see the response

For example if you do a tblsearch for layer "0" what would the response be:

(tblsearch "layer" "0")

Since every valid drawing must have a layer "0" you'll see that the command prompt returns:

((0 . "LAYER") (2 . "0") (70 . 0) (62 . 7) (6 . "CONTINUOUS"))

Now try a layer name that doesn't exist like "12345"

(tblsearch "layer" "12345")

The command prompt would return nil because that layer does not exist. There's no need to do any other kind of comparison evaluation.

Likewise with member....just create a list by entering the following at the command prompt:

(setq test (list "A" "B" "D" "F"))

AutoCAD returns: 

("A" "B" "D" "F")

Now use the member function to see if a matching item exists by entering the following at the command prompt:

(member "B" test)

Because that item "B" is available in the list AutoCAD returns all items after starting at the location the item is found:

("B" "D" "F")

But if you enter an item that does not exists with the member function like:

(member "C" test)

Since the item "C" is not in the list AutoCAD returns nil again without a need to do any further comparison tests

 

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 7 of 23
Kent1Cooper
in reply to: emilio24DRY

One thing to keep in mind:

In an (if) function, or at the beginning of a condition within a (cond) function, there's a test expression, and the (if) or (cond) is looking at only two possibilities for what is returned by that expression.  One possibility is nil, in which case the (if) function will perform its 'else' expression, or the (cond) function will move on to the next possible condition to check for [if there is one].  The other possibility is anything at all other than nil.  It doesn't matter whether it's a list [like what is returned by (tblsearch), a number, a text string, an entity name, a variable name if that contains anything other than nil, a mathematical function that returns a number, etc., etc.  If the return is any of the numerous non-nil possibilities, it will pass the test, and the (if) function will perform its 'then' expression, or the (cond) function will perform the remaining stuff spelled out within that condition [or if none, will just pass through the return of the test expression, which itself doesn't need to be a test, but can just be a text string or number or whatever].  So in situations like yours, there's no comparison to be made or equality to check for -- there's nothing needed beyond the simple nil-vs-anything-else check.

Kent Cooper, AIA
Message 8 of 23
emilio24DRY
in reply to: emilio24DRY

@Kent1Cooper So if I am undertanding correctly, in my case, the first condition or if statement would be anything other than nil. If it is nil the else statement will catch anything else. Since my case is just checking that the layer exists, it is super simple.

 

(defun ECR:deleteLayer ( LAYER / )
;; CHECKS IF LAYER EXISTS BEFORE DELETING LAYER
	(cond
		((tblsearch "layer" LAYER)
			(command "-laydel" "name" LAYER "" "yes")  
		);ANYTHING OTHER THAN NIL
		(t
			(princ (strcat "\n-\n" LAYER " does not exist to be deleted\n-\n"))
		);IN MY CASE, THIS WOULD BE NIL
	);COND
(princ)
)

 

 

Message 9 of 23
Kent1Cooper
in reply to: emilio24DRY

And if there's only one condition to check for, it can be even simpler:

(defun ECR:deleteLayer ( LAYER / )
;; CHECKS IF LAYER EXISTS BEFORE DELETING LAYER
  (if (tblsearch "layer" LAYER)
    (command "-laydel" "name" LAYER "" "yes"); 'then'
    (princ (strcat "\n-\n" LAYER " does not exist to be deleted\n-\n")); 'else'
  ); if
  (princ)
)

The (cond) function can be used for this, but is really built for situations with multiple possible conditions -- try the first one, and if its test passes do what it says, but if it fails go on to try the next one, etc., stopping at whichever condition's test expression passes first.

Kent Cooper, AIA
Message 10 of 23
paullimapa
in reply to: Kent1Cooper

FYI if there are objects on that layer the layer will not be deleted


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 11 of 23
emilio24DRY
in reply to: paullimapa

@paullimapa It pushes through those objects and deletes them-I tested it. It does put up a warning, but it does delete the layer and all the objects on those layers. In my case this is how I want it to work.

Message 12 of 23
Kent1Cooper
in reply to: paullimapa


@paullimapa wrote:

FYI if there are objects on that layer the layer will not be deleted


LAYDEL will delete it [including any objects on it] -- what you can't do to it is to PURGE it.  If it's the current Layer, it can't be deleted with LAYDEL, so it might be worth checking for that.

 

(defun ECR:deleteLayer (LAYER / ldata)
;; CHECKS IF LAYER EXISTS BEFORE DELETING LAYER
  (if
    (and
      (setq ldata (tblsearch "layer" LAYER)) ; it exists
      (/= (getvar 'clayer) LAYER) ; but it's not current
      (= (logand 4 (cdr (assoc 70 ldata))) 0) ; and not locked
    ); and
    (command "-laydel" "name" LAYER "" "yes"); 'then'
    (princ ; 'else'
      (strcat
        "\n-\n" LAYER " does not exist to be deleted, or is "
        "locked or is the current Layer and cannot be deleted."
        "\n-\n"
      ); strcat
    ); princ
  ); if
  (princ)
)

 

Or, if you really want to be rid of it even if it's current and/or locked, the 'else' could be to set Layer 0 current and then unlock and delete the one in question.

EDITED for the locked-Layer issue.

Kent Cooper, AIA
Message 13 of 23
paullimapa
in reply to: emilio24DRY

that's true as long as the current layer is not the layer you want to delete.


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 14 of 23
paullimapa
in reply to: Kent1Cooper

also won't work if the layer is locked.


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 15 of 23
Kent1Cooper
in reply to: paullimapa


@paullimapa wrote:

also won't work if the layer is locked.


Ah, yes....  I've Edited my previous Reply to account for that, too.

Kent Cooper, AIA
Message 16 of 23
paullimapa
in reply to: emilio24DRY

So an interesting challenge would be to come up with code to check if the layer attempting to be deleted is current. If it is then set the current layer to another like as @Kent1Cooper stated layer 0. But you'll also have to check to make sure whatever layer you want to set current is also Thawed and not Frozen. A Frozen layer cannot be set current...happy coding...


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 17 of 23
dbroad
in reply to: emilio24DRY

@emilio24DRY 

Re line 6:  look up how COND works. Each argument is tested. If that argument’s first element evaluates to nil, it skips evaluating the rest of that argument. Cond is like if but allows more than two choices. It’s one of the most effective branches in LISP. 

Architect, Registered NC, VA, SC, & GA.
Message 18 of 23
dbroad
in reply to: paullimapa

@paullimapa 

Have you used laydel?

Architect, Registered NC, VA, SC, & GA.
Message 19 of 23
paullimapa
in reply to: dbroad

Yes I used it but I happened to have the layer I wanted to delete set current so that’s what prevented it from deleting and not that there are objects contained in the layer


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 20 of 23
dbroad
in reply to: emilio24DRY

My solution was to (...(setvar "clayer" "0")(command "laydel")...)  I never need to worry about being on a layer I want to delete. The lock icon shows those layers which are locked and I can live with unlocking those manually.

Architect, Registered NC, VA, SC, & GA.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

AutoCAD Inside the Factory


Autodesk Design & Make Report