Pass arguments to "c:" commands

Pass arguments to "c:" commands

christian_paulsen98V29
Enthusiast Enthusiast
1,424 Views
14 Replies
Message 1 of 15

Pass arguments to "c:" commands

christian_paulsen98V29
Enthusiast
Enthusiast

Ive found out how to call the gatte command using "c:" instead of "command". However i cant figure out how to pass arguments into the command line after getting gatte started. Ideally after the gatte command is started i can input the following. "B" "DWGSTATE" "STATE" keyword "YES"

 

(defun c:RELEASESTATE ()
(initget "PRELIMINARY RELEASED")
(if (setq keyword (getkword "[Preliminary/Released]: <Released>"))
	(c:gatte)
)
)

 

0 Likes
1,425 Views
14 Replies
Replies (14)
Message 2 of 15

paullimapa
Mentor
Mentor

already answered when you posted this in your other thread


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 3 of 15

christian_paulsen98V29
Enthusiast
Enthusiast

He did not. That was a different way of doing it using vla commands, im trying to simplify it into not using vla commands.

 

It also didnt work. When it came to the "yes" at the end of the arguments, it wasn't getting that input. It was changing the attribute to literally say "Released yes" and then you had to still click yes at the end.

0 Likes
Message 4 of 15

paullimapa
Mentor
Mentor

Your better option is to run vla functions which are way more flexible than GATTE which requires Express Tools to be loaded. An example of implementation can be found here:

https://www.cadtutor.net/forum/topic/58824-gatte-w-mtext-or-alternative/?do=findComment&comment=4873...

Just replace the Block, Attribute Tag name & new value with yours in the code.


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 5 of 15

paullimapa
Mentor
Mentor

here's a version that modifies your code but without using vla functions:

 

