Update a block with attributes from another block

Update a block with attributes from another block

eprime.ec
Participant Participant
525 Views
4 Replies
Message 1 of 5

Update a block with attributes from another block

eprime.ec
Participant
Participant

Okay, I have an AutoCAD / LISP question. For CIVIL 3D 2018. I draw diagrams for long drilling routes, where I station the conduit being placed under ground for various reasons. As you might expect, the conduit being placed in the ground requires many sheets to be created in paper space. I draw typically in a 1:50 scale. I have a rectangular block that I use in model space that has scaled down dimensions that line up to the viewports in paper space. The rectangular block that I use in model space has three attributes. The first attribute is a page number, and the 2nd attribute is a left station or distance and the 3rd one is a right station or distance. In paper space I have two blocks and they are left and right match lines. They have 3 attributes respectively, the page number the match line is proceeding to (entering or leaving the page), the station or distance denoting at what distance the conduit enters the page and at what distance the conduit exits the page. Now that we have the picture, let's move to the question. I want to be able to type into my block in model space, the page number and the beginning and ending station, if the page number matches the sheet number then what ever I type in the stations attribute on the model space layout block rectangle, will appear on the match line in layout space. On the left and right respectively.

Here is my lisp file trying tirelessly to error check it. I can't get it to even error check properly, someone please point me in the right direction, I use civil 3d 2018, and VLA-GET-ATTRIBUTES doesn't seem to be recognized. 

The command doesn't get past selecting the viewport. 

0 Likes
526 Views
4 Replies
Replies (4)
Message 2 of 5

paullimapa
Mentor
Mentor

You would have to try the approach of actually creating a selection set of the block that's already inserted to get the attributes like this:

