Rewrite Visual Lisp to "plain" AutoLISP

Rewrite Visual Lisp to "plain" AutoLISP

tomaz.og
Participant Participant
3,883 Views
19 Replies
Message 1 of 20

Rewrite Visual Lisp to "plain" AutoLISP

tomaz.og
Participant
Participant

Hello everyone!

 

I'm trying to load a LISP to my AutoCAD Mac 2018.

The lisp I am trying to load is to automatically number my layout tabs according to their position/order based on CTAB field, so that if I add or reorder the layouts, the pages would be automatically renumbered.

 

Apparently someone has done it, but as a Visual Lisp, which I found in this page < https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/auto-number-lisp-based-on-layout-tab...

But since I work with AutoCAD Mac, it doesn't work for me.

 

I would like to know if anyone have a plain AutoLISP with the same function as this one, or if someone knows how to rewrite the Visual Lisp format into "plain" AutoLISP so I could use it on my AutoCAD Mac.

I thank in advance everyone who can help! 

 

0 Likes
Accepted solutions (1)
3,884 Views
19 Replies
Replies (19)
Message 2 of 20

devitg
Advisor
Advisor

@tomaz.og , please upload or paste as code here , the LISP, and your sample.dwg

 

Message 3 of 20

CodeDing
Mentor
Mentor

@tomaz.og ,

 

I only briefly glanced at the link you provided.. But based what you wrote in your question, there's no method (without Visual LISP) to Automatically renumber your layout sheets. You would need to run a command when you wish for them to be updated..

So, if you wish for sheets to be numbered based on their layout position in AutoCAD, this command should work for you:

