After insert a block, get attribute value from another block...

After insert a block, get attribute value from another block...

C.Utzinger
Collaborator Collaborator
3,334 Views
29 Replies
Message 1 of 30

After insert a block, get attribute value from another block...

C.Utzinger
Collaborator
Collaborator

HI

I need a little help

The aim is get the Attribute value from a existing block after insert a new one.

It should be easy, but i'm to dumb...

 

 

(defun c:<Test1 (/ pp ensel tag atr)

  ;; Lee Mac
  ;; http://www.lee-mac.com/attributefunctions.html

  (defun LM:getattributevalue ( blk tag / val enx )
    (while
        (and
            (null val)
            (= "ATTRIB" (cdr (assoc 0 (setq enx (entget (setq blk (entnext blk)))))))
        )
        (if (= (strcase tag) (strcase (cdr (assoc 2 enx))))
            (setq val (cdr (assoc 1 enx)))
        )
    )
  )

(setq pp (getpoint "\nEinfügepunkt wählen: ") 
      pp (subst (- (car pp) 170) (car pp) pp)
      pp (subst (+ (cadr pp) 277) (cadr pp) pp))

(setq ensel (car (nentselp pp)))
(setq tag (cdr (assoc 2 (entget ensel))))
(setq atr (LM:getattributevalue ????? tag))

(princ atr)

(prin1)
)
0 Likes
Accepted solutions (4)
3,335 Views
29 Replies
Replies (29)
Message 21 of 30

ВeekeeCZ
Consultant
Consultant

@C.Utzingerwrote:

 

How can i get the "[vla] VLA Block Reference Object" of an object in a selection set?

 


The same way as you did already twice in the code.

 


@C.Utzingerwrote:

 

...

I don't know how to get on... Are I on the right way?

 


Not really sure what you're after - a quick overlook tells me, that the other way around would be better - select all the blocks of the name and check the coordinates and/or attributes to identify which you're looking for to change.

0 Likes
Message 22 of 30

C.Utzinger
Collaborator
Collaborator

So...

Thank you for the hint...

 


@ВeekeeCZwrote:

 


The same way as you did already twice in the code.



 UPS!!!

 

Now the routine works perfect.

Make it the other way around like you propose i think is more complicated, while there can be a lot of lists.

I tried to simplificate it as much i could. Give me your opinion please.

 

Kind regards

 

 

