V4Mp Posted December 3, 2020 Posted December 3, 2020 (edited) Hello @all I have an edited code. It creates a new layout with a new name. The new name is set by a number a user can input into autocad (variable "num"). Layouts get the names: 2-1, 2-2, 3-1, 3-2 and so on. What the code should do, is 1. Take the name of the new page-layout as "num" (ie 4) 2. Create two new layouts (ie 4-1 and 4-2) 3. Move these layouts to the position they should be. (ie 3-2 > 4-1 > 4-2) I wanted to repeat the codes, when the number of the layout befor not exists. (ie our num is 6 and we have the layout 3-1, 3-2 , 8-1, 8-2) And then move the layout behind the next logic number. (in the example it should be 3-2, 6-1, 6-2, 8-1, 8-2) I tried to edit it, but failed. Anyone who can help me? What I tried was, to repeat the code until no error. Every error "value" should be changed to "num_befor" minus 1 and the fix string "-2", because "-2" is the last layout of the number. (ie num_befor = 5, because we have 6 as num, after an error the "value" should be changed to 4-2 and then next error to 3-2. With an error the function should be repeated with the new variables "value for tname2" as tname2 is our layout behind we try to move the layout each try. Hopefully you can understand me. (tab-after num_page1 num_page_befor num) (setvar 'CMDECHO oCMDECHO) (princ) ) (defun tab-after (tname1 tname2 num / tabs pos1 pos2) (vl-load-com) (restart-case (/ tname1 tname2 num) (return-zero () :report "Return 0" 0) (divide-by-one () :report "Divide by 1" (/ x 1)) (setq tabs (vla-get-Layouts (vla-get-Activedocument (vlax-get-acad-object)) ) ) (setq pos1 (vla-get-TabOrder (vla-item tabs tname1)) pos2 (vla-get-TabOrder (vla-item tabs tname2)) ) (if (> pos1 pos2) (setq pos2 (1+ pos2))) (vla-put-TabOrder (vla-item tabs tname1) pos2) (princ) (set-new-divisor (value) (setq num_befor (- (atoi num) 1)) (setq value (strcat num_befor "-2")) ;; and call the divide function with the new value… ;; … possibly catching bad input again! (tab-after tname1 value num) ) ) ) Edited December 3, 2020 by V4Mp Quote
tombu Posted December 3, 2020 Posted December 3, 2020 There's plenty of code out there for this already. I usually rearrange them by dragging tabs around but use Lee Mac's http://www.lee-mac.com/tabsort.html from time to time. Coping is simply ctrl+dragging tabs and for adding layouts from templates Lee Mac's http://www.lee-mac.com/steal.html. Using layout names that describe what's on them for makes them a lot easier for everyone to follow. I'm guessing you're referencing tab names as page numbers? I use a modified version of Lee Mac's http://www.lee-mac.com/layoutfield.html for those that automatically modifies them when they're rearranged, added, or deleted. I don't plan my posts to promote Lee Mac's code but I use a lot of it every day. Thanks Lee! Quote
V4Mp Posted December 3, 2020 Author Posted December 3, 2020 (edited) Thanks for your reply. No, the layoutname describe what it is. In fact the complete drawing is a building and the numbers are specific parts of the building. I knew already lee-mac's version. But for me it's over the top for the lisp I am using. It would consume to mutch time for me to edit the lee-mac code. But I think I am changing my strategy. Insted of moving one tab to the correct position, I am now sorting all tabs. That will do the same and in the end it helps provending mistakes. Edited December 3, 2020 by V4Mp Quote
Jonathan Handojo Posted December 5, 2020 Posted December 5, 2020 (edited) This one will sort all the desired tabs and places it at the end of the list of all the layouts. (defun c:test ( / acd ind len lst nm sortl) (while (progn (initget 6) (setq nm (getint "\nSpecify number <exit>: ")) (cond ((not nm) nil) ((progn (setq nm (itoa nm)) (vl-some '(lambda (x) (if (wcmatch x (strcat nm "`-[12]")) (princ (strcat "\nLayout name " x " already exists.")) ) ) (layoutlist) ) ) ) ) ) ) (if nm (progn (setq acd (vla-get-Layouts (vla-get-ActiveDocument (vlax-get-acad-object)))) (foreach x (list (strcat nm "-1") (strcat nm "-2")) (vla-Add acd x) ) (setq lst (layoutlist) sortl (vl-remove-if-not '(lambda (x) (wcmatch x "#*`-[12]")) lst) ind (vl-sort sortl '(lambda (a b) (if (= (atoi a) (atoi b)) (< (atoi (substr a (+ (vl-string-search "-" a) 2))) (atoi (substr b (+ (vl-string-search "-" b) 2))) ) (< (atoi a) (atoi b)) ) ) ) len (length lst) ) (mapcar '(lambda (x) (vla-put-TabOrder (vla-item acd x) len)) ind) ) ) (princ) ) Edited December 5, 2020 by Jonathan Handojo 1 Quote
V4Mp Posted December 9, 2020 Author Posted December 9, 2020 (edited) Jonathan Handojo Thank you for your replay. The code works, but I have more then 10 layouts. If I use 2, 6, 9 everything ok. But I need also 22 or 123. That could be rooms. With your code a number with two or three places do not work. I have found a simple function that does the job, but it sorts only for one place. In example the result is 1, 2, 5, 55, 6 but should be 1, 2, 5, 6, 55 Edited December 9, 2020 by V4Mp Quote
pkenewell Posted December 9, 2020 Posted December 9, 2020 Unfortunately you are dealing with Windows sorting rules. You need to pad the numbers with leading zeros so that the layouts have something like "001, 002, 005, 006, 055", then you can remove the leading zeros after the sort by using (vl-string-left-trim). Quote
Lee Mac Posted December 9, 2020 Posted December 9, 2020 Use an alphanumerical sorting function to interpret & sort numerical data within the string, rather than sorting character-wise, e.g. to sort layouts alphanumerically, you might use: (defun c:sortlayouts ( / ls1 ls2 ord ) (vlax-for lyt (vla-get-layouts (vla-get-activedocument (vlax-get-acad-object))) (if (= :vlax-false (vla-get-modeltype lyt)) (setq ls1 (cons (strcase (vla-get-name lyt)) ls1) ls2 (cons lyt ls2) ) ) ) (setq ord 0) (foreach idx (LM:alphanumsort-i ls1) (vla-put-taborder (nth idx ls2) (setq ord (1+ ord))) ) (princ) ) ;; Alphanumerical Sort-i - Lee Mac ;; Sorts a list of strings containing a combination of alphabetical & numerical characters and returns the indices. (defun LM:alphanumsort-i ( lst ) (vl-sort-i (mapcar 'LM:splitstring lst) (function (lambda ( a b / x y ) (while (and (setq x (car a)) (setq y (car b)) (= x y) ) (setq a (cdr a) b (cdr b) ) ) (cond ( (null x) b) ( (null y) nil) ( (and (numberp x) (numberp y)) (< x y)) ( (numberp x)) ( (numberp y) nil) ( (< x y)) ) ) ) ) ) ;; Split String - Lee Mac ;; Splits a string into a list of text and numbers (defun LM:splitstring ( str ) ( (lambda ( l ) (read (strcat "(" (vl-list->string (apply 'append (mapcar (function (lambda ( a b c ) (cond ( (or (= 34 b) (= 92 b)) (list 32 34 92 b 34 32) ) ( (or (< 47 b 58) ;(and (= 45 b) (< 47 c 58) (not (< 47 a 58))) (and (= 46 b) (< 47 a 58) (< 47 c 58)) ) (list b) ) ( (list 32 34 b 34 32)) ) ) ) (cons nil l) l (append (cdr l) '(( ))) ) ) ) ")" ) ) ) (vl-string->list str) ) ) (vl-load-com) (princ) 3 Quote
V4Mp Posted December 14, 2020 Author Posted December 14, 2020 Thank you for the information. Lee Mac are the best! Works Quote
Recommended Posts
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.