Jump to content

If Functions in Menu Macros ?


rob150588

Recommended Posts

Afternoon all.

 

I'm wondering if there is any way to write an "IF" function (similar to the Excel one) into a Menu Macro to determine if certain sections of the macro should be run ?

 

What I have is a macro for merging layers that are in a drawing (since we updated our layering standards a short while ago). I would like the macro to be able to determine if a layer is present within the drawing. IF so, proceed with the macro. IF not, ignore the macro.

 

Any ideas ? I'm thinking DIESEL programming, but I don't know enough about it to get very far with it.

 

The Macro I'm using is this (if anyone is interested):

 

 
^C^C_-LA;N;CD-PIPEWORK;C;2;CD-PIPEWORK;LT;CONTINUOUS;CD-PIPEWORK;;^C_REC;521,521;D;10;10;@1,1;^C_CHPROP;L;;LA;DETAIL;;^C_CO;L;;521,521,0;541,521,0;^C_CHPROP;L;;LA;CD-PIPEWORK;;^C^C_-LAYMRG;N;DETAIL;;N;CD-PIPEWORK;Y;^C_E;l;;E;L;;^C^C

 

There are a series of these in one menu function. If one of the layers is not present it causes the function to stop. So to have a way of bypassing layers not present would be really useful.

 

Cheers.

Link to comment
Share on other sites

  • Replies 29
  • Created
  • Last Reply

Top Posters In This Topic

  • Lee Mac

    14

  • rob150588

    14

  • lpseifert

    1

  • DVDM

    1

Firstly, welcome to CADTutor rob, hope you like it here.

 

You can invoke LISP functions (such as "IF") within your macro to accomplish this task, however I would opt for making the whole thing into a LISP function in its own right, as, when you include LISP functions inside macros the macro can become somewhat "messy".

 

I'm sure your task could be accomplished with a simple LISP function and I'd be more than happy to write one for you. This can then be called from a custom toolbar button and perform the same tasks as your macro without error.

 

Hope this helps,

 

Lee

Link to comment
Share on other sites

I understand that you are trying to merge layer "detail" into layer "cd-pipework"? Is that correct

 

I see that you are using Express tool "laymrg" to accomplish this.

 

Called an Express tool within LISP is dodgy to say the least, and is better done using either scripts or macros - so I shall go back on what I have said about using a LISP function and so you may be better off sticking to a macro or script.

Link to comment
Share on other sites

Lee,

 

Thanks for your prompt response, and thanks for your welcome. I've seen cadtutor many times, thought it was about time to join.

 

LISP for me is something of a dark art. I've written basic (and I mean very basic) routines for menu macros. And I tend to steer clear of them, simply because I don't know what I'm doing with them.

 

Personally I would prefer the LISP function written into the macro because then the CUI file is the only thing that has to be reloaded. A LISP routine is just another thing to be loaded into the system. I don't have a problem with that, but our other guys are the types that like things to "just work", so I wouldn't put it past them to not load the LISP routine in at all and wonder why it doesn't work :huh:.

 

However, I remember reading some years ago that a LISP routine written externally can be loaded into the system from a macro and then unloaded when the macro is finished ? I may be wrong there though.

 

I would not be adverse to you writing a LISP routine for this purpose, and you would be given full credit for it on our systems. As long as you could explain what the various functions are that are used. I am quite keen to learn them.

 

If you would like anymore information, do not hesitate to ask.

 

Cheers.

 

Rob.

Link to comment
Share on other sites

I understand that you are trying to merge layer "detail" into layer "cd-pipework"? Is that correct

 

I see that you are using Express tool "laymrg" to accomplish this.

 

Called an Express tool within LISP is dodgy to say the least, and is better done using either scripts or macros - so I shall go back on what I have said about using a LISP function and so you may be better off sticking to a macro or script.

 

Yup, that's right. Having done a lot of research into doing this, I finally settled on using the express tool (Not ideal I know :oops: ).

 

I assume the same effect can be achieved using a LISP routine. And probably without the need for the section that draws reference objects for the layers (which is hit and miss at the best of times)...