(defun c:<Test1 ( / *error* oVAR nVAR titpt titptg ent tag loop ss obj i data lnum snum snumn snuml bestl snrpt lstr lend ltit titn)

(vl-load-com)

  (defun *error* (errmsg)
    (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break,end"))
      (princ (strcat "\nError: " errmsg)))
         (mapcar 'setvar nVAR oVAR)
    	 (vla-endundomark adoc)
    (princ))

  (defun LM:vl-getattributevalue ( blk tag )
    (setq tag (strcase tag))
    (vl-some '(lambda ( att ) (if (= tag (strcase (vla-get-tagstring att))) (vla-get-textstring att))) (vlax-invoke blk 'getattributes)))

  (defun LM:vl-setattributevalue ( blk tag val )  ;blk as obj name requiered
    (setq tag (strcase tag))
    (vl-some '(lambda ( att )
                (if (= tag (strcase (vla-get-tagstring att)))
                  (progn (vla-put-textstring att val) val)))
             (vlax-invoke blk 'getattributes)))

  (or *einhsk* (setq *einhsk* 1))

  (vla-endundomark (setq adoc (vla-get-activedocument (vlax-get-acad-object))))
  (vla-startundomark adoc)
  (setq oVAR (mapcar 'getvar (setq nVAR '(ATTREQ ATTDIA CLAYER SELECTIONOFFSCREEN))))
  (setvar 'ATTREQ 0)
  (setvar 'ATTDIA 0)
  (setvar 'SELECTIONOFFSCREEN 2)

  (if (tblsearch "block" "SPI-DK-Eisenliste_Bl")
         T
         (progn (command "_.insert" "SPI-DK-Eisenliste_Bl")(command)))

  (while (= loop nil)
    (if (and (setq ent (car (entsel "\nTitelblatt wählen: ")))
             (equal (cdr(assoc 0 (entget ent))) "INSERT")
             (= (strcase (vla-get-effectivename (vlax-ename->vla-object ent))) "EL_1"))
        (setq titpt (cdr (assoc 10 (entget ent)))                                                                  ;Einfügepunkt Titelblatt
              loop  1)
    )
  )

  (setq titptg (subst (+ (car titpt) 420) (car titpt) titpt)
        titptg (subst (- (cadr titptg) 297) (cadr titptg) titptg)
        ss     (ssget "_W" titpt titptg (list '(0 . "INSERT") (cons 2 "$el-titel,$el-lsnr") '(66 . 1))))

      (repeat (setq i (sslength ss))
        (setq obj (vlax-ename->vla-object (ssname ss (setq i (1- i))))
              lnum (LM:vl-getattributevalue obj "BetonStahlListeNr")                                               ;Listennummer
              snum (cond ((LM:vl-getattributevalue obj "SeitenNr"))(snum))
              ltit (cond ((LM:vl-getattributevalue obj "Bauteil"))(ltit))                                          ;Listentitel
        )                                             
      )

  (setq snum (substr snum 3)                                                                                       ;Seitenanzahl
        snumn (itoa (+ (atoi snum) 1))                                                                             ;Seitenanzahl neu
        snuml (strcat snumn "/" snumn)                                                                             ;Seitenzahl Titel neu
        snrpt (subst (- (cadr titpt) 297) (cadr titpt) titpt)                                                      ;Einfügepunkt Seitennummertext
        lend (subst (+ (car snrpt) (* 210 (atoi snum))) (car snrpt) snrpt)                                         ;Einfügepunkt neue Liste
        titn (subst (+ (car lend) 100.715) (car lend) lend)
        titn (subst (+ (cadr titn) 277.732) (cadr titn) titn)                                                      ;Einfügepunkt Listentitel
        ss   (ssget "_W" titpt lend (list '(0 . "INSERT")(cons 2 "$el-lsnr,spi-dk-eisenliste-titel,spi-dk-eisenliste-text") '(66 . 1))))
        
  (repeat (setq i (sslength ss))
     (setq obj  (vlax-ename->vla-object (ssname ss (setq i (1- i))))
           data (cond ((LM:vl-getattributevalue obj "SeitenNr"))(data))
           data (strcat (vl-string-right-trim "0123456789" data) snumn)   
     )
     (LM:vl-setattributevalue (vlax-ename->vla-object (ssname ss i)) "SeitenNr" data)
     (if (LM:vl-setattributevalue (vlax-ename->vla-object (ssname ss i)) "Seitennummer" snumn)
         (setq bestl 1))
  )

  (setvar 'CLAYER "0")
  (command "-stil" "BEW2" "simplex.shx" (* 4 *einhsk*) "0.7" "0" "_n" "_n" "_n")
  (command "_.mtext" titn "a" "ml" titn ltit "")

  (if (tblsearch "LAYER" "EISENLISTE")
      (setvar 'CLAYER "EISENLISTE") 
      (command "_.-LAYER" "_m" "EISENLISTE" "_co" "7" "EISENLISTE" ""))

  (command "_.INSERT" "spi-dk-eisenliste-titel" "_s" *einhsk* "_r" 0 lend)										
  (setq en-blk1 (entlast))
  (LM:vl-setattributevalue (vlax-ename->vla-object en-blk1) "BetonStahlListeNr" lnum)
  (LM:vl-setattributevalue (vlax-ename->vla-object en-blk1) "SeitenNr" snuml)
  (command "_.INSERT" "*spi-dk-eisenliste-blatt" lend *einhsk* 0)
  (if (not bestl)
      (progn
        (vl-cmdf "_.INSERT" "spi-dk-eisenliste-text" "_s" *einhsk* "_r" 0 snrpt)											
        (setq en-blk2 (entlast))
        (LM:vl-setattributevalue (vlax-ename->vla-object en-blk2) "Seitennummer" snumn)
      )
  )

  (mapcar 'setvar nVAR oVAR)
  (vla-endundomark adoc)
(prin1)

); end of defun

 

0 Likes
Message 23 of 30

ВeekeeCZ
Consultant
Consultant

@C.Utzingerwrote:

 

... I tried to simplificate it as much i could. Give me your opinion please. ...

  

(defun c:<Test1 ( / *error* oVAR nVAR titpt titptg ent tag loop ss obj i data lnum snum snumn snuml bestl snrpt lstr lend ltit titn) ; are they all?

(vl-load-com)

  (defun *error* (errmsg)
    (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break,end"))
      (princ (strcat "\nError: " errmsg)))
         (mapcar 'setvar nVAR oVAR)
    	 (vla-endundomark adoc)
    (princ))

  (defun LM:vl-getattributevalue ( blk tag ) ; either inside and local or outside.
    (setq tag (strcase tag))
    (vl-some '(lambda ( att ) (if (= tag (strcase (vla-get-tagstring att))) (vla-get-textstring att))) (vlax-invoke blk 'getattributes)))

  (defun LM:vl-setattributevalue ( blk tag val )  ;blk as obj name requiered
    (setq tag (strcase tag))
    (vl-some '(lambda ( att )
                (if (= tag (strcase (vla-get-tagstring att)))
                  (progn (vla-put-textstring att val) val)))
             (vlax-invoke blk 'getattributes)))

  (or *einhsk* (setq *einhsk* 1))

  (vla-endundomark (setq adoc (vla-get-activedocument (vlax-get-acad-object))))
  (vla-startundomark adoc)
  (setq oVAR (mapcar 'getvar (setq nVAR '(ATTREQ ATTDIA CLAYER SELECTIONOFFSCREEN))))
  (setvar 'ATTREQ 0)
  (setvar 'ATTDIA 0)
  (setvar 'SELECTIONOFFSCREEN 2)

  (if (tblsearch "block" "SPI-DK-Eisenliste_Bl")  ; keep consistent in solving same logic issues. More readable. See down the code a different solution
         T
         (progn (command "_.insert" "SPI-DK-Eisenliste_Bl")(command)))

  (while (= loop nil) ; do you really need this var? Do you need if?
    (if (and (setq ent (car (entsel "\nTitelblatt wählen: ")))
             (equal (cdr(assoc 0 (entget ent))) "INSERT") ; why equal?
             (= (strcase (vla-get-effectivename (vlax-ename->vla-object ent))) "EL_1"))
        (setq titpt (cdr (assoc 10 (entget ent)))                                                                  ;Einfügepunkt Titelblatt
              loop  1)
    )
  )

  (setq titptg (subst (+ (car titpt) 420) (car titpt) titpt)
        titptg (subst (- (cadr titptg) 297) (cadr titptg) titptg)
        ss     (ssget "_W" titpt titptg (list '(0 . "INSERT") (cons 2 "$el-titel,$el-lsnr") '(66 . 1)))) ; why list and cons?

      (repeat (setq i (sslength ss))
        (setq obj (vlax-ename->vla-object (ssname ss (setq i (1- i))))
              lnum (LM:vl-getattributevalue obj "BetonStahlListeNr")                                               ;Listennummer
              snum (cond ((LM:vl-getattributevalue obj "SeitenNr"))(snum)) ; clever, but would have be better to sort blocks by a name?
              ltit (cond ((LM:vl-getattributevalue obj "Bauteil"))(ltit))                                          ;Listentitel
        )                                             
      )

  (setq snum (substr snum 3)                                                                                       ;Seitenanzahl
        snumn (itoa (+ (atoi snum) 1))   ; we also have 1+ function                                                                          ;Seitenanzahl neu
        snuml (strcat snumn "/" snumn)                                                                             ;Seitenzahl Titel neu
        snrpt (subst (- (cadr titpt) 297) (cadr titpt) titpt)                                                      ;Einfügepunkt Seitennummertext
        lend (subst (+ (car snrpt) (* 210 (atoi snum))) (car snrpt) snrpt)                                         ;Einfügepunkt neue Liste
        titn (subst (+ (car lend) 100.715) (car lend) lend)
        titn (subst (+ (cadr titn) 277.732) (cadr titn) titn)                                                      ;Einfügepunkt Listentitel
        ss   (ssget "_W" titpt lend (list '(0 . "INSERT")(cons 2 "$el-lsnr,spi-dk-eisenliste-titel,spi-dk-eisenliste-text") '(66 . 1))))
        
  (repeat (setq i (sslength ss))
     (setq obj  (vlax-ename->vla-object (ssname ss (setq i (1- i))))
           data (cond ((LM:vl-getattributevalue obj "SeitenNr"))(data))
           data (strcat (vl-string-right-trim "0123456789" data) snumn)   
     )
     (LM:vl-setattributevalue (vlax-ename->vla-object (ssname ss i)) "SeitenNr" data) ; why?
     (if (LM:vl-setattributevalue (vlax-ename->vla-object (ssname ss i)) "Seitennummer" snumn)
         (setq bestl 1))
  )

  (setvar 'CLAYER "0")
  (command "_.style" "BEW2" "simplex.shx" (* 4 *einhsk*) "0.7" "0" "_n" "_n" "_n")
  (command "_.mtext" titn "_j" "_ml" titn ltit "")

  (if (tblsearch "LAYER" "EISENLISTE")
      (setvar 'CLAYER "EISENLISTE") 
      (command "_.-LAYER" "_m" "EISENLISTE" "_co" "7" "EISENLISTE" ""))
(command "_.-LAYER" "_t" "EISENLISTE" "_m" "EISENLISTE" "_co" "7" "EISENLISTE" "")) ; also possible, maybe little more suitable
  (command "_.INSERT" "spi-dk-eisenliste-titel" "_s" *einhsk* "_r" 0 lend)		; I see OSNAPs still on.								
  (setq en-blk1 (entlast)) ; why you save the ename? what for?
  (LM:vl-setattributevalue (vlax-ename->vla-object en-blk1) "BetonStahlListeNr" lnum)
  (LM:vl-setattributevalue (vlax-ename->vla-object en-blk1) "SeitenNr" snuml)
  (command "_.INSERT" "*spi-dk-eisenliste-blatt" lend *einhsk* 0)
  (if (not bestl) ; is this var necessary? Why you solve this so far from place where you identified missing block?
      (progn
        (vl-cmdf "_.INSERT" "spi-dk-eisenliste-text" "_s" *einhsk* "_r" 0 snrpt)											
        (setq en-blk2 (entlast)) ; why?
        (LM:vl-setattributevalue (vlax-ename->vla-object en-blk2) "Seitennummer" snumn)
      )
  )

  (mapcar 'setvar nVAR oVAR)
  (vla-endundomark adoc)
(prin1)

); end of defun

 


Ok, I see.

couple of questions you to answer (to yourself). Same things not commented multiple times.

Message 24 of 30

C.Utzinger
Collaborator
Collaborator
Accepted solution

HI

Thank you very much!

OMG i'm so dumb :-). So many things I should have seen.

OK i have fixed it, but there are some points i don't know:

 

(defun c:<Test1 ( / *error* oVAR nVAR titpt titptg ent tag ss obj i data lnum snum snumn snuml bestl snrpt lstr lend ltit blk)

(vl-load-com)

  (defun *error* (errmsg)
    (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break,end"))
      (princ (strcat "\nError: " errmsg)))
         (mapcar 'setvar nVAR oVAR)
    	 (vla-endundomark adoc)
    (princ))

  (defun LM:vl-getattributevalue ( blk tag )
    (setq tag (strcase tag))
    (vl-some '(lambda ( att ) (if (= tag (strcase (vla-get-tagstring att))) (vla-get-textstring att))) (vlax-invoke blk 'getattributes)))

  (defun LM:vl-setattributevalue ( blk tag val )  ;blk as obj name requiered
    (setq tag (strcase tag))
    (vl-some '(lambda ( att )
                (if (= tag (strcase (vla-get-tagstring att)))
                  (progn (vla-put-textstring att val) val)))
             (vlax-invoke blk 'getattributes)))

  (or *einhsk* (setq *einhsk* 1))

  (vla-endundomark (setq adoc (vla-get-activedocument (vlax-get-acad-object))))
  (vla-startundomark adoc)
  (setq oVAR (mapcar 'getvar (setq nVAR '(ATTREQ ATTDIA CMDECHO CLAYER SELECTIONOFFSCREEN))))
  (setvar 'ATTREQ 1)
  (setvar 'ATTDIA 0)
  (setvar 'CMDECHO 0)
  (setvar 'SELECTIONOFFSCREEN 2)

  (command "_.-LAYER" "_t" "EISENLISTE" "_m" "EISENLISTE" "_co" "7" "EISENLISTE" "") The other way was because if the user prefer for example an other color of layer, then i wont change. But in this case doesn't matter. 

  (if (not (tblsearch "block" "SPI-DK-Eisenliste_Bl"))
      (progn (command "_.insert" "SPI-DK-Eisenliste_Bl")(command)))

  (while (not (and (setq ent (car (entsel "\nTitelblatt wählen: ")))
         (= (cdr(assoc 0 (entget ent))) "INSERT")
         (= (strcase (vla-get-effectivename (vlax-ename->vla-object ent))) "EL_1")
         (setq titpt (cdr (assoc 10 (entget ent))))))                                                              ;Einfügepunkt Titelblatt    
  )

  (setq titptg (subst (+ (car titpt) 420) (car titpt) titpt)
        titptg (subst (- (cadr titptg) 297) (cadr titptg) titptg)
        ss     (ssget "_W" titpt titptg '((0 . "INSERT")(2 . "$el-titel,$el-lsnr"))))

      (repeat (setq i (sslength ss))
        (setq obj (vlax-ename->vla-object (ssname ss (setq i (1- i))))
              lnum (LM:vl-getattributevalue obj "BetonStahlListeNr")                                               ;Listennummer
              snum (cond ((LM:vl-getattributevalue obj "SeitenNr"))(snum)) Sort, how? and then?
              ltit (cond ((LM:vl-getattributevalue obj "Bauteil"))(ltit))  Sort, how? and then?                                       ;Listentitel
        )                                             
      )

  (setq snum (substr snum 3)                                                                                       ;Seitenanzahl
        snumn (itoa (1+ (atoi snum)))                                                                              ;Seitenanzahl neu
        snuml (strcat snumn "/" snumn)                                                                             ;Seitenzahl Titel neu
        snrpt (subst (- (cadr titpt) 297) (cadr titpt) titpt)                                                      ;Einfügepunkt Seitennummertext
        lend (subst (+ (car snrpt) (* 210 (atoi snum))) (car snrpt) snrpt)                                         ;Einfügepunkt neue Liste
        ss   (ssget "_W" titpt lend '((0 . "INSERT")(2 . "$el-lsnr,spi-dk-eisenliste-titel,spi-dk-eisenliste-text"))))
        
  (repeat (setq i (sslength ss))
     (setq obj  (vlax-ename->vla-object (ssname ss (setq i (1- i))))
           data (cond ((LM:vl-getattributevalue obj "SeitenNr"))(data))
           data (if data (strcat (vl-string-right-trim "0123456789" data) snumn) nil)   
     )
     (LM:vl-setattributevalue obj "SeitenNr" data)
     (if (LM:vl-setattributevalue obj "Seitennummer" snumn)
         (setq bestl 1))  I don't know how to get rid of it and not insert 10 times the block!     
  )

  (command "_.INSERT" "spi-dk-eisenliste-titel" "_s" *einhsk* "_r" 0 lend lnum ltit snuml)
  (command "_.INSERT" "*spi-dk-eisenliste-blatt" lend *einhsk* 0)
  (if (not bestl)
      (command "_.INSERT" "spi-dk-eisenliste-text" "_s" *einhsk* "_r" 0 snrpt snumn "")
  )

  (*error* "end")
(prin1)

); end of defun
0 Likes
Message 25 of 30

ВeekeeCZ
Consultant
Consultant
Accepted solution

Just heard, its 2:2. Not watching, but could be interesting if only + points we got from this WC was beating the future champion. But congrats anyway, even a final is great succes.

 

Back to the topic. 

You should get use to localizing all sub-functions, even the Lee's ones, if you put those inside your routine.

You also didn't turn off the OSMODE yet.

The other things you can sure keep as you already have. 

 

 

(setq snum (cond ((LM:vl-getattributevalue obj "SeitenNr"))(snum)) Sort, how? and then?

Well, personally don't like very much that you basically ignore a block name and sort this just by an attribute name.

Sorting by block name probably get the code more complicated and it might be useless it this case, but it may open you a lot of possibilities. So I've written you couple of lines just to give you some simple examples of taking advantige from working with lists. Useful, if not for this code, then just for the learning purpose. 

 

(defun :BlocksByNames (ss)
;; return list of pairs '(blk-name . obj)
 (mapcar '(lambda (x / obj)
	    (cons (if (vlax-property-available-p (setq obj (vlax-ename->vla-object x)) 'EffectiveName)
		    (vla-get-EffectiveName obj)
		    (vla-get-Name obj))
		  obj))
	 (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))))

;; turn ss into lst
(setq lst (:BlocksByNames (ssget '((0 . "INSERT")))))

;; then you can sort them by names
(foreach itm lst
  (cond ((= (car itm) "$el-lsnr")
	 (...))
	(wcmatch (= (car itm) "$el-lsnr,some-other-name")
	 (...))

;; or test if there is some at ss
(if (assoc "$el-lsnr" lst)
  ...)

;; or make a list of blocks of particular name
(setq lst2 (vl-remove-if-not '(lambda (x) (= (car x) "$el-pos")) lst))

;; or count them
(length lst2)

 

Message 26 of 30

C.Utzinger
Collaborator
Collaborator

HI

UPS they lost, lol.

 

Thank you very much.

That gives me a lot of ideas.

But why should I turn off the OSNAP?

 

Kind regards

0 Likes
Message 27 of 30

cadffm
Consultant
Consultant

"But why should I turn off the OSNAP?"

Because you are using graphical object selection mode (ssget "_W" ....)  and you can not be sure which window ponts are used for your ssget when osnapcoord is set to 0 or 2.

On top of your program set osnapcoord to value 1, this disabled running object snap for automations.

 

 

Sebastian

0 Likes
Message 28 of 30

ВeekeeCZ
Consultant
Consultant
Accepted solution

@C.Utzingerwrote:

 

... But why should I turn off the OSNAP? ...

 


What I had in mind was that all points set using the (command ... pnt ...) function are effected by running OSNAPs. Then it's very unpredictable, depending on current zoom level as well. 

 

Either turn off osmode or use "_non" in front of each point

(vl-cmdf "_.INSERT" "spi-dk-eisenliste-text" "_s" *einhsk* "_r" 0 "_non" snrpt)

 

I cannot confirm what @cadffm says. I think that points within the (ssget) are not affected by OSNAPs, but I could be wrong. Didn't found any documentation remarks nor (my) proved by (my) experience. Never had such issue. (not talking about ZOOM)

Message 29 of 30

cadffm
Consultant
Consultant

The statement above was wrong because here the ssget lisp function was used and not the normal object selection is controlled by the command line (command). BeekeeCZ is quite right there (thanks for the correction).
{{Except for the problematic case of zoom -ependency, but this is another problem}}
Sorry for the unnecessary confusion.

Sebastian

0 Likes
Message 30 of 30

C.Utzinger
Collaborator
Collaborator

HI

Thank you very much for your time, again I learned a lot :).

 

Sorry for my late answer, I was on Holidays.

 

Best regards

0 Likes