; if find left matching line block in current layout
(if(setq ss (ssget "X" (list '(0 . "INSERT")'(66 . 1) '(2 . "FN_Matchline_L1")(cons 410 (getvar "ctab")))))
 (progn
  ;; get the attribute objects from that block assuming only a single block found in current layout
  (setq att (vlax-invoke (vlax-ename->vla-object (ssname ss 0)) 'getattributes))
 ;; now you can loop through each attribute & use a condition to test which is the tag you want
  (foreach itm att 
   (cond 
    ((= (vla-get-TagString itm) "STA_NUM_L")(alert"Station#"))
    ((= (vla-get-TagString itm) "SHT#")(alert"Sheet#"))
    ((= (vla-get-TagString itm) "T_SHTS")(alert"T_Shts"))
   ) ; cond
  ) ; foreach
 ) ; progn
) ; if

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

eprime.ec
Participant
Participant

Like this? 

;;; UML.lsp

(defun c:UML (/ ss obj blkRefLeft blkRefRight attColl page stationL stationR att)
  ; Find left matching line block in the current layout
  (if (setq ss (ssget "X" (list '(0 . "INSERT") '(2 . "FN_Matchline_L1") (cons 410 (getvar "ctab")))))
    (progn
      ; Get the attribute objects from the block (assuming only a single block found in the current layout)
      (setq att (vlax-invoke (vlax-ename->vla-object (ssname ss 0)) 'getattributes))

      ; Loop through each attribute and use a condition to test which is the tag you want
      (foreach itm att
        (cond
          ((= (vla-get-TagString itm) "STA_NUM_L")
           (setq stationL (vla-get-textstring itm)))
          ((= (vla-get-TagString itm) "SHT#")
           (setq page (vla-get-textstring itm)))
          ; Add other conditions as needed
        ) ; cond
      ) ; foreach

      ; Now you can use the retrieved values (e.g., page and stationL) as needed

      ; Check for the existence of right match line block
      (if (setq blkRefRight (vla-item (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object))) "FN_Matchline_R1"))
        (progn
          (setq attColl (vla-get-attributes blkRefRight))
          (setq stationR (vla-get-textstring (vla-item attColl 2)))

          ; Now you can use the retrieved values (e.g., stationR) as needed
        )
      )
    )
  )
)

(princ "UML loaded. Type UML to update match lines.")
0 Likes
Message 4 of 5

eprime.ec
Participant
Participant

This doesn't seem to work btw. The command seems to not be break after I enter "UML"

0 Likes
Message 5 of 5

paullimapa
Mentor
Mentor

Ok, this is a full blown revised UML.lsp code that requires you to first select the Pspace Vport, then go into Mspace to select the Station Block with Attributes. Next it'll grab those attribute values found saving them respectively.

Then it'll check if the current Layout name matches the Page # found in the Station Block.

If it does, then it'll proceed back in Pspace automatically locating the MatchLine Blocks Right & Left & update those attribute values. But every time you change the Station Block Attribute values then you'll have to run UMB again to update the MatchLine Block Attribute values.

;;; UML.lsp Updates Layout Matchline Attribute Values with Matching Block Attributes in Model
; OP:
; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/update-a-block-with-attributes-from-another-block/m-p/12418359#M458454
(defun c:UML (/ ssVport cmdecho menuecho ctab ssStation attStation stationL stationR page ssMatchL ssMatchR attMatchL attMatchR)
 (princ"\nPick Vport...")
 (if (setq ssVport (ssget "_+.:E:S" '((0 . "VIEWPORT"))))
  (progn
   ; setup environment
   (setq cmdecho (getvar "cmdecho")
         menuecho (getvar "menuecho")
         ctab (getvar"ctab") ; save current layout name
         ssVport (cdr(assoc 69 (entget(ssname ssVport 0)))) ; get the vport id
   )
   (setvar "cmdecho" 0)
   (setvar "menuecho" 0) 
   (vl-cmdf "_.Mspace") ; goto mspace
   (setvar "cvport" ssVport) ; set selected vport current
   (princ"\nPick Station Block with Attributes...")
  ; select station block for this example should have name: "FN_Viewport_Page_No1"
   (if (setq ssStation (ssget "_+.:E:S" '((0 . "INSERT") (66 . 1)))) 
    (progn
      ; Get the attribute objects from the station block - assuming only a single block found
      (setq attStation (vlax-invoke (vlax-ename->vla-object (setq en (ssname ssStation 0))) 'getattributes))
      ; Loop through each attribute and use a condition to test which is the tag you want
      (foreach itm attStation ; loop through station block attributes
        (cond
          ((= (vla-get-TagString itm) "STA_NUM_L") ; matching left station #
           (setq stationL (vla-get-textstring itm))
          )
          ((= (vla-get-TagString itm) "STA_NUM_R") ; matching right station #
           (setq stationR (vla-get-textstring itm))
          )
          ((= (vla-get-TagString itm) "PGNO") ; get page number
           (setq page (vla-get-textstring itm))
          )
        ) ; cond
      ) ; foreach
      (if (and 
            stationL ; got this value 
            stationR ; got this value 
            page     ; got the page
            (eq page ctab) ; check if page # matches with saved layout name
          )
        (progn
        ; Find left & right matching line block in layout matching page
         (if (and
              (setq ssMatchL (ssget "X" (list '(0 . "INSERT") '(2 . "FN_Matchline_L1") '(66 . 1) (cons 410 page)))
                    ssMatchR (ssget "X" (list '(0 . "INSERT") '(2 . "FN_Matchline_R1") '(66 . 1) (cons 410 page)))
              )
             )
           (progn
            ; Get the attribute objects from the matchline blocks - assuming only a single block found each
            (setq attMatchL (vlax-invoke (vlax-ename->vla-object (ssname ssMatchL 0)) 'getattributes)
                  attMatchR (vlax-invoke (vlax-ename->vla-object (ssname ssMatchR 0)) 'getattributes)
            )
            ; Loop through each matchline left attribute and use a condition to test which is the tag you want
            (foreach itm attMatchL
             (cond
              ((= (vla-get-TagString itm) "STA_NUM_L")
               (vla-put-textstring itm stationL) ; put new value
              )
              ((= (vla-get-TagString itm) "SHT#")
               (vla-put-textstring itm page) ; put page #
              )
             ) ; cond
            ) ; foreach
            (princ"\nMatchLine Left Updated.")
            ; Loop through each matchline right attribute and use a condition to test which is the tag you want
            (foreach itm attMatchR
             (cond
              ((= (vla-get-TagString itm) "STA_NUM_R")
               (vla-put-textstring itm stationR) ; put new value
              )
              ((= (vla-get-TagString itm) "SHT#")
               (vla-put-textstring itm page) ; put page #
              )
             ) ; cond
            ) ; foreach
            (princ"\nMatchLine Right Updated.")
           ) ; progn
           (alert(strcat "No MatchLines Found on Layout Matching Sheet [" page "]."))
         ) ;if
        ) ; progn
        (alert(strcat "No Layout Name Matching Page [" page "] Found."))
      ) ; if
    ) ; progn
    (alert"No Station Block Selected.")
   ) ; if
   (vl-cmdf "_.Pspace") ; return to pspace
   ; restore environment
   (setvar "menuecho" menuecho)
   (setvar "cmdecho" cmdecho)
  ) ; progn
  (alert"No Vport Selected.")
 ) ; if
 (princ) ; clean exit
) ; defun UML

(princ "UML loaded. Type UML to update match lines.")(princ)

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes