Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

COMPILING MULTIPLE TEXT ENTRIES FROM BLOCK ATTRIBUTES INTO A SINGLE MLEADER MTEXT ENTRY

I'm trying to write a LISP that will gather attributes from multiple blocks and construct a specific format Mtext field for inclusion in a Mleader. I don't know how to go about including multiple instances of the selection set and retain the correct formatting for the Mleader command without writing multiple instances of TX for 1,2,3,4,5 etc pipes. How do I go about repeating the RPT section of the code to compile a text body of nTX's?

varopen/close just set the system variables and return them to drafting defaults and GA goes and gets the attributes and insertion point of the blocks. I get how this code is just rewriting the TX for RPT number of times instead of compiling a full list, but I don't know whether to princ out to a 'temp file' and read the text back in or if you can change the current LISP to accommodate mutiple instances of attribute text.

(defun c:MULTITAG ( / )
(setq DEPTH () CODE () ELEVATION () SIZE () MATERIAL () NOTE () FLOW () )
(varopen)

 (setq RPT (getint "\nEnter Number of Pipes : "))   

 (repeat RPT                        
 (setq Blname (car(entsel "\nSelect Survey Points for attributes:")))   

 (GA Blname)    

 (setq coord (cdr(assoc 10 (entget blname))))       
 (setq A (rtos (nth 0 coord) 2 3))
 (setq B (rtos (nth 1 coord) 2 3))
 (setq C (rtos (nth 2 coord) 2 3))              

 (setq Si_dia (strcat flow " - " Size "%%c"))
 (if (= material "UKN")
 (setq Si_dia_mat Si_dia)
 (setq Si_dia_mat (strcat Si_dia " " Material))
 )
 (setq ELEVATIONN (atof C))             
 (setq DEPTHN (atof DEPTH))             
 (setq y (- ELEVATIONN DEPTHN))             
 (setq x (rtos y))                  
 (setq D DEPTH)                     
 (setq Tx (strcat si_dia_mat " (" CODE ")" "\n\ RL OF INVERT: " x "m" "\n\ TAPE DEPTH: " D "m" "\n" )))
 (princ)


 (setq Blname2 (car(entsel "\nSelect Survey Point for leader insertion:"))) 

 (GA Blname2)

 (setq coord2 (cdr(assoc 10 (entget blname2))))     


 (COMMAND "-LAYER" "M" (strcat lay "_txt") "")      
 (COMMAND "_MLEADER" coord2 PAUSE TX))          
 (Varclose)
 (prin1)