Link to comment
Share on other sites

lpseifert may have deleted his post for some reason. :)

 

Possibly a mistake in the code - one can only postulate.

again too hasty of a reply, I should test first... and stay away from macros.

Link to comment
Share on other sites

In LISP form (without the use of LayMrg):

 

; Layer Merger ~  Lee McDonnell 18.02.09
; Two Args (strings):
; lay1 = layer to be deleted
; lay2 = layer to be merged to

(defun mlay (lay1 lay2 / ss eLst)
 (vl-load-com)
 (if (and (tblsearch "layer" lay1) (not (eq "0" lay1))
      (not (eq (strcase lay1) (getvar "CLAYER")))
      (tblsearch "layer" lay2)
     (setq ss (ssget "X" (list (cons 8 lay1)
       (if (getvar "CTAB")(cons 410 (getvar "CTAB"))
         (cons 67 (- 1 (getvar "TILEMODE"))))))))
   (progn
     (setq eLst (mapcar 'entget (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))))
     (mapcar '(lambda (x) (entmod (subst (cons 8 lay2) (assoc 8 x) x))) eLst)
     (if (vl-catch-all-error-p
       (vl-catch-all-apply 'vla-Delete (list (vlax-ename->vla-object (tblobjname "LAYER" lay1)))))
   (princ "\n<!> Layer Could not be Deleted <!>")))
   (princ "\n<!> Error in Layer Name Specification <!>")))

Link to comment
Share on other sites

Thanks for that Lee.

 

I'm not entirely sure what to do with it though. :?

 

I pasted that into a new LSP file and apploaded it into CAD. I changed Defun to Defun C: so I could test it on the command line, but running the command produced:

Error: Too few arguments

Which seemed a little odd. So I scanned the code to try to understand it a little and to check if I was missing something. But my LISP knowledge is too limited, so I couldn't make head nor tail of it...

 

Um, help ?

 

Cheers.

 

Rob.

Link to comment
Share on other sites

Ahhh sorry Rob, I should have explained in a lot more detail.

 

The code I posted is only a local function - as I was not sure if you wanted to use it on more than one pair of layers, so I thought I'd keep things open and simple.

 

You will need to create another function, using (defun c: ) and call the sub-function, providing it with the two arguments that it requires - (which is why you returned the error of too few arguments - because the arguments were not specified).

 

I apologise for not explaining this earlier, and I shall include an example for you:

 

; Layer Merger ~  Lee McDonnell 18.02.09
; Two Args (strings):
; lay1 = layer to be deleted
; lay2 = layer to be merged to

(defun mlay (lay1 lay2 / ss eLst)
 (vl-load-com)
 (if (and (tblsearch "layer" lay1) (not (eq "0" lay1))
      (not (eq (strcase lay1) (getvar "CLAYER")))
      (tblsearch "layer" lay2)
     (setq ss (ssget "X" (list (cons 8 lay1)
       (if (getvar "CTAB")(cons 410 (getvar "CTAB"))
         (cons 67 (- 1 (getvar "TILEMODE"))))))))
   (progn
     (setq eLst (mapcar 'entget (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))))
     (mapcar '(lambda (x) (entmod (subst (cons 8 lay2) (assoc 8 x) x))) eLst)
     (if (vl-catch-all-error-p
       (vl-catch-all-apply 'vla-Delete (list (vlax-ename->vla-object (tblobjname "LAYER" lay1)))))
   (princ "\n<!> Layer Could not be Deleted <!>")))
   (princ "\n<!> Error in Layer Name Specification <!>")))

(defun c:test ()
 (mlay "detail" "cd-pipework")
 (princ)
)

As you can see from the above example, I have called the sub-function and provided it with two arguments necessary: "lay1" and "lay2" respectively.

 

You will need to provide these in the correct order for the program to delete the correct layer - an explanation of which argument does what is provided at the top of the code.

 

Hope this clarifies things much better.

 

Cheers

 

Lee

Link to comment
Share on other sites

Thanks for that Lee, worked like a charm :D .

 

I assume it would be a simple case of adding more lines to the list under the "test" function for additional layers ? Ie.

 
(defun c:test ()
 (mlay "detail" "cd-pipework")
 (mlay "origin" "z-origin")
 (mlay "symbol" "z-syymbol")
 (mlay "planning" "cd-planning")
 (princ)
)

Another thing I'd like to check is if it will bypass any of the original layers that are not present in the drawing ? Ultimately I'd like to add about 20-30 of the most commonly used layers from the previous standards to it you see.

 

Many thanks.

 

Rob.

Link to comment
Share on other sites

Oh yeah. Totally forgot to ask. Can the lisp routine be able to create the new layers based on the old layers that are present in the drawing ?

 

For instance; IF layer Concrete exists - Create layer CD-CONCRETE, IF not - Do nothing.

 

Creating layers using macros is messy and it takes a lot of time if there are lots of layers to be created when using and argument such as the one above.

 

I'm probably moving slightly off topic here with this one, and I apologise if I am but I'm not au-fait with the etiquet of online forums.

 

Cheers.

 

Rob.

Link to comment
Share on other sites

Thanks for that Lee, worked like a charm :D .

 

I assume it would be a simple case of adding more lines to the list under the "test" function for additional layers ? Ie.

 
(defun c:test ()
 (mlay "detail" "cd-pipework")
 (mlay "origin" "z-origin")
 (mlay "symbol" "z-syymbol")
 (mlay "planning" "cd-planning")
 (princ)
)

Another thing I'd like to check is if it will bypass any of the original layers that are not present in the drawing ? Ultimately I'd like to add about 20-30 of the most commonly used layers from the previous standards to it you see.

 

Many thanks.

 

Rob.

 

Hi Rob,

 

Yes, you can add extra lines to change more than one layer.

 

Yes, the code will bypass any layers that aren't in the drawing as it includes "(tblsearch "layer" lay1)" in the IF function to check if the layer is in the drawing first. - if it isn't, the function will carry on running and not cause an error, but won't do anything with those layers.

 

I believe it will also notify you in this case.

 

There are other restrictions on the layer name also, that will prevent the function from continuing, namely:

 

  • lay1 and lay2 must be in the drawing
  • lay1 cannot be equal to "0"
  • lay1 cannot be the current layer.

Hope this helps :)

 

Lee

Link to comment
Share on other sites

Oh yeah. Totally forgot to ask. Can the lisp routine be able to create the new layers based on the old layers that are present in the drawing ?

 

For instance; IF layer Concrete exists - Create layer CD-CONCRETE, IF not - Do nothing.

 

Creating layers using macros is messy and it takes a lot of time if there are lots of layers to be created when using and argument such as the one above.

 

I'm probably moving slightly off topic here with this one, and I apologise if I am but I'm not au-fait with the etiquet of online forums.

 

Cheers.

 

Rob.

 

No worries Rob, I am quite happy to include a line of coding that basicallly says, "if lay2 is not here, create it please..."

 

This should give you almost no restrictions on the amount of layers to add.

 

Not a problem at all.

 

Thanks

 

Lee

Link to comment
Share on other sites

Here is the code with the extra line for layer creation:

 

; Layer Merger ~  Lee McDonnell 18.02.09
; Two Args (strings):
; lay1 = layer to be deleted
; lay2 = layer to be merged to

(defun mlay (lay1 lay2 / vlst ovar ss eLst)
 (vl-load-com)
 (setq vlst (list "cmdecho" "clayer")
   ovar (mapcar 'getvar vlst))
 (setvar "cmdecho" 0)
 (if (and (tblsearch "layer" lay1) (not (eq "0" lay1))
      (not (eq (strcase lay1) (getvar "CLAYER")))
     (setq ss (ssget "X" (list (cons 8 lay1)
       (if (getvar "CTAB")(cons 410 (getvar "CTAB"))
         (cons 67 (- 1 (getvar "TILEMODE"))))))))
   (progn
     (if (not (tblsearch "layer" lay2)) (command "-layer" "m" lay2 ""))
     (setq eLst (mapcar 'entget (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))))
     (mapcar '(lambda (x) (entmod (subst (cons 8 lay2) (assoc 8 x) x))) eLst)
     (if (vl-catch-all-error-p
       (vl-catch-all-apply 'vla-Delete (list (vlax-ename->vla-object (tblobjname "LAYER" lay1)))))
   (princ "\n<!> Layer Could not be Deleted <!>")))
   (princ "\n<!> Error in Layer Name Specification <!>"))
 (mapcar 'setvar vlst ovar))

(defun c:test ()
 (mlay "detail" "cd-pipework")
 (princ)
)

 

On a side note, one may want to use an error handler code with this because I am fiddling with two system variables, namely: "cmdecho" and "clayer", but these are reset at the end of the sub-function and so it shouldn't cause a problem.

 

Cheers

 

Lee

Link to comment
Share on other sites

Thank for that Lee. It would be useful if the routine can set the layer to 0 automatically. That would mean a user could be on a layer such as Detail and the function would still run. I tried adding in code like:

(setlayer "0")

...but was unsure where to put it without producing a "Too few arguments" error.

 

Another thing I noticed is that the function can't change the layers of objects nested within blocks, whereas the LAYMRG tool can as it redefines the block with the new layer. Is that somehing that can be written into the routine ? Or would the -laymrg command have to be run as a macro ?

 

And on a final note (I will shut up in a minute :P ). Is it at possible for the routine to be able to set colours and linetypes for layers that it is creating. I figured that might involve a lot of code, and would probably involve some sort of table for the routine to reference to.

 

Cheers,

 

Rob.

 

Here is the code with the extra line for layer creation:

 

; Layer Merger ~  Lee McDonnell 18.02.09
; Two Args (strings):
; lay1 = layer to be deleted
; lay2 = layer to be merged to

(defun mlay (lay1 lay2 / vlst ovar ss eLst)
 (vl-load-com)
 (setq vlst (list "cmdecho" "clayer")
   ovar (mapcar 'getvar vlst))
 (setvar "cmdecho" 0)
 (if (and (tblsearch "layer" lay1) (not (eq "0" lay1))
      (not (eq (strcase lay1) (getvar "CLAYER")))
     (setq ss (ssget "X" (list (cons 8 lay1)
       (if (getvar "CTAB")(cons 410 (getvar "CTAB"))
         (cons 67 (- 1 (getvar "TILEMODE"))))))))
   (progn
     (if (not (tblsearch "layer" lay2)) (command "-layer" "m" lay2 ""))
     (setq eLst (mapcar 'entget (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))))
     (mapcar '(lambda (x) (entmod (subst (cons 8 lay2) (assoc 8 x) x))) eLst)
     (if (vl-catch-all-error-p
       (vl-catch-all-apply 'vla-Delete (list (vlax-ename->vla-object (tblobjname "LAYER" lay1)))))
   (princ "\n<!> Layer Could not be Deleted <!>")))
   (princ "\n<!> Error in Layer Name Specification <!>"))
 (mapcar 'setvar vlst ovar))

(defun c:test ()
 (mlay "detail" "cd-pipework")
 (princ)
)

 

On a side note, one may want to use an error handler code with this because I am fiddling with two system variables, namely: "cmdecho" and "clayer", but these are reset at the end of the sub-function and so it shouldn't cause a problem.

 

Cheers

 

Lee

Link to comment
Share on other sites

I believe that the LAYMRG and all other LAY- commands are part of Autocad 2009 now, no longer an express tool.

 

Yeah, they've been a part of CAD since the 2007 release. Up till then they were just part of the Express Tools.

 

That's why I didn't feel too bad about using them in the original macro.:roll:

Link to comment
Share on other sites

My apologies Rob - working on a mere '04 version, I wasn't aware that they had been incorporated into the full version...

 

With this knowledge, it would probably be easier just to use the LayMrg function within the code.

 

As for your other request to have the colour and linetype.. this is not too difficult to incorporate - I shall look into it :)

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...