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,343 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,344 Views
29 Replies
Replies (29)
Message 2 of 30

ВeekeeCZ
Consultant
Consultant

See Lee's commentary:

;; Get Attribute Value  -  Lee Mac
;; Returns the value held by the specified tag within the supplied block, if present.
;; blk - [vla] VLA Block Reference Object
;; tag - [str] Attribute TagString
;; Returns: [str] Attribute value, else nil if tag is not found.

(defun LM:vl-getattributevalue ( blk tag )
...

 

 So...

(setq atr (LM:getattributevalue (vlax-ename->vla-object ensel) tag))

 

 Or is this as it was before that you're selecting a nested entity... 

0 Likes
Message 3 of 30

C.Utzinger
Collaborator
Collaborator

Thank you

but i does not work:

Fehlerhafter Argumenttyp: lentityp #<VLA-OBJECT IAcadAttributeReference 000000006e7357b8>

 

0 Likes
Message 4 of 30

ВeekeeCZ
Consultant
Consultant
Accepted solution

Sorry, I did not realize that Lee has both method there, vla and vanilla.

But I still do think that we were solving this issue before... it was something with re-selection leaders??

 

Anyway, this should work.

(setq atr (LM:getattributevalue (cdr (assoc 330 (entget ensel))) tag))

But you should test a selection if that really was an attribute...

0 Likes
Message 5 of 30

C.Utzinger
Collaborator
Collaborator

Thank you

 

Now it works.

 


But you should test a selection if that really was an attribute...


What do you mean?

 

Kind regards

0 Likes
Message 6 of 30

ВeekeeCZ
Consultant
Consultant

@C.Utzingerwrote:

 

... 

But you should test a selection if that really was an attribute...


What do you mean?

 

....

You know what I mean, always make sure that input values are as expected

(if (and (setq ensel (car (nentsel)))
         (= "ATTRIB" (cdr (assoc 0 (entget ensel))))
         )
  (setq tag (cdr (assoc 2 (entget ensel)))
        atr (LM:getattributevalue (cdr (assoc 330 (entget ensel))) tag))
  (alert "Error: Attribute selection failed. "))
0 Likes
Message 7 of 30

C.Utzinger
Collaborator
Collaborator

Ah of course

thank you again!

 

Kind regards

0 Likes
Message 8 of 30

C.Utzinger
Collaborator
Collaborator

HI

I have a little question

The following code works fine, but only if all objects are visible on the Screen. They don´t change if they are not.

I think there is a little stupid thing y don´t know. 

 

(defun c:<Test1 ( / titpt stnro tag obj snum snumn snumv stnro)

(vl-load-com)

  (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)))

  (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 titpt (cdr (assoc 10 (entget (car (entsel "\nTitelblatt wählen: ")))))             ;Einfügepunkt Titelblatt
        stnro (subst (+ (car titpt) 404) (car titpt) titpt)
        stnro (subst (- (cadr stnro) 20) (cadr stnro) stnro))

  (while (and (setq ensel (car (nentselp stnro)))
              (= "ATTRIB" (cdr (assoc 0 (entget ensel))))
      )
      (setq tag (cdr (assoc 2 (entget ensel)))
            obj (vlax-ename->vla-object (cdr (assoc 330 (entget ensel))))
            snum (LM:getattributevalue (cdr (assoc 330 (entget ensel))) tag)               ;Seitennummer
            snumn (if (= (substr snum 3 1) "/")
                      (itoa (+ (atoi (substr snum 4)) 1))
                      (itoa (+ (atoi (substr snum 3)) 1)))
            snumv (strcat (vl-string-right-trim "0123456789" snum) snumn)                  ;Seitennummer neu
            stnro (subst (+ (car stnro) 210) (car stnro) stnro)
      )           
     (LM:vl-setattributevalue obj tag snumv)
  )

(prin1)
)
0 Likes
Message 9 of 30

ВeekeeCZ
Consultant
Consultant