Comments

  • @Colin_Digmore
    Not sure if I get what you want, but sounds like you want to pick one or more survey points and combine their info into lines in an mleader.
    So if you pick 4 points, the mleader gets 4 lines, then rinse and repeat for another set of points.
    To start, the users does not have to say number of pipes. Do this instead:
    (setq SS (SSGET "\nPick Pipe Points"))
    The number they picked is how ever many are in the SS var. Loop through it to build list of strings for mleader like:
    (setq index 0
    TxFinalVal ""
    )
    (repeat (sslength SS)
    (setq ename (ssname SS index)
    elist (entget ename)
    coord (cdr (assoc 10 elist))
    ....build vars....
    Tx (strcat si_dia_mat " (" CODE ")" "\n\ RL OF INVERT: " x "m" "\n\ TAPE DEPTH: " D "m" "\n" ))
    TxFinalVal (if (not TxFinalVal)
    Tx
    (strcat TxFinalVal "\n" Tx) ;<---- ok, I forget the carriage return string for mtext, replace "\n" with correct string
    )
    index (+ 1 index)
    )
    )
    now you have a string for the mleader.

    That (GA blname) is very bad form, sorry to break it to you while I'm sure you feel like miracles are happening :)
    You are setting "global" vars like flow and material.
    Global vars will sour your lisp experience as then you have to be careful what you call what. You should never have to worry about INDEX in one function messing with INDEX in another.
    You should have no global vars except for settings you need from run to run.
    Instead, your functions should return lists.
    you should have:
    (setq attlist (GA entname))
    Then access the list by:
    (setq flow (nth 0 attlist)
    material (nth 1 attlist) and so on
    )

    and localize vars like:
    (defun myfunction ( / localvar1 localvar2....)
    Put them after the / in the defun params.

    I know its a lot, but you are making the super important jump from keeping all vars exposed and raw, to clean handshaking of main routine with sub-functions. You do that with lists because a function can only return one thing.
    I have a library with like 23k lines of code with my functions for all this. One to get list of att tags and vals, one to write back atts using list of att tags and vals. The rabbit hole is deep but once you get the hang of it you just collect from the internet, free digging.
    thx

  • edited February 18

    btw, here are the att read and write functions I mentionedfrom my library.
    The first one gives list of ((tag val txinspoint)(tag val txinspoint)...) for those times I need to make sure the updated block also has atts in same location if user tweaked after insert:

    ;(MAKE-LIST-OF-ATTRIBS-PTS (CAR (ENTSEL)))
    (defun MAKE-LIST-OF-ATTRIBS-PTS (EN / BLK ATT RET)
        (SETQ BLK (VLAX-ENAME->VLA-OBJECT EN))
        (IF (= (VLA-GET-HASATTRIBUTES BLK) :VLAX-TRUE)
            (FOREACH ATT (VLAX-SAFEARRAY->LIST (VLAX-VARIANT-VALUE (VLA-GETATTRIBUTES BLK)))
                (SETQ RET (CONS (LIST (VLA-GET-TAGSTRING ATT) (VLA-GET-TEXTSTRING ATT) (GET-TXT-INSPT ATT)) RET))
            )
        )
        (REVERSE RET)
    )

    ;------(CT-UPDATE-ATT-VALUES.LSP------
    ;SUPPLY:
    ;EN    ENTITY NAME
    ;ATTS  LIST OF TAGS AND VALUES ((TAG VALUE)(...))
    ;      ATTS may be either a sequential list of
    ;      strings or a list containing a tag name and
    ;      the attribute data.
    ;RETURN:
    ;UPDATES BLOCK (NO VALUE)
    (defun CT-UPDATE-ATT-VALUES (EN ATTS / BLK INDEX TAG DIMZIN VAL)
        (SETQ BLK (VLAX-ENAME->VLA-OBJECT EN))
        (IF (AND ATTS
                         (= (VLA-GET-HASATTRIBUTES BLK) :VLAX-TRUE)
                )
            (PROGN
                (SETQ DIMZIN (GETVAR "DIMZIN"))
                (SETVAR "DIMZIN" 8)
                (if (atom (car ATTS))
                    (PROGN
                    ;;update sequential
                        (SETQ INDEX 0)
                    (FOREACH ATT (VLAX-SAFEARRAY->LIST (VLAX-VARIANT-VALUE (VLA-GETATTRIBUTES BLK)))
                            (IF (< INDEX (LENGTH ATTS))
                                (PROGN
                                    (SETQ VAL (NTH INDEX ATTS))
                                    (IF (NUMBERP VAL)(SETQ VAL (RTOS-MAX 2 VAL))) ;CONVERT NUMBER IF SUPPLIED
                                  (VLA-PUT-TEXTSTRING ATT VAL)
                                  (IF (WCMATCH VAL "*%<\\A*")
                                      (COMMAND* "updatefield" (VLAX-VLA-OBJECT->ENAME ATT) "")
                                  )
                                )
                            )
                            (SETQ INDEX (+ 1 INDEX))
                        )
                    )
                    ;ELSE update BY TAG
                (FOREACH ATT (VLAX-SAFEARRAY->LIST (VLAX-VARIANT-VALUE (VLA-GETATTRIBUTES BLK)))
                      (SETQ TAG (VLA-GET-TAGSTRING ATT))
                      (FOREACH ITEM ATTS
                          (IF (= (STRCASE TAG) (STRCASE (CAR ITEM)))
                              (PROGN
                                    (SETQ VAL (CADR ITEM))
                                    (IF (NUMBERP VAL)(SETQ VAL (RTOS-MAX 2 VAL))) ;CONVERT NUMBER IF SUPPLIED
                                  (VLA-PUT-TEXTSTRING ATT VAL)
                                  (IF (WCMATCH VAL "*%<\\A*")
                                      (COMMAND* "updatefield" (VLAX-VLA-OBJECT->ENAME ATT) "")
                                  )
                              )
                          )
                      )
                    )
                )
                (SETVAR "DIMZIN" DIMZIN)
            )
        )
    )

    I think I left out a sub or two. The COMMAND* is a sub that uses COMMAND-S as needed. I can provide if you are inclined to follow.

  • hey man, thanks for that, yah i know the "GA" isn't ideal, but the guy who set the system up years ago has a bunch of stuff like this scattered all through the 60+ routines we've got in the library. It took a neophyte like me 6 months before I understood what was a function and what was a lisp phrase. The benefit it gives the system as a whole is that if we change something for, e.g. a font type/size or whatever, you only change it in a single location in the library, so yeah I'm hearing you, but as an uninitiated it'd be nigh on impossible for me to eradicate these global variable setting LISPS.

    I'm going to run your script, thanks for the help :)

  • @Colin_Digmore
    It always amazes me that civil engineers charge $125 an hour or more, yet cannot keep a consultant on staff to manage their automation.
    Sounds like you are becoming that consultant, and getting used to lisp takes time. Don't underestimate the value you bring, keep climbing that mountain.

  • hey James, I added your suggestions to the LISP and after much experimentation I've got to :smile:

    (defun c:multitag ( / )
    (setq DEPTH () CODE () ELEVATION () SIZE () MATERIAL () NOTE () FLOW () )
    (varopen)

    (princ "\n Pick Pipe Points:")
    (setq SS (SSGET))
    (setq index 0 TxFinalVal "")
    (repeat (sslength SS)
    (setq ename (ssname SS index))

    (GA ename)

     (setq elist (entget ename))
    

    (setq coord1 (cdr (assoc 10 elist)))

    (setq A1 (rtos (nth 0 coord1) 2 3))
    (setq B1 (rtos (nth 1 coord1) 2 3))
    (setq C1 (rtos (nth 2 coord1) 2 3))

    (setq Si_dia (strcat flow " - " Size "%%c"))
    (if (= material "UKN") (setq Si_dia_mat Si_dia) (setq Si_dia_mat (strcat Si_dia " " Material)))

    (setq ELEVATIONN (atof C1))
    (setq DEPTHN (atof DEPTH))
    (setq y (- ELEVATIONN DEPTHN))
    (setq x (rtos y))
    (setq D DEPTH)

    (setq Tx (strcat si_dia_mat " (" CODE ")" "\n\ RL OF INVERT: " x "m" "\n\ TAPE DEPTH: " D "m" "\n" )))

    (setq TxFinalVal
    (if (not TxFinalVal)
    (strcat TxFinalVal "\n" Tx)
    )
    index (+ 1 index)
    )

    (princ)

    (setq Blname22 (car(entsel "\nSelect Survey Point for leader insertion:")))
    (GA Blname22)

    (setq coord22 (cdr(assoc 10 (entget blname22))))

    (COMMAND "-LAYER" "M" (strcat lay "_txt") "")
    (COMMAND "_MLEADER" coord22 PAUSE TX)
    (Varclose)
    (prin1)
    )

    The LISP will now let me ssget 3 points, then ask for the insertion point and write the Mleader. But this code only returns a single set of attributes text for the first point.

    I'll be honest and say I don't understand the TxFinalVal sections or how they're interacting with the Tx. Sorry man, just a little more help?

  • @James Maeding said:
    @Colin_Digmore
    It always amazes me that civil engineers charge $125 an hour or more, yet cannot keep a consultant on staff to manage their automation.
    Sounds like you are becoming that consultant, and getting used to lisp takes time. Don't underestimate the value you bring, keep climbing that mountain.

    lol

    You're not wrong. The suite of LISPS we have are appx. 6 years old and someone 'appropriated" them from a previous employer, I'm the 6th or 7th guy to come through and no-one before me could be bothered to learn enough to even edit them for different functions. Most of them I understand, they're written pretty basically and the format and code for most of them borrow from each other. This MULTITAG is the last of my inherited problems and it requires a 'perspective' that I just don't have, prior to me making the Tx section of this the PM's/engineers have just been hand calculating the inverts and filling in the text by hand, at yes $145 ph.

    Thx for the input and the support J :)

  • @Colin_Digmore
    If you ever want me to look over things for free, I'd be happy to. I would keep it confidential.
    I've done that for about 5 companies now and many still use my old "FastProf" tools for profiles.
    Sometimes I notice things like routines using (command .. instead of Entmake and can speed them up 10x.
    I just find it interesting to see what others have collected since I did the same for years but have now rewritten anything that mattered.
    thx

Sign In or Register to comment.
Origami
Origami is the Japanese word for paper folding. ORI means to fold and KAMI means paper and involves the creation of paper forms usually entirely by folding.

Powered by VanillaForums, Designed by Steam