TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: MSTG007 on July 16, 2015, 02:34:57 PM

Title: Update a Attributed Block by selecting entities for Count
Post by: MSTG007 on July 16, 2015, 02:34:57 PM
Wondering if there was someway to select objects (lines or circles or whatever) and it adds us the count of those objects then you can select an attributed block to update the count too. Any ideas like that?
Title: Re: Update a Attributed Block by selecting entities for Count
Post by: roy_043 on July 16, 2015, 03:57:29 PM
Something like this:
Code - Auto/Visual Lisp: [Select]
  1. (defun c:test ( / ss enme)
  2.   (if
  3.     (and
  4.       (setq ss (ssget))
  5.       (setq enme (car (nentsel "\nSelect attribute: ")))
  6.     )
  7.     (vla-put-textstring (vlax-ename->vla-object enme) (itoa (sslength ss)))
  8.   )
  9.   (princ)
  10. )
Title: Re: Update a Attributed Block by selecting entities for Count
Post by: MSTG007 on July 16, 2015, 04:12:06 PM
Thanks a lot! Does this need to be a specific attributed block name or any attributed block?

By the way, I can always burst the block and use text like you have it. Works great!
Title: Re: Update a Attributed Block by selecting entities for Count
Post by: roy_043 on July 17, 2015, 06:46:06 AM
The block name is irrelevant. Below is an improved version. The old version would also change items nested in blocks.
Code - Auto/Visual Lisp: [Select]
  1. ; (_Sys_ObjectOwner (vlax-ename->vla-object (car (nentsel))))
  2. (defun _Sys_ObjectOwner (obj)
  3. )
  4.  
  5. (defun c:test2 ( / attLst doc obj selLst ss)
  6.   (if (= 8 (logand (getvar 'undoctl) 8))
  7.     (vla-endundomark doc)
  8.   )
  9.   (if
  10.     (and
  11.       (setq ss (ssget))
  12.       (setq selLst (nentsel "\nSelect attribute, (m)text or block (first attribute will be changed): "))
  13.     )
  14.     (progn
  15.       (setq obj (vlax-ename->vla-object (car selLst)))
  16.       (cond
  17.         ;; Attribute reference:
  18.         ((= "AcDbAttribute" (vla-get-objectname obj))
  19.           (if (= :vlax-true (vla-get-islayout (_Sys_ObjectOwner (_Sys_ObjectOwner obj))))
  20.             (vla-put-textstring obj (sslength ss))
  21.             (princ "\nError: nested (m)text or attribute ")
  22.           )
  23.         )
  24.         ;; Mtext, text and attribute definition:
  25.         ((vlax-property-available-p obj 'textstring)
  26.           (if (= :vlax-true (vla-get-islayout (_Sys_ObjectOwner obj)))
  27.             (vla-put-textstring obj (sslength ss))
  28.             (princ "\nError: nested (m)text or attribute ")
  29.           )
  30.         )
  31.         ;; Nested entity in block selected. First attribute reference is updated:
  32.         (
  33.           (and
  34.             (cdddr selLst)
  35.             (setq obj (vlax-ename->vla-object (last (cadddr selLst))))
  36.             (= "AcDbBlockReference" (vla-get-objectname obj))
  37.             (setq attLst (vlax-invoke obj 'getattributes))
  38.           )
  39.           (vla-put-textstring (car attLst) (sslength ss))
  40.         )
  41.         (T
  42.           (princ "\nError: invalid object ")
  43.         )
  44.       )
  45.     )
  46.   )
  47.   (princ)
  48. )

EDIT: Renamed c:test to c:test2.
EDIT: Changed (car (cadddr ...)) to (last (cadddr ...)).
Title: Re: Update a Attributed Block by selecting entities for Count
Post by: MSTG007 on July 17, 2015, 07:19:48 AM
Awesome. Cant wait to try this out!
Title: Re: Update a Attributed Block by selecting entities for Count
Post by: roy_043 on July 17, 2015, 02:25:22 PM
I have updated the code in my previous post.
The code below achieves the same but is more concise.
Code - Auto/Visual Lisp: [Select]
  1. (defun c:test3 ( / attLst doc obj selLst ss)
  2.   (if (= 8 (logand (getvar 'undoctl) 8))
  3.     (vla-endundomark doc)
  4.   )
  5.   (if
  6.     (and
  7.       (setq ss (ssget))
  8.       (setq selLst (nentsel "\nSelect attribute, (m)text or block (first attribute will be changed): "))
  9.     )
  10.     (cond
  11.       ;; Nested object. First attribute reference is updated:
  12.       ((cdddr selLst)
  13.         (if (setq attLst (vlax-invoke (vlax-ename->vla-object (last (cadddr selLst))) 'getattributes))
  14.           (vla-put-textstring (car attLst) (sslength ss))
  15.           (princ "\nError: invalid nested object ")
  16.         )
  17.       )
  18.       ;; Non-nested mtext, text and attribute definition:
  19.       ((vlax-property-available-p (setq obj (vlax-ename->vla-object (car selLst))) 'textstring)
  20.         (vla-put-textstring obj (sslength ss))
  21.       )
  22.       (T
  23.         (princ "\nError: invalid object ")
  24.       )
  25.     )
  26.   )
  27.   (princ)
  28. )
Title: Re: Update a Attributed Block by selecting entities for Count
Post by: MSTG007 on July 28, 2015, 07:20:59 AM
Roy,
I forgot to thank you again for your help on this guy. I have another dumb question to ask. Is it possible to select objects thru an xref? If circles are on another drawing that is xref'd into the current one, can the lisp still select those objects for a count. Currently it works great when everything is in a current drawing! Again thanks!
Title: Re: Update a Attributed Block by selecting entities for Count
Post by: roy_043 on July 29, 2015, 07:12:47 AM
You cannot create a selection set 'through an xref'. You can use (nentsel) for single picks. Or count all circles in an xref. See code below for an example of the latter.

Code - Auto/Visual Lisp: [Select]
  1. (defun _Conv_Pickset_To_EnameList (ss / i ret)
  2.   (if ss
  3.     (repeat (setq i (sslength ss))
  4.       (setq ret (cons (ssname ss (setq i (1- i))) ret))
  5.     )
  6.   )
  7. )
  8.  
  9. ; (CountCircles (ssget '((0 . "CIRCLE,INSERT"))))
  10. (defun CountCircles (ss / N_CheckObj_P blkDef blks i xrefDb)
  11.  
  12.   (defun N_CheckObj_P (obj)
  13.     (and
  14.       (= "AcDbCircle" (vla-get-objectname obj))
  15.       (= "0" (vla-get-layer obj))
  16.       ; ... ; Add more tests.
  17.     )
  18.   )
  19.  
  20.   (setq i 0)
  21.   (foreach obj (mapcar 'vlax-ename->vla-object (_Conv_Pickset_To_EnameList ss))
  22.     (cond
  23.       ((/= "AcDbBlockReference" (vla-get-objectname obj))
  24.         (if (N_CheckObj_P obj)
  25.           (setq i (1+ i))
  26.         )
  27.       )
  28.       ((setq xrefDb (vla-get-xrefdatabase (setq blkDef (vla-item blks (vla-get-name obj)))))
  29.         (vlax-for obj (vla-get-modelspace xrefDb)
  30.           (if (N_CheckObj_P obj)
  31.             (setq i (1+ i))
  32.           )
  33.         )
  34.       )
  35.       (T ; Normal block.
  36.         (vlax-for obj blkDef
  37.           (if (N_CheckObj_P obj)
  38.             (setq i (1+ i))
  39.           )
  40.         )
  41.       )
  42.     )
  43.   )
  44.   i
  45. )
  46.  
  47. (defun c:test4 ( / attLst doc i obj selLst ss)
  48.   (if (= 8 (logand (getvar 'undoctl) 8))
  49.     (vla-endundomark doc)
  50.   )
  51.   (if
  52.     (and
  53.       (setq ss (ssget '((0 . "CIRCLE,INSERT"))))
  54.       (setq i (CountCircles ss))
  55.       (princ (strcat "\nCount is: " (itoa i)))
  56.       (setq selLst (nentsel "\nSelect attribute, (m)text or block (first attribute will be changed): "))
  57.     )
  58.     (cond
  59.       ;; Nested object. First attribute reference is updated:
  60.       ((cdddr selLst)
  61.         (if (setq attLst (vlax-invoke (vlax-ename->vla-object (last (cadddr selLst))) 'getattributes))
  62.           (vla-put-textstring (car attLst) (itoa i))
  63.           (princ "\nError: invalid nested object ")
  64.         )
  65.       )
  66.       ;; Non-nested mtext, text and attribute definition:
  67.       ((vlax-property-available-p (setq obj (vlax-ename->vla-object (car selLst))) 'textstring)
  68.         (vla-put-textstring obj (itoa i))
  69.       )
  70.       (T
  71.         (princ "\nError: invalid object ")
  72.       )
  73.     )
  74.   )
  75.   (princ)
  76. )
  77.