Hard to image since you didn't attached a dwg... !?!
But you can always ZOOM there (make a window from your selpoint + some surroundings according the offset you set.

Or do simply ZOOM Extents. Then ZOOM back.

0 Likes
Message 10 of 30

C.Utzinger
Collaborator
Collaborator

OK

Attached i send you a dwg.  I'm not finished, it' s just a part of it. 

The aim is to change all pagenumbers, like 2/14 to 2/15.

It works if you have all pages on the screen. But if they are not, the Routine only changes the ones they are.

 

 

(defun c:<Test1 ( / *error* oATTREQ oATTDIA titpt stnro tag obj snum snumn snumv)

(vl-load-com)

  (defun *error* (errmsg)
    (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break"))
      (princ (strcat "\nError: " errmsg)))
         (setvar 'ATTREQ oATTREQ)
         (setvar 'ATTDIA oATTDIA)
    	 (vla-endundomark adoc)
	 (princ "\nAlles rückgängig gemacht! ")
    (princ))

  (vla-endundomark (setq adoc (vla-get-activedocument (vlax-get-acad-object))))
  (vla-startundomark adoc)
  (setq oATTREQ (getvar 'ATTREQ)
        oATTDIA (getvar 'ATTDIA))
  (setvar 'ATTREQ 0)
  (setvar 'ATTDIA 0)


  (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)))

  (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 titpt (cdr (assoc 10 (entget (car (entsel "\nTitelblatt wählen: ")))))             ;Einfügepunkt Titelblatt
        stnro (subst (+ (car titpt) 404) (car titpt) titpt)
        stnro (subst (- (cadr stnro) 20) (cadr stnro) stnro))

  (while (and (setq ensel (car (nentselp stnro)))
              (= "ATTRIB" (cdr (assoc 0 (entget ensel))))
      )
      (setq tag (cdr (assoc 2 (entget ensel)))
            obj (vlax-ename->vla-object (cdr (assoc 330 (entget ensel))))
            snum (LM:getattributevalue (cdr (assoc 330 (entget ensel))) tag)               ;Seitennummer
            snumn (if (= (substr snum 3 1) "/")
                      (itoa (+ (atoi (substr snum 4)) 1))
                      (itoa (+ (atoi (substr snum 3)) 1)))
            snumv (strcat (vl-string-right-trim "0123456789" snum) snumn)                  ;Seitennummer neu
            stnro (subst (+ (car stnro) 210) (car stnro) stnro)
      )           
     (LM:vl-setattributevalue obj tag snumv)
  )

  (setvar 'ATTREQ oATTREQ)
  (setvar 'ATTDIA oATTDIA)
  (vla-endundomark adoc)

(prin1)
)
0 Likes
Message 11 of 30

ВeekeeCZ
Consultant
Consultant

Well, as I've said, you can use the ZOOM command, BUT!!!

 

I would definitely change the approach - select all the $el-lsnr blocks, get att values, sort them by X coord... It would be MUCH MORE reliable than your nentselp. I think you're skilled enough to write such code, or you'll learn some.

Forget about the (nentselp), seriously.

Easy Peasy. Good luck though!

0 Likes
Message 12 of 30

C.Utzinger
Collaborator
Collaborator

Thank you

The Zoom does not work :(.

I will try :)...

 

Best Regards

0 Likes
Message 13 of 30

ВeekeeCZ
Consultant
Consultant

@C.Utzingerwrote:

Thank you

The Zoom does not work :(.

I will try :)...

 

Best Regards


Probably not precise enough. If you zoom close enough, it should work. But in such cases we usually use some kind of (ssget) function - to make window selection, or fence selection, with filter or not. 

Anyway, this issue was solved by Autocad 2018+ which allows selection off screen by default.

 

But as being say, those methods you should only use when no other option is on the table. Slow and less reliable.

Message 14 of 30

cadffm
Consultant
Consultant
I totally agree with @Anonymous

For your understanding, that have nothing to do with lisp,
thats how the Acad object seletion works!

"Since Anyway, this issue was solved by Autocad 2018+ which allows selection off"

But this isn't not the only important/problem point of object selection.

Another part of the (view depend) object selection is the precition.
The result of view depended selection modes like window selection are different between your current zoom-level.
Near to objects it works well, zoom out (far) the object selection can select object which outer your coordinates.

Use view depend selectionmodes with care.

Sebastian

0 Likes
Message 15 of 30

C.Utzinger
Collaborator
Collaborator

HI

Need a Little Hand please

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

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

 

(defun c:<Test1 ( / *error* oVAR nVAR titpt titptg ent tag loop ss obj i data data2 lnum snum lstr lend)

(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-getattributes ( blk )
    (mapcar '(lambda (att) (cons (vla-get-tagstring att) (vla-get-textstring att)))
            (vlax-invoke blk 'getattributes)))

(defun LM:vl-setattributevalue ( blk tag val )
    (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 CMDECHO))))
  (setvar 'ATTREQ 0)
  (setvar 'ATTDIA 0)

  (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))))
              data (cons (LM:vl-getattributes obj) data)))

  (setq lnum (cdr(car(car data)))                                                                      ;Listennummer
        snum (substr (cdr(car(cdr(car data)))) 3)                                                      ;Seitenanzahl
  )
 

  (setq lend (subst (+ (car titpt) (* 420 (atoi snum))) (car titpt) titpt)
        lend (subst (- (cadr lend) 297) (cadr lend) lend)
        ss   (ssget "_W" titpt lend (list '(0 . "INSERT") (cons 2 "$el-lsnr,spi-dk-eisenliste-titel") '(66 . 1))))

      (repeat (setq i (sslength ss))
        (setq obj (vlax-ename->vla-object (ssname ss (setq i (1- i))))
              data2 (cons (LM:vl-getattributes obj) data2)))

(foreach e ss
   (LM:vl-setattributevalue e "SeitenNr" "1/1")
)

  (mapcar 'setvar nVAR oVAR)
  (vla-endundomark adoc)
(prin1)
)
0 Likes
Message 16 of 30

C.Utzinger
Collaborator
Collaborator

OMG

ssget does not select the blocks they are not on the screen.

 

(ssget "_W" titpt lend (list '(0 . "INSERT") (cons 2 "$el-lsnr,spi-dk-eisenliste-titel") '(66 . 1))))
0 Likes
Message 17 of 30

cadffm
Consultant
Consultant

Thats not a Lisp thing, that usual for autocad object graphical selection modes

(in prior versions or SELECTIONOFFSCREEN is set to 0)

 

That how million of users work with, every day.

Sebastian

Message 18 of 30

C.Utzinger
Collaborator
Collaborator

Cool

In my case it was on "1", but with "2" it works.

 

Thank you!

0 Likes
Message 19 of 30

cadffm
Consultant
Consultant

Right, 2 is the value for automation.

 

So you you have to limit you code is only running in Versions since 2017.1 (sysvar vernum)

or you need a second way for older version (zoom drawing well for the selection part)

 

And since 2017.1 you have to handle the system variable selectionoffscreen in your code.

store value, changing to 2, restore changing. directly and should taken into account in your *error* function.

 


Please read my earlier answer again, about a second special of autocad graphical object selection, like mode "W"/Windows is.

Sebastian

Message 20 of 30

C.Utzinger
Collaborator
Collaborator

Thank you

The version is not a problem, we all work with the newest one.

 

 

0 Likes