; RELEASESTATE
; OP:
; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/pass-arguments-to-quot-c-quot-commands/m-p/12779080#M466161
(defun c:RELEASESTATE (/ blknam ent keyword n ss sslen tagnam)
 (setq blknam "DWGSTATE" ; block name
       tagnam "STATE"    ; attribute tag name
 )
 (if (setq ss (ssget "_X" (list '(0 . "INSERT")(cons 2 blknam))))
  (progn
   (initget "Preliminary Released")
   (setq keyword (getkword "Specify keyword [Preliminary/Released]: ")) 
   (setq sslen (sslength ss) n 0)
   (repeat sslen
    (setq ent (ssname ss n))
    (setpropertyvalue ent tagnam keyword)
    (setq n (+ 1 n))
   ) ; repeat
   (princ(strcat"\nFound " (itoa sslen) " Blocks matching name [" blknam "]"))
  ) ; progn
  (princ(strcat"\nFound no Blocks matching Name [" blknam "]"))
 ) ; if
 (princ)
) ; defun

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 6 of 15

john.uhden
Mentor
Mentor

@christian_paulsen98V29 ,

The only way c: functions can accept input in the same way as AutoCAD commands is to provide them with input arguments, one for one.  But I don't know of anybody who does that because they typically just want to call the command with no arguments and have the function prompt them for the inputs.

Now you might want to try using vlax-add-cmd first.  But I think you would be better just to realize the limitation and create a regular function that accepts arguments.

John F. Uhden

0 Likes
Message 7 of 15

paullimapa
Mentor
Mentor

This modified version works but again using vla

 

(vla-sendcommand (vla-get-activedocument (vlax-get-acad-object)) (strcat "gatte B DWGSTATE STATE " keyword "\rYes\r"))

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 8 of 15

paullimapa
Mentor
Mentor

@christian_paulsen98V29 

Totally agree...like this version which defines your own gatte that accepts arguments:

; RELEASESTATEA
; OP:
; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/pass-arguments-to-quot-c-quot-commands/m-p/12779080#M466161
(defun c:RELEASESTATEA (/ gatte keyword)
 ; gatte similar to c:gatte function but with following arguments:
 ; blk-arg = block name
 ; tag-arg = attribute tag name
 ; val-arg = attribute value
(defun gatte (blk-arg tag-arg val-arg / ent n ss sslen)
 (if (setq ss (ssget "_X" (list '(0 . "INSERT")(cons 2 blk-arg))))
  (progn
   (setq sslen (sslength ss) n 0)
   (repeat sslen
    (setq ent (ssname ss n))
    (setpropertyvalue ent tag-arg val-arg)
    (setq n (+ 1 n))
   ) ; repeat
   (princ(strcat"\nFound " (itoa sslen) " Blocks matching name [" blk-arg "]"))
  ) ; progn
  (princ(strcat"\nFound no Blocks matching Name [" blk-arg "]"))
 ) ; if
) ; defun gatte
;
; main function
;
 (initget "Preliminary Released")
 (if (setq keyword (getkword "Specify keyword [Preliminary/Released]: ")) 
   (gatte "DWGSTATE" "STATE" keyword)
 )
 (princ)
) ; defun

Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 9 of 15

christian_paulsen98V29
Enthusiast
Enthusiast

I looked at that other version on cad tutor that looked like it had kinda the same code as the one you wrote without the vla stuff. However i couldnt 100% figure out how to rework into what i need. I saw where you put in the block name but didnt see where to put in the attribute name.  I guess my problem with all the vla stuff is that i dont fully understand it and it looks overwhelming whenever i see it in code. 

I did have a question though. In the beginning of both of the codes it does an ssget and selects all the blocks with the chosen name. Does this select all the blocks in the entire drawing or will it only select all the blocks in your current workspace? Say like if im in model space it will only change the blocks in model space.

 

Below is a copy of the final code i ended up using. I liked it because it was short and easy, i guess the only downfall is that it relys on the express tools. I also didnt like having to add the second line in the if statement because it seemed redundant but i couldnt find another way to make it work if the user just pressed enter and it returned 'nil'.

 

(defun c:RELEASESTATE ()
	(vl-load-com)
	(initget "PRELIMINARY RELEASED")
	(if (setq keyword (getkword "[Preliminary/Released]: <Released>"))
		(vla-sendcommand (vla-get-activedocument (vlax-get-acad-object)) (strcat "gatte b dwgstate state " keyword "\nyes "))
		(vla-sendcommand (vla-get-activedocument (vlax-get-acad-object)) (strcat "gatte b dwgstate state RELEASED\nyes "))
	)
)

  

0 Likes
Message 10 of 15

christian_paulsen98V29
Enthusiast
Enthusiast

I looked at that other version on cad tutor that looked like it had kinda the same code as the one you wrote without the vla stuff. However i couldnt 100% figure out how to rework into what i need. I saw where you put in the block name but didnt see where to put in the attribute name.  I guess my problem with all the vla stuff is that i dont fully understand it and it looks overwhelming whenever i see it in code. 

I did have a question though. In the beginning of both of the codes it does an ssget and selects all the blocks with the chosen name. Does this select all the blocks in the entire drawing or will it only select all the blocks in your current workspace? Say like if im in model space it will only change the blocks in model space.

 

Below is a copy of the final code i ended up using. I liked it because it was short and easy, i guess the only downfall is that it relys on the express tools. I also didnt like having to add the second line in the if statement because it seemed redundant but i couldnt find another way to make it work if the user just pressed enter and it returned 'nil'.

 

 

(defun c:RELEASESTATE ()
	(vl-load-com)
	(initget "PRELIMINARY RELEASED")
	(if (setq keyword (getkword "[Preliminary/Released]: <Released>"))
		(vla-sendcommand (vla-get-activedocument (vlax-get-acad-object)) (strcat "gatte b dwgstate state " keyword "\nyes "))
		(vla-sendcommand (vla-get-activedocument (vlax-get-acad-object)) (strcat "gatte b dwgstate state RELEASED\nyes "))
	)
)

 

  

0 Likes
Message 11 of 15

paullimapa
Mentor
Mentor

Yes, the link I provided and the two code versions I wrote use the same ssget method to select ALL instances of the given block name which in your case is called "DWGSTATE" both in Model & all Layouts matching what the Express Tools Gatte function does.

Cadtutor code:

(setq ss (ssget "X" '((0 . "INSERT")(2 . "NP TITLEBLOCK INFO")))) ; block name is "NP TITLEBLOCK INFO"

My Code #1:

(setq blknam "DWGSTATE" ; block name
       tagnam "STATE"    ; attribute tag name
)
(if (setq ss (ssget "_X" (list '(0 . "INSERT")(cons 2 blknam))))

My Code #2: which defines own gatte function with three arguments: block name, tag name & new attribute value:

; gatte similar to c:gatte function but with following arguments:
 ; blk-arg = block name
 ; tag-arg = attribute tag name
 ; val-arg = attribute value
(defun gatte (blk-arg tag-arg val-arg / ent n ss sslen)
 (if (setq ss(ssget "_X" (list '(0 . "INSERT")(cons 2 blk-arg)))) 
; ....
; then towards the end of code call the new gatte function:
(gatte "DWGSTATE" "STATE" keyword)

As for your new modified code, what you could do is to actually define a default global keyword variable like this:

 (or **keyword** (setq **keyword** "RELEASED")) ; setup default

This assume no other code is using **keyword**

Then the following lines of code will respond to the initget

If an enter is press to accept the default **keyword** then keyword will be set equal to the global variable

Else the global variable will be reset using the new selected keyword value:

 (initget "PRELIMINARY RELEASED")
 (setq keyword (getkword (strcat "Specify keyword [PRELIMINARY/RELEASED] <" **keyword** ">: ")))
 (if (not keyword) 
  (setq keyword **keyword**) ; hit enter to accept default
  (setq **keyword** keyword) ; reset default to new entry
 ) ; if

Then lastly run the vla command but using the version I provided which completes itself without further interaction:

 (vla-sendcommand (vla-get-activedocument (vlax-get-acad-object)) (strcat "gatte B DWGSTATE STATE " keyword "\rYes\r"))

Yes, there are more lines of code...but all automated if you want to run RELEASESTATE again in the same drawing.

; RELEASESTATE
; OP:
; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/pass-arguments-to-quot-c-quot-commands/m-p/12781153#M466205
(defun c:RELEASESTATE (/ keyword)
 (vl-load-com)
 (or **keyword** (setq **keyword** "RELEASED")) ; setup default
 (initget "PRELIMINARY RELEASED")
 (setq keyword (getkword (strcat "Specify keyword [PRELIMINARY/RELEASED] <" **keyword** ">: ")))
 (if (not keyword) 
  (setq keyword **keyword**) ; hit enter to accept default
  (setq **keyword** keyword) ; reset default to new entry
 ) ; if
 (vla-sendcommand (vla-get-activedocument (vlax-get-acad-object)) (strcat "gatte B DWGSTATE STATE " keyword "\rYes\r"))
 (princ) ; clean exit
) ; defun

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 12 of 15

Sea-Haven
Mentor
Mentor

Re "Say like if im in model space it will only change the blocks in model space." You can use a 410 filter for the current space. Or "Model" for model space only. 

 

(if (setq ss(ssget "_X" (list '(0 . "INSERT")(cons 2 blk-arg)(cons 410 (getvar 'ctab))))

 

 

0 Likes
Message 13 of 15

paullimapa
Mentor
Mentor

@christian_paulsen98V29 

you can learn a lot by opening Express Tools gatte.lsp file & see what it does:

         (Setq
            NA (GetString T "\nEnter new text: ")
            SS1 (SsGet "_X"
                 (List
                    (Cons 0 "INSERT")
                    (Cons 2 bn)
                    (Cons 66 1)
                 )
              )

Notice the gatte.lsp's ssget function adds an additional (cons 66 1) which tells AutoCAD to select the block that also has attributes ignoring other blocks that do not.

FYI: Notice the "_X" that follow ssget tells AutoCAD to automatically select all both in Model & Layouts

PS: to find the location of gatte.lsp at the command prompt enter:

(findfile "gatte.lsp")

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 14 of 15

hak_vz
Advisor
Advisor

Passing arguments to c:command

(defun somecommand (arg1 arg2 argn / local_1 local_2 .....)
......

)
(defun c:somecommand nil (somecommand (arg1 arg2 argn)))

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
0 Likes
Message 15 of 15

john.uhden
Mentor
Mentor

Blast it all again... kicked out with "authentication failed" right as I submitted!!

And I didn't save a draft of what I had written.  It was something like this...

@hak_vz ,

I wouldn't call your method as passing arguments to a command function, as your method does not use local variables but only references symbols that are global.

As I had stated, you might as well use just a regular function that accepts arguments as inputs (which by definition are local).

But there is a kind of work-around using vlax-add-cmd.

For example:

 

(defun test ( / a b c)
  (setq a (getstring "\nFirst: "))
  (setq b (getstring "\nSecond: "))
  (setq c (getstring "\nThird: "))
  (print (strcat a " " b " " c))
  (princ)
)
(vlax-add-cmd "Test" 'test)
Command: (setvar "cmdecho" 0) 0
Command: (command "test" "One" "Two" "Three")
"One Two Three" nil

 

Of course there is a limitation... Unlike AutoCAD commands, you must provide the exact number of input arguments as the function requests.

BUT, your function could be embellished to deal with a null response to any input prompt and carry on appropriately.

I would still stick with a plain function, unless you are into scripts where this technique could be helpful, especially with users1(-5), useri1(-5), and userr1(-5).

John F. Uhden

0 Likes