Sheet "##" of Sheets

Sheet "##" of Sheets

lylegrisso
Participant Participant
2,989 Views
22 Replies
Message 1 of 23

Sheet "##" of Sheets

lylegrisso
Participant
Participant

sheet of sheets.JPG

 

I'm trying to figure out how to get a lisp routine to change the ## from the "page" section to auto insert the page number (not "ctab" name) based on it's position in the layout tabs. I'm already using the lisp routine for the total number of pages and that is working great.

0 Likes
Accepted solutions (1)
2,990 Views
22 Replies
Replies (22)
Message 2 of 23

paullimapa
Mentor
Mentor

found this little lisp routine on this thread that returns the layouts in order:

(defun getLayoutOrderList( / lst mklist mappend flatten)
  (defun mklist (x) (if (listp x) x (list x)))
  (defun mappend (fn lst)(apply 'append (mapcar fn lst)))
  (defun flatten (expr)(mappend 'mklist expr))
  (vlax-for lay
    (vla-get-layouts (vla-get-activedocument (vlax-get-acad-object)))
    (setq lst (cons (list (vla-get-taborder lay)(vla-get-name lay)) lst))
  )
  (cdr(flatten(mapcar 'cdr (vl-sort lst '(lambda (a b) (< (car a)(car b)))))))
)
you can call the function like this (vl-position (getvar"ctab") (getLayoutOrderList)) and add 1 to it return the position

 


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

pbejse
Mentor
Mentor

@lylegrisso wrote:

I'm already using the lisp routine for the total number of pages and that is working great.


Curious, what is the field source for that total number of pages - " of 11" <--- ? 

 

0 Likes
Message 4 of 23

ronjonp
Advisor
Advisor

Why not number them in the sheet set manager? It looks like you're already heavily using fields already.

ronjonp_0-1663695099044.png

If you want to do this with code try this. You'll need to supply the blockname of your attributed block and the tag you wish to fill out. IMO the sheet set manager is a bit tidier though.

 

(defun c:foo (/ a bn c e s tg)
  ;; Name of your attribute block
  (setq bn "TBINFO")
  ;; Name of the attribute tag to fill out
  (setq tg "SHEET#")
  (cond	((setq s (ssget "_X" (list '(0 . "INSERT") '(410 . "~Model") (cons 2 bn) '(66 . 1))))
	 (setq a (cdr (assoc -1 (dictsearch (namedobjdict) "ACAD_LAYOUT"))))
	 (foreach e (mapcar 'cadr (ssnamex s))
	   (setq c (dictsearch a (cdr (assoc 410 (entget e)))))
	   ;; Function not available in Bricscad
	   (setpropertyvalue e tg (itoa (cdr (assoc 71 c))))
	 )
	)
  )
  (princ)
)

 

 

0 Likes
Message 5 of 23

lylegrisso
Participant
Participant

pbejse

 

I'm using this lisp to get the total number

(vlr-command-reactor nil '((:vlr-commandWillStart . _totalLayoutsReactor)))

0 Likes
Message 6 of 23

lylegrisso
Participant
Participant

ronjonp

I'm not using the sheet set manager due to the client.
I tried your code (after changing the block name and attribute name) and it seems to bring up the visual LISP console, but it's not reacting to the drawing.

paulli_apa
your code didn't work with this either.

0 Likes
Message 8 of 23

ronjonp
Advisor
Advisor

@lylegrisso 

Post a sample drawing with your titleblock. For it to "react" to your drawing you'd need to include it in the "_totalLayoutsReactor" code that you already have.

0 Likes
Message 9 of 23

lylegrisso
Participant
Participant

@ronjonp
here is a sample dwg with my border.

also not sure if it matters but I'm using Acad 2023

0 Likes
Message 10 of 23

ronjonp
Advisor
Advisor
Accepted solution

@lylegrisso wrote:

@ronjonp
here is a sample dwg with my border.

also not sure if it matters but I'm using Acad 2023


Worked here see attached:

(defun c:foo (/ a bn c e s tg)
  ;; Name of your attribute block
  (setq bn "BORDER")
  ;; Name of the attribute tag to fill out
  (setq tg "SHT")
  (cond	((setq s (ssget "_X" (list '(0 . "INSERT") '(410 . "~Model") (cons 2 bn) '(66 . 1))))
	 (setq a (cdr (assoc -1 (dictsearch (namedobjdict) "ACAD_LAYOUT"))))
	 (foreach e (mapcar 'cadr (ssnamex s))
	   (setq c (dictsearch a (cdr (assoc 410 (entget e)))))
	   ;; Function not available in Bricscad
	   (setpropertyvalue e tg (itoa (cdr (assoc 71 c))))
	 )
	)
  )
  (princ)
)

I'm using AutoCAD 2023 as well.

 

0 Likes
Message 11 of 23

lylegrisso
Participant
Participant

@ronjonp 

still can't seem to get it to work on my end. I'm not sure why, I copied the code and tried it but the dwg didn't change on my end and the dwg you gave back wouldn't go beyond 11 on the sheet number, even though the total number updated fine.

0 Likes
Message 12 of 23

ronjonp
Advisor
Advisor

@lylegrisso 

You'd have to run the code again after you make changes .. the other "_totalLayoutsReactor" code you mentioned runs on a reactor which is code that "reacts" to changes/commands automatically.

0 Likes
Message 13 of 23

lylegrisso
Participant
Participant

@ronjonp 
as you can see from this picture, this is what im getting every time i try to load it.

 

sheet.JPG

and then nothing from the dwg changes. 

0 Likes
Message 14 of 23

ronjonp
Advisor
Advisor

Are you typing "foo" on the command line after you load it? It does not run automatically.

 

If you want it to run automatically after load then add this line at the end:

ronjonp_0-1663705618697.png

 

0 Likes
Message 15 of 23

paullimapa
Mentor
Mentor

Any reason why you don't want to run PageOf.vlx (my reply message 7)?

After loading the vlx, works pretty well on your SHT attribute.

The only thing you need to do is edit & remove the text you don't want

paulli_apa_0-1663705862269.png

 


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

ronjonp
Advisor
Advisor

@paullimapa wrote:

Any reason why you don't want to run PageOf.vlx (my reply message 7)?


@paullimapa 

For me I don't run compiled code unless I created it and or I completely trust the author. Compiled code for this simple task is unnecessary IMO.

0 Likes
Message 17 of 23

paullimapa
Mentor
Mentor

I typically don't like to use compiled code either. But since this little vlx file gets the job done, I thought I share it so OP is aware.


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

Sea-Haven
Mentor
Mentor

Another example it uses the layout name pulling the number from it, but the layout number could be used instead.

 

;;-------------------=={ Parse Numbers }==--------------------;;
;;                                                            ;;
;;  Parses a list of numerical values from a supplied string. ;;
;;------------------------------------------------------------;;
;;  Author: Lee Mac, Copyright © 2011 - www.lee-mac.com       ;;
;;------------------------------------------------------------;;
;;  Arguments:                                                ;;
;;  s - String to process                                     ;;
;;------------------------------------------------------------;;
;;  Returns:  List of numerical values found in string.       ;;
;;------------------------------------------------------------;;

(defun LM:ParseNumbers ( s )
  (
    (lambda ( l )
      (read
        (strcat "("
          (vl-list->string
            (mapcar
              (function
                (lambda ( a b c )
                  (if
                    (or
                      (< 47 b 58)
                      (and (= 45 b) (< 47 c 58) (not (< 47 a 58)))
                      (and (= 46 b) (< 47 a 58) (< 47 c 58))
                    )
                    b 32
                  )
                )
              )
              (cons nil l) l (append (cdr l) (list nil))
            )
          )
          ")"
        )
      )
    )
    (vl-string->list s)
  )
)
; end of lee-mac

; start of update

(DEFUN ah:sheetupdate1 ( / DOC LAY PLOTABS LEN TABNAME DWGNUM OLDTAG1 SHEETNUM NEWSTR1 ATT ss1)
(setq doc (vla-get-activedocument (vlax-get-acad-object)))
(setq plotabs '())
(vlax-for lay (vla-get-Layouts doc)
  (setq plotabs (cons (vla-get-name lay) plotabs))
)
(setq len (length plotabs))

(setq x 0)
(setq oldtag1 "SHTNO.") ;attribute tag name change to suit
(repeat len
  (setq tabname (nth x plotabs))
  (if (/= tabname "Model")
    (progn
      (setvar 'ctab tabname)
      (command "pspace")
      (setq ss1 (ssget "x"  (list (cons 0 "INSERT") (cons 2 "Your title block name")(cons 410 tabname))))
      (setq sheetnum  (abs (car (Lm:parsenumbers tabname))))
      
      (setq newstr1 (STRCAT (rtos sheetnum 2 0) " of " (RTOS (- LEN 1) 2 0)))
 
      (foreach att (vlax-invoke (vlax-ename->vla-object (ssname SS1 0 )) 'getattributes)
        (if (= oldtag1 (strcase (vla-get-tagstring att)))
        (vla-put-textstring att newstr1) 
        )
       )
    )
 )
(setq x (+ x 1))
) ; end repeat

)
; end defun ah

(ah:sheetupdate1)
0 Likes
Message 19 of 23

paullimapa
Mentor
Mentor

If having a field (automatic update) is not a requirement, then this works.

I modified it to fit your title block name & attribute. 

It'll automatically fill out sheet #. But if you move the layout tabs around, you'll have to re-run tabnumber command.

(defun c:tabnumber (/ _put a blk_name e i n s tag_name)
  (defun _put (blk tag val)
    (vl-some
      '(lambda (x) (and (wcmatch (vla-get-tagstring x) (strcase tag)) (vla-put-textstring x val)))
      (vlax-invoke blk 'getattributes)
    )
  )
  ;; Edit below for your use
  (setq blk_name "BORDER" ; "YOURTITLEBLOCKNAME"
  tag_name "SHT" ; "YOURATTRIBUTETAG"
  )
  (setq i (itoa (length (layoutlist))))
  (vlax-for l (vla-get-layouts (vla-get-activedocument (vlax-get-acad-object)))
    (setq a (cons (list (vla-get-name l) (vla-get-taborder l)) a))
  )
  (if (setq s (ssget "_A" (list '(0 . "INSERT") (cons 2 blk_name) '(66 . 1))))
    (foreach b (mapcar 'cadr (ssnamex s))
      (if (setq n (cadr (assoc (cdr (assoc 410 (entget b))) a)))
; (_put (vlax-ename->vla-object b) tag_name (strcat "Page " (itoa n) " of " i))
  (_put (vlax-ename->vla-object b) tag_name (itoa n))
      )
    )
  )
  (princ)
)

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

lylegrisso
Participant
Participant
okay, i see that now from your code. thanks and it works. thank you very much.
0 Likes