Lisp for combining multiple block attributes into a main block

Lisp for combining multiple block attributes into a main block

timothy.birdwell
Enthusiast Enthusiast
3,049 Views
26 Replies
Message 1 of 27

Lisp for combining multiple block attributes into a main block

timothy.birdwell
Enthusiast
Enthusiast

                I am looking for a lisp either already created or help with creating. What it needs to do is gather data from other blocks and incorporate that data into one block. In this situation my main block would be Fiber_Ped, I need to incorporate the data from the other blocks into it. A test drawing will be supplied. All I need from the second block is the assignment number and the address.

368

916 WACO OAKDALE LA 71463

369

 

370

 

371

 

372

 

403

 

 

                So essentially the Lisp would need create a new attribute system, that can house the information stored from the other blocks up to 12 assignment numbers.

0 Likes
3,050 Views
26 Replies
Replies (26)
Message 2 of 27

Sea-Haven
Mentor
Mentor

Try this select the attribute text to get its name eg 368, then window select all the blocks, pick a point for new block and angle.

 

; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/lisp-for-combining-multiple-block-attributes-into-a-main-block/td-p/11637019

(defun c:wow ( / )
(setq ent (nentsel "Pick block attribute for name "))
(setq attname (cdr (assoc 2 (entget (car ent)))))
(prompt "\nSelect the blocks ")
(setq ss (ssget '((0 . "INSERT"))))

(if (= ss nil)
(alert "No blocks picked will exit")

(progn
  (setq lst '())
  (repeat (setq x (sslength ss))
    (setq blk (vlax-ename->vla-object (ssname ss (setq x (- x 1)))))
              (setq atts (vlax-invoke blk 'Getattributes))
          (if (= atts nil)
		  (princ)
		  (foreach att atts
	        (if (= (vla-get-tagstring att) attname)
             (setq lst (cons (vla-get-textstring att) lst))
            )
          )
        )
    )


(setq lst (reverse (vl-sort lst '<)))
(setq len (- 11 (length lst)))
(repeat len
  (setq lst (cons "" lst))
)
(setq lst (reverse lst))

(setq pt (getpoint "\npick point for block ") ang (getreal "\nEnter angle "))
(if (= ang nil)(setq ang 0.0))

(setq x -1)
(setvar 'attreq 0)
(command "-insert" "Fiber_Ped" pt 1.0 1.0 ang)
(setq atts (vlax-invoke (vlax-ename->vla-object (entlast) ) 'getattributes))
(setq x -1)
(repeat (length lst)
  (vla-put-textstring  (nth (setq x (1+ x)) atts)   (nth x lst))
)
(setvar 'attreq 1)

)

) ; ss nil

(princ)
)
(c:wow)

 

0 Likes
Message 3 of 27

timothy.birdwell
Enthusiast
Enthusiast

So with this code, when I select the subscriber block, which would be the number. Then I select the fiber ped box and press enter, I select the point and angle. A new block is inserted but with the standard ped_block information with nothing filled out.

0 Likes
Message 4 of 27

timothy.birdwell
Enthusiast
Enthusiast
So what I am needing is to be able to extract information from block "SUBSCRIBER", ASSIGNMENT_NUM " x". Also from this block I need to extract information from OD:SUBSCRIBER, lines 5, 7, 8, 11, 12, 10. These lines will be combined together to make the address as one line. This info needs to be placed on the block Fiber_Ped. Now if the lisp creates a new OD on top of the Fiber_Ped is acceptable. Also if can get the numbers to go in descending order. I can almost see how to write it but don't know how to start writing it.
0 Likes
Message 5 of 27

Sea-Haven
Mentor
Mentor

Adding OD data adds a lot more complexity, but the simple answer is to use a LIST make the list with the number as 1st item then add all your OD data to list, so when you use the vl sort function its based on the number.

 

((368 "916 WACO OAKDALE LA 71463")(402 "123 WACO WOOD ST LA 71463)(.....))

 

 

0 Likes
Message 6 of 27

timothy.birdwell
Enthusiast
Enthusiast

Wanting to make sure im on the right track so far what I have is a function that pulls the variables and stores into a temporary list. 

(defun c:extract (/)
  ((setq SubscriberBlock (entsel))
   (setq SubscriberBlockList (entget (car SubscriberBlock)))
   (if (/= (cdr (assoc 0 SubscriberBlockList)) "block")
     (progn
     (while (/= (cdr (assoc 0 SubscriberBlockList)) "block")
       (prompt "\nSelect an object: ")
       (setq SubscriberBlock (entsel))
        (setq SubscriberBlockList (entget (car SubscriberBlock)))
        
       );End while function
     );End progn
   );End Function
  
0 Likes
Message 7 of 27

Sea-Haven
Mentor
Mentor

Ok a couple of suggestions 

1st

 

 

 

(( is not needed 
(setq SubscriberBlock (entsel))

 

 

 

 

 

2nd 

 

 

 

);End Function
) ; this is end of defun missing )

 

Ok so trying  a bit more walking slowly not running.

 

 

; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/lisp-for-combining-multiple-block-attributes-into-a-main-block/td-p/11637019
; an attempt by AlanH Dec 2022

(defun c:wow (/)

; Sort functions By pbejse forums/autodesk

  (defun _n (str / s)
    (setq s (vl-string-right-trim "0123456789" str))
    (list s (atoi (substr str (1+ (strlen s)))))
  )

  (Defun ThisSortFunc (l)
         (Vl-sort l '(lambda (n m)
                             (setq n (_n (Car n)) m (_n (Car m)))
                       (cond
                         ((< (Car n) (car m)))
                         ((eq (Car n) (car m)) (< (Cadr n) (cadr m)))
                       )
                     )
         )
  )
  (defun c:wow (/)
    (princ "\n Pick 1 block object for block name ")
    (setq ss (ssget "_+.:E:S" '((0 . "INSERT"))))
    (if (= ss nil)
      (alert "You may not have picked a block please try again")
      (progn
        (setq blk (vlax-ename->vla-object (ssname ss 0)))
        (setq bname (vla-get-name blk))
        (if (wcmatch bname "*U#*")
          (setq bname (vla-get-effectivename blk))
        )
        (princ "\nSelect the blocks ")
        (setq ss (ssget '((0 . "INSERT"))))
        (if (= ss nil)
          (alert "No blocks picked will exit")
          (progn
            (setq lst '())
            (repeat (setq x (sslength ss))
              (setq lst2 '())
              (setq blk (vlax-ename->vla-object (ssname ss (setq x (- x 1)))))
              (setq blkname (vla-get-name blk))
              (if (wcmatch blkname "*U#*")
                (setq blkname (vla-get-effectivename blk))
              )
              (if (= blkname bname)
                (progn
                  (setq atts (vlax-invoke blk 'Getattributes))
                  (if (= atts nil)
                    (princ "No Atts")
                    (progn
                      (foreach att atts
                        (setq lst2 (cons (vla-get-textstring att) lst2))
                      )
                      (setq lst (cons lst2 lst))
                    )
                  )
                )
              )
            )
            (setq lst (ThisSortFunc lst))
          )
        )
      )
    )
    (princ)
  )
  (c:wow)

 

 

 

So if you look at lst type !lst you can see we are getting somewhere.

(("368" "") ("369" "") ("370" "") ("371" "") ("372" "") ("403" ""))

 

Next task is to look for OD data and add to the list.

0 Likes
Message 8 of 27

timothy.birdwell
Enthusiast
Enthusiast

So when I try to run this code I get a bad ssget mode string error.

0 Likes
Message 9 of 27

paullimapa
Mentor
Mentor

What if you changed it to:

"_+.:E:S"


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

timothy.birdwell
Enthusiast
Enthusiast

Thanks that fixed, that error. So this code as it stands right now is suppose to only extract information? I can select named object, and now objects, press enter, doesn't show anything, command ends for me.

0 Likes
Message 11 of 27

paullimapa
Mentor
Mentor

After running that code did you do as @Sea-Haven instructed:

At command prompt: type !lst

you should get something like:

(("368" "") ("369" "") ("370" "") ("371" "") ("372" "") ("403" ""))


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

timothy.birdwell
Enthusiast
Enthusiast
Ok I was typing generic list, that was straight up user error. Im watching some videos and taking notes, using the code he wrote to write notes next to it with ; so I can see what each area is doing. As the "O.D." I believe I read yesterday that its a sub list with a prefix code of 1000. Going to see if I can get that extracted now.
0 Likes
Message 13 of 27

timothy.birdwell
Enthusiast
Enthusiast

6 hours in and a little defeated, Im slowly learning and got a few functions to work. This is what I have so far, I just can not find anything that shows how to get OD info. 

(DEFUN DXF (i l)(cdr (assoc i l)))

;---------------------------------;
;    SELECT BLOCK, EXTRACT OD     ;
;---------------------------------;

(defun c:foo (/ *ERROR* DAS SOURCE bname TEMPSS)
  ;SELECT BLOCK
  (SETQ DAS (ENTSEL "PLEASE CHOOSE AN OBJECT: "
            )) ;SELECT ENTITY
  
  (SETQ SOURCE (ENTGET (CAR DAS)));GET ENTITY INFO
  ;MAKE SURE ITS A BLOCK
  ;(= (dxf 0 SOURCE) "INSERT")
  ;GRAB ITS BLOCK NAME
  (setq bname (dxf 2 SOURCE))
  ;GET ALL BLOCKS
  (SETQ TEMPSS 
         (SSGET)
  ) ; _SETQ
  ;PROCESS THE BLOCKS
  ;
)
0 Likes
Message 14 of 27

paullimapa
Mentor
Mentor

if O.D. you mean extended entity data then take a look at this example:

https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/extended-entity-data-in-lisp/td-p/69...


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

Sea-Haven
Mentor
Mentor

Change this line did original off the top of my head should have looked it up.

 

(setq ss (ssget "_+.:E:S" '((0 . "INSERT"))))

 

ssget Function Reference | Lee Mac Programming (lee-mac.com)

0 Likes
Message 16 of 27

timothy.birdwell
Enthusiast
Enthusiast

So I believe I somewhat understand from looking at this, but do not fully comprehend. I can find the string information on the block, but as the OD goes I am unable to find it. I found routine "XDA" from Gilles (gile), tried it and when I selected the object it stated it has no Xdata. I am fully stumped here. *UPDATE* This is working in autocad map3d, a program I've been learning rapidly. The OD I can seperate by exporting as a .shp file and re-importing it. Could this be the reason why I am unable to find the code? 

block.JPG

0 Likes
Message 17 of 27

Sea-Haven
Mentor
Mentor

Look at this example it should help you.

(setq ent (car (entsel "\n Select object for OD: ")))
(setq Address (ade_odgetfield ent odname "ADDRESS_TYPE" 0))
(setq Pcode (ade_odgetfield ent odname "POSTAL_CODE" 0))

  

0 Likes
Message 18 of 27

timothy.birdwell
Enthusiast
Enthusiast

I'm still researching, and finding information. When I try to add the odd code, it overrides the previous. Any good suggestions of videos that can break it down barny style for me? 

0 Likes
Message 19 of 27

timothy.birdwell
Enthusiast
Enthusiast

I'm a little all over the place now. The biggest thing I can't do is find those other values. I'll show you where I am at right now, I know the code is redundant, but I'm trying to figure out what each line does.

(defun c:NestedAttValues (/ Sel Obj)
  (defun _n (str / s)
    (setq s (vl-string-right-trim "0123456789" str))
    (list s (atoi (substr str (1+ (strlen s)))))
  )
  (Defun ThisSortFunc (l)
         (Vl-sort l '(lambda (n m)
                             (setq n (_n (Car n)) m (_n (Car m)))
                       (cond
                         ((< (Car n) (car m)))
                         ((eq (Car n) (car m)) (< (Cadr n) (cadr m)))
                       )
                     )
         )
  )
(defun PrintAttList (BlkObj)

(print
(list
(vla-get-Name Obj)
(mapcar '(lambda (x) (cons (vla-get-TagString x) (vla-get-TextString x)))
(vlax-invoke Obj 'GetAttributes))
)
)
)
(defun GetNestedBlocks (BlkName BlkCol)
 (setq att_lst nil)
 (setq ss (ssget "X" (list (cons 0 "INSERT"))))
  (if ss
   (progn
    (setq C 0)
    (repeat (sslength ss)
     (setq blk (ssname ss C))
     (setq elist (entget blk))
     (setq bn (cdr (assoc 2 elist))); blockname
     (vlax-for Obj (vla-Item BlkCol BlkName)
      (if (= (vla-get-ObjectName Obj) "AcDbBlockReference")
       (progn
        (PrintAttList Obj)
        (GetNestedBlocks (vla-get-name Obj) BlkCol)
       )
      )
     )
    )
   )
  )
);end fun
(setq BlkCol (vla-get-Blocks (vla-get-ActiveDocument
(vlax-get-Acad-Object))))
(if
 (and
  (setq Sel (entsel "\n Select block to get nested attributes: "))
  (setq Obj (vlax-ename->vla-object (car Sel)))
  (= (vla-get-ObjectName Obj) "AcDbBlockReference")
  (progn
   (MakeAttLists Obj)
   (GetNestedBlocks (vla-get-Name Obj) BlkCol)
  ); progn
 );and
 (setq C (+ C 1))
); if
(princ)
(progn
 (PrintAttList Obj)
 (GetNestedBlocks (vla-get-Name Obj) BlkCol)
)
(princ)
(princ "\n Pick 1 block object for block name ")
    (setq ss (ssget "_+.:E:S" '((0 . "INSERT"))))
    (if (= ss nil)
      (alert "You may not have picked a block please try again")
      (progn
        (setq blk (vlax-ename->vla-object (ssname ss 0)))
        (setq bname (vla-get-name blk))
        (if (wcmatch bname "*U#*")
          (setq bname (vla-get-effectivename blk))
        )
        (princ "\nSelect the blocks ")
        (setq ss (ssget '((0 . "INSERT"))))
        (if (= ss nil)
          (alert "No blocks picked will exit")
          (progn
            (setq lst '())
            (repeat (setq x (sslength ss))
              (setq lst2 '())
              (setq blk (vlax-ename->vla-object (ssname ss (setq x (- x 1)))))
              (setq blkname (vla-get-name blk))
              (if (wcmatch blkname "*U#*")
                (setq blkname (vla-get-effectivename blk))
              )
              (if (= blkname bname)
                (progn
                  (setq atts (vlax-invoke blk 'Getattributes))
                  (if (= atts nil)
                    (princ "No Atts")
                    (progn
                      (foreach att atts
                        (setq lst2 (cons (vla-get-textstring att) lst2))
                      )
                      (setq lst (cons lst2 lst))
                    )
                  )
                )
              )
            )
            (setq lst (ThisSortFunc lst))
          )
        )
      )
    )
    (princ)
  ) ;endfun
0 Likes
Message 20 of 27

Sea-Haven
Mentor
Mentor

Had another go try this version, pick the 368 block then window the others.

 

; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/lisp-for-combining-multiple-block-attributes-into-a-main-block/td-p/11637019
; an attempt by AlanH Dec 2022

; Sort functions By pbejse forums/autodesk



(defun _n (str / s)
    (setq s (vl-string-right-trim "0123456789" str))
    (list s (atoi (substr str (1+ (strlen s)))))
)
(Defun ThisSortFunc (l)
         (Vl-sort l '(lambda (n m)
                             (setq n (_n (Car n)) m (_n (Car m)))
                       (cond
                         ((< (Car n) (car m)))
                         ((eq (Car n) (car m)) (< (Cadr n) (cadr m)))
                       )
                     )
         )
)
(defun c:wow ( / )
(princ "\n Pick 1 block object for block name ")
(setq ss (ssget "_+.:E:S" '((0 . "INSERT"))))
(if (= ss nil)
(alert "You may not have picked a block please try again")
(progn
(setq blk (vlax-ename->vla-object (ssname ss 0)))
(setq bname (vla-get-name blk))
(if (wcmatch bname "*U#*")
(setq bname (vla-get-effectivename blk))
)
(princ "\nSelect the blocks ")
(setq ss (ssget '((0 . "INSERT"))))
(if (= ss nil)
(alert "No blocks picked will exit")
(progn
(setq lst '())
(repeat (setq x (sslength ss))
(setq lst2 '())
(setq ent (ssname ss (setq x (- x 1))))
(setq blk (vlax-ename->vla-object ent))
(setq blkname (vla-get-name blk))
(if (wcmatch blkname "*U#*")
(setq blkname (vla-get-effectivename blk))
)
(if (= blkname bname)
(progn
(setq atts (vlax-invoke blk 'Getattributes))
(if (= atts nil)
(princ "No Atts")
(progn
(foreach att atts
(setq lst2 (cons (vla-get-textstring att) lst2))
)
(setq odname (ade_odgettables ent))
(setq Stnum (ade_odgetfield ent odname "STREET_NUMBER" 0))
(setq Stname (ade_odgetfield ent odname "STREET_NAME" 0))
(setq state (ade_odgetfield ent odname "STATE" 0))
(setq Pcode (ade_odgetfield ent odname "POSTAL_CODE" 0))
(setq lst (cons (list  (car lst2) (strcat stnum " " stname " " state " " pcode)) lst))
(setq lst (ThisSortFunc lst))
)
)
)
)
)
(setvar 'attreq 0)
(command "-insert" "Fiber_Ped" (getpoint "\nPick insertion point ") 9 9 0)
(setvar 'attreq 1)
(setq len (length lst))
(setq blkatts (vlax-invoke (vlax-ename->vla-object (entlast)) 'Getattributes))
(setq x 0 Y 0)
(repeat (- 12  len)
(vla-put-textstring (nth x blkatts) (strcat (car (nth y lst)) " " (cadr (nth y lst))))
(setq x (1+ x) y (1+ y))
)
)
)
)
)
(princ)
)
(c:wow)

 

 

0 Likes