(defun c:LIO ( / LayoutListOrdered cnt prefix postfix)
  ;Layouts In Order
  ;helper function
  (defun LayoutListOrdered ( / dLays lays oLays cnt)
    (setq dLays (cdr (assoc -1 (dictsearch (namedobjdict) "ACAD_LAYOUT"))))
    (setq lays (mapcar '(lambda (l) (cons (cdr (assoc 71 (dictsearch dLays l))) l)) (layoutlist)))
    (repeat (1- (setq cnt (1+ (length lays))))
      (setq oLays (cons (cdr (assoc (setq cnt (1- cnt)) lays)) oLays))
    );repeat
  );defun
  ;begin work
  (setq prefix "")  ;<-- you can add a prefix here if you like
  (setq postfix "") ;<-- you can add a postfix here if you like
  (setq cnt 0)
  (setvar 'CMDECHO 0)
  (foreach lay (LayoutListOrdered)
    (command "-LAYOUT" "r" lay (strcat prefix (itoa (setq cnt (1+ cnt))) postfix))
  );foreach
  (setvar 'CMDECHO 1)
  (prompt "\nLIO Complete.")
  (princ)
);defun

Best,

~DD

Message 4 of 20

tomaz.og
Participant
Participant

Hi DD!

Thank you so much for your answer! Actually, when I said I wanted it automatically done, I meant with a command, so you nailed it 🙂 

 

Since it's my first time using lisp, I'm not sure what to do with the orange texts in the code you sent. Should I erase them?


So just to be sure, I should paste this code into a plain text editor and save it as ".lsp". Than I'll load it into AutoCAD through appload right?

I'm sorry if that's too basic, but I've never done it before.

Thank you very much for the help!

0 Likes
Message 5 of 20

tomaz.og
Participant
Participant

Hi @devitg thank you for replying!

 

The code (which is also on the link I posted, if you have any doubts) is the following:

(defun c:somefunc  (/ adoc layouts layoutname ss1 ent entdata)
 (setq layouts (vla-get-layouts (setq adoc (vla-get-activedocument (vlax-get-acad-object)))))
 (if (setq ss1 (ssget "_x" '((0 . "INSERT") (2 . "_11x17"))))
  (mapcar
   '(lambda (x)
     (setq ent     (cadr x)
           entdata (entget ent))
     (while (/= (cdr (assoc 0 entdata)) "SEQEND")
      (cond ((= "SHT#" (cdr (assoc 2 entdata)))
             (vlax-for y  layouts
              (cond ((=
                     (vla-get-name (vla-objectidtoobject adoc (vla-get-ownerID (vlax-ename->vla-object (cdr (assoc 330 entdata))))))
                     (vla-get-name (vla-get-block y)))
                    (entmod (subst (cons 1 (itoa (vla-get-taborder y))) (assoc 1 entdata) entdata)))
                    (T ())))
              ))
            (setq entdata (entget (setq ent (entnext ent))))))
     (ssnamex ss1))
  "No titleblocks found!")
 (princ))

 

And the sample is also attached. Thanks!!

 

 

0 Likes
Message 6 of 20

CodeDing
Mentor
Mentor

@tomaz.og ,

 

No problem, everybody has to start somewhere.

For the Orange text, I was only highlighting some comments in my code (to make it easier to spot & read).

The only 2 areas you might want to change would be next to my comments.

As it currently stands, it will number your layouts like so: 1,2,3,....

But if you add a prefix like this example:

  (setq prefix "LAY_")

...it will number your layouts like so: LAY_1,LAY_2,LAY_3,....

Or, if you add a postfix like this example:

  (setq postfix "_BLAH")

...it will number your layouts like so: 1_BLAH,2_BLAH,3_BLAH,....

Or you can use both, or you don't even have to use them at all.

 

Also, yes you can save a text file with the ".lsp" file type to create the lisp, then use the "Manage" tab or the APPLOAD command to load the routine. If you use it often, you can add it to your Startup Suite.

 

Hope that helps! Best,

~DD

0 Likes
Message 7 of 20

Sea-Haven
Mentor
Mentor

This code snippet may be useful as well padding the layout when less than 10.

 

; if less than 10
    (if (< (car dwgnum) 10.0) 
      (setq newstr2 (strcat dwgname "-D0"  (rtos sheetnum 2 0)))
      (setq newstr2 (strcat dwgname "-D"  (rtos sheetnum 2 0)))
    )

 

Message 8 of 20

tomaz.og
Participant
Participant

Hello DD!

 

About the orange parts, I kinda got the prefix and postfix at first, but I wasn't 100% sure about it. Thank you for the explanation.

 

So I'm still not managing to make it work. But now CAD is at least recognising the command. In my previous attempts, it wasn't even doing so. So I'm uploading a video of every step I'm taking (also described below) so maybe you could help me identify what I am doing wrong... I have a feeling it might be in the field configuration...? I really don't know...

So here is what I'm doing:


1) Copy the code you provided to plain text editor, save as ".rtf" than rename it to ".lsp". (I first copy it to google translator, just so it loses its color and shading properties - when I didn't do so, AutoCAD wasn't even recognising the command.)

2) Use a CTAB field to "number" the layout pages according to its name. (I did this because of what I first read in the forum discussion from the link I mentioned on my first post here.)

 

3) Load LISP through appload.

4) Enter command "lio" - CAD recognises it, but doesn't seem to work.

Thanks again for the help!!
I'm hoping to eventually find the light in the end of this tunnel 🙂

Regards,

 

Tomaz

Message 9 of 20

CodeDing
Mentor
Mentor

@tomaz.og ,

 

Hmmmm, this is very weird. Thank you for the video it was useful to see.

What does the command history say after you run the command? If the command is visible and can be seen when you type it, then the Lisp was loaded just fine. There must be something wrong with the way the code was written perhaps. I do not use Mac so I am unfamiliar with what it Can and Can Not do. 

 

Can you show me the command history after you run the command? Perhaps it will tell us something.

 

BUT FIRST - Please remove these 2 lines of code before you load the Lisp.. Then run it and tell us what the history says:

  .....
  (setvar 'CMDECHO 0) <-- remove this entire line from original
  .....
  (setvar 'CMDECHO 1) <-- remove this entire line from original
  .....
Message 10 of 20

CodeDing
Mentor
Mentor

@tomaz.og ,

 

Also, you seem to be contradicting yourself with these 2 statements.. Can you clarify please?

----- 1


@tomaz.og wrote:

The lisp I am trying to load is to automatically number my layout tabs according to their position/order based on CTAB field


----- 2

image.png

0 Likes
Message 11 of 20

tomaz.og
Participant
Participant

@CodeDing 

 

Sorry for the misunderstanding... I will try to explain better.

 

What I meant is that I need a command that will number my layout pages according to their order, regardless of their name. So if I have the following layout tabs named "red", "blue" and "yellow" - in this order - they will be numbered "1"(red), "2"(blue) and "3"(yellow). And the number itself on each page is a CTAB field.


If you watch the video from the discussion in the link from my first post, maybe it will be clearer. From what I understood when I saw it, there is a command (lisp) that will modify the CTAB fields in each page so that each one will be a number. And this number corresponds to the layout position/order among the tabs. Maybe I'm wrong and the numbers on each page aren't a CTAB field. I don't know...

-----

So, I excluded the two lines you mentioned from the lisp code, but it's still the same as before. I also tried it on AutoCAD on windows just to be sure, but didn't work as well... I texted in another forum discussion with @maxim_k about AutoCAD for Mac and from what he told me, as soon as it isn't a Visual Lisp, it should work on AutoCAD Mac.

 

Do you think the problem can be that I shouldn't be using a CTAB field as the page number?

Below is the command history

 

Captura de Tela 2020-08-04 às 15.16.02.png

 

Message 12 of 20

ronjonp
Mentor
Mentor

Give this a try, it sounds like you don't need to rename the tab, just append the ctab text field with the taborder number. 

 

(defun c:foo (/ e i l n s)
  ;; RJP » 2020-08-04
  (if (and (setq s (ssget "_X" '((0 . "Text") (1 . "*%<\\AcVar ctab>%*"))))
	   (setq l (cdr (assoc -1 (dictsearch (namedobjdict) "ACAD_LAYOUT"))))
      )
    (repeat (setq i (sslength s))
      (setq n (dictsearch l (cdr (assoc 410 (entget (setq e (ssname s (setq i (1- i)))))))))
      (entmod (append (entget e)
		      ;; Modify below to set format you want ->> " (%<\\AcVar ctab>%)"
		      (list (cons 1 (strcat (itoa (cdr (assoc 71 n))) " (%<\\AcVar ctab>%)")))
	      )
      )
    )
  )
  (princ)
)

 

Could be written like this too:

(defun c:foo (/ e el i n s)
  ;; RJP » 2020-08-04
  (if (setq s (ssget "_X" '((0 . "Text") (1 . "*%<\\AcVar ctab>%*"))))
    (repeat (setq i (sslength s))
      (and
	(setq e (ssname s (setq i (1- i))))
	(setq n (cdr (assoc 330 (setq el (entget e)))))
	(setq n (cdr (assoc 340 (entget n))))
	(entmod
	  (append el
		  ;; Modify below to set format you want ->> " (%<\\AcVar ctab>%)"
		  (list (cons 1 (strcat (itoa (cdr (assoc 71 (entget n)))) " (%<\\AcVar ctab>%)")))
	  )
	)
      )
    )
  )
  (princ)
)

 

Message 13 of 20

CodeDing
Mentor
Mentor

@tomaz.og ,

 

Ok thank you for explaining further. Well, based on what it sounds like you're wanting now, can you please post a sample dwg for me to look at?

 

What is going to end up happening, is that you will need to have a title block on each layout (preferably the same title block on every layout) and we will have an attribute in that we can search for in that title block.. when you run the command then we will place the page # into that Attribute. No Fields necessary. I think that is where I was getting confused.


0 Likes
Message 14 of 20

tomaz.og
Participant
Participant

@CodeDing 

 

That makes total sense!! Thats exactly what I want 🙂

I just attached the file sample I'm working on.

 

 

 

Message 15 of 20

tomaz.og
Participant
Participant

Hi @ronjonp !


Thanks for replying 🙂

I tried these too codes but AutoCAD isn't recognising the command... 

0 Likes
Message 16 of 20

ronjonp
Mentor
Mentor

If you use single line text rather than mtext it works on my test. You really need to look into block attributes to get this drawing as you'd like it.

2020-08-04_14-00-35.gif

 

0 Likes
Message 17 of 20

tomaz.og
Participant
Participant

Hi @ronjonp 

 

So as I said, I think the lisp isn't properly loading into AutoCAD, because when I type the command "foo" it says it's an unknown command.

But concerning the text, I'm not sure if I got it. It's my first time using field and lisp, so maybe I'm not getting what is rather obvious for you, sorry.

 

I didn't understand if I need to use just a single line text instead of the CTAB field or if I need to reconfigure the CTAB field somehow. I didn't understand the gif you posted, sorry...

0 Likes
Message 18 of 20

CodeDing
Mentor
Mentor
Accepted solution

@tomaz.og ,

 

I'm starting to wonder if the reason your LISPs are acting weird is because you're using a Rich Text Format when saving to a .lsp file..?

 

I have created a code which I believe will work for you now. If you copy / paste my code below and it does NOT work when you run it, then try Using My Attached LSP File (it's the same code, but I created it instead of you having to) and if that DOES work, then now we will know that you can not use your RTF editor to create LSP files.

 

ALSO, I have attached your dwg file showing the attribute I used.. You must add an attribute to your title block to make this work. I named mine "PG#".

 

(defun c:LIO ( / ss e eg cnt g2g pgNo dLays attName shtName)
  ;Layouts In Order
  (setq attName "PG#")
  (if (setq ss (ssget "_X" '((0 . "INSERT") (2 . "MICRA.carimbo") (-4 . "<NOT") (410 . "Model") (-4 . "NOT>"))))
    (progn
      (setq dLays (cdr (assoc -1 (dictsearch (namedobjdict) "ACAD_LAYOUT"))))
      (repeat (setq cnt (sslength ss))
        (setq e (ssname ss (setq cnt (1- cnt))))
        (setq eg (entget e))
        (setq g2g nil)
        (setq shtName (cdr (assoc 410 eg)))
        (setq pgNo (cdr (assoc 71 (dictsearch dLays shtName))))
        (while (and (not g2g) (/= "SEQEND" (cdr (assoc 0 eg))))
          (if (and (member '(0 . "ATTRIB") eg)
                   (member (cons 2 attName) eg))
            (setq eg (subst (cons 1 (itoa pgNo)) (assoc 1 eg) eg)
                  g2g t)
            (setq e (entnext e) eg (entget e))
          );if
        );while
        (if g2g (entmod eg))
      );repeat
      (command "_.REGEN")
    );progn
  ;else
    (prompt "\nTitle Block(s) not found.")
  );if
  (prompt "\nLIO Complete.")
  (princ)
);defun

 

Fingers crossed. Best,

~DD

Message 19 of 20

tomaz.og
Participant
Participant

Hi @CodeDing 

As you guessed, copying the code and saving it in ".rtf" format to then convert it to ".lsp" didn't work. But when I used the lisp you attached it worked perfectly! So apparently besides using an attribute instead of a field, there was this technicality in the way of making it work...

 

I can't thank you enough for the effort you put into helping me! This will be a game changer for me and my partners in our office. Thank you thank you thank you!

Wish you all the best!
Regards,

Tomaz

Message 20 of 20

Sea-Haven
Mentor
Mentor

Why not add the total number of layouts at same time, as you have how many -1 for model, an extra attribute. I have like what you have done and looks for block attributes. Can do a confirm total as we have some extra layouts created by 3rd party but may not be used.

0 Likes