SELECTION SET ATTRIBUTE

SELECTION SET ATTRIBUTE

Anonymous
Not applicable
2,224 Views
14 Replies
Message 1 of 15

SELECTION SET ATTRIBUTE

Anonymous
Not applicable

The attached block has several att, I would like to number with a prefix TAG = Number,
, why does not the code work?

 

(defun c:Test  (/ dat ent etdata found post pre ss1)
  (setq pre  (getstring "\nPrefix: ")
	post (1- (getint "\nSufix: ")))
  (while
    (setq ss1 (ssget ":s" '((0 . "insert") (66 . 1))))
    (setq found ()
	  dat   (strcat pre (itoa (setq post (1+ post))))
	  ent   (ssname ss1 0))
    (while (and (setq ent (entnext ent)) (null found))
      (setq etdata (entget ent))
      (and (= (cdr (assoc 0 etdata)) "ATTRIB")
	   (= (cdr (assoc 2 etdata)) "ADSKFACTORY:Custom.ASSET_TAG")
	   (setq found t)
	   (entmod
	     (subst (cons 1 dat) (assoc 1 etdata) etdata)
	     )
	   )
      )
    )
  (princ)
  )
0 Likes
Accepted solutions (2)
2,225 Views
14 Replies
Replies (14)
Message 2 of 15

ВeekeeCZ
Consultant
Consultant
You need to use the (entupd ent) function to update the block.

See Lee's example
http://www.lee-mac.com/attributefunctions.html
0 Likes
Message 3 of 15

Moshe-A
Mentor
Mentor

Frjuniornogueira,

 

first, well done! i see you are trying to learn autolisp and with your 'premission' i would like to note some coding issues starting with user input:

(setq pre  (getstring "\nPrefix: ")
 post (1- (getint "\nSufix: ")))

if the user fail to enter the right values this will fail so it is better to check what is comming-in in order to make sure your program will work as you design it to work (see example below)

 (while
    (setq ss1 (ssget ":s" '((0 . "insert") (66 . 1))))

    .......

    .......

)

the ":s" argument will let the user to select only one time. that means he can choose to select by pick or any other windows or crossing but only once and if he misses? it is true it is in a while loop but it is better to let the user to select objects as much as he wants and after that to interate the selection set.

 

(while (and (setq ent (entnext ent)) (null found))
    (setq etdata (entget ent))
     (and (= (cdr (assoc 0 etdata)) "ATTRIB")
              (= (cdr (assoc 2 etdata)) "ADSKFACTORY:Custom.ASSET_TAG")
              (setq found t)
             (entmod  (subst (cons 1 dat) (assoc 1 etdata) etdata)
      )
 )

 

if the (entmod) function (somehow will be failed) the (and) expression will return nil but the while loop will end with found=T. so some times it is good to put as many test expressions and  body expression inside (and)

but some time not.

 

see the code bellow how would i do it

(defun c:test (/ pre post ss1 found dat ent edata)
 (if (and
       (/= (setq pre  (getstring "\nPrefix: ") "")
       (not (initget (+ 2 4))
       (setq post (1- (getint "\nSufix: ")))
     )
  (progn
   (setq i -1) 
   (while (setq ss1 (ssget '((0 . "insert") (66 . 1))))
    (setq i (1+ i))
    (setq found ()
	 dat   (strcat pre (itoa (1+ post)))
	 ent   (ssname ss1 i)
    )

    (while (and (setq ent (entnext ent)) (null found))
     (setq etdata (entget ent))
     (if (and
	   (= (cdr (assoc 0 etdata)) "ATTRIB")
	   (= (cdr (assoc 2 etdata)) "ADSKFACTORY:Custom.ASSET_TAG")
	 )
      (progn	   
       (entmod (subst (cons 1 dat) (assoc 1 etdata) etdata)
       (entupd (cdar edata))
       (setq found t)
      ); progn
     ); if
    ); inner while
   ); outer while
  ); progn
 ); if
); c:test

 

 

have a nide day

Moshe

Message 4 of 15

Anonymous
Not applicable

@Moshe-A 
You are an EXCELLENT teacher !!!! Robot LOL  
But the above code still does not work! because? Smiley Frustrated Smiley Frustrated

 

0 Likes
Message 5 of 15

dlanorh
Advisor
Advisor

You are accessing a Block REFERENCE. You need to access the block DEFINITION

Get the block name from the  entity data then

 

;get the block entity        
(setq ent (tblobjname "block" blkname)) (while (setq ent (entnext ent));loop through block entities ;do what you need here )

 

 

I am not one of the robots you're looking for

Message 6 of 15

Moshe-A
Mentor
Mentor

I did not said i test it, only suggest good coding

but i will try it very soon.

Message 7 of 15

dlanorh
Advisor
Advisor
Having re-read you initial post my above post may be wrong if you are trying to alter the text string, so
are you trying to access the Attribute TAG, or the Attribute text string?

I am not one of the robots you're looking for

0 Likes
Message 8 of 15

Anonymous
Not applicable

@dlanorh wrote:
Having re-read you initial post my above post may be wrong if you are trying to alter the text string, so
are you trying to access the Attribute TAG, or the Attribute text string?

The Attribute text string.

0 Likes
Message 9 of 15

cadffm
Consultant
Consultant
Accepted solution

 

 

@Anonymous i can only write about plain AutoCAD:

 

You posted a DWG which contain dynamic parameters,

so that is a dwg to use 'as Block'(-definition)

 

If you want to edit the block(definition) = You want to edit this uploaded file

then you have to select attributdefinitions (ssget "_X" '((ATTDEF)))

 

If you want to edit blockreferences of this block (in another file, where you insert that file "as Block")

then you are right to search for inserts and looking for attributes, BUT* see below

 

If you want to edit the block(definition) in another file (where you insert that file "as Block")

then you have to go to the block (tblobjname "BLOCK" "Rogers CC") - *I don't write about anonyme block clones*

 

WHY DOES IT NOT WORK?

Because blockreferences of this block doesn't have an attribut with a tag named "ADSKFACTORY:Custom.ASSET_TAG"

(when the attributes are synchron to this blockdefinition)

 

 

Thats the Attribut(tag)list which new inserts of this block would have:

EXISTENTE
PROJETADO
NUMERO
TAM_RESIS
ID_POSTE

 

Your Code works! f the selected blockreference have a Attribut with tag "ADSKFACTORY:Custom.ASSET_TAG"

 

Sebastian

Message 10 of 15

dlanorh
Advisor
Advisor

Then ignore my above.

 

If you only want to change one entity in one block i suggest using (nentsel) to directly select the entity

(while (setq ent (car (nentsel "\nSelect Attribute : ")))
  (setq ents (entget ent))
.....
);end_while

will get the entity data of the attribute direct instead of looping through all the entities

I am not one of the robots you're looking for

Message 11 of 15

Moshe-A
Mentor
Mentor
Accepted solution

here you are budy, it's now working

i choose the NUMERO attribute instead of what you 'want'?

you can change it to what you like

 

 

(defun c:test (/ pre post i j ss1 dat ent etdata found)
 (if (and
       (/= (setq pre (getstring "\nPrefix: ")) "")
       (not (initget (+ 2 4)))
       (setq post (getint "\nSufix: "))
     )
  (progn
   (setq j 0) 
   (while (setq ss1 (ssget '((0 . "insert") (2 . "rogers cc") (66 . 1))))
    (setq i -1)
    (repeat (sslength ss1) 
     (setq i (1+ i))
     (setq dat (strcat pre (itoa (+ post j)))
	   ent (ssname ss1 i) j (1+ j) found nil)
      
     (while (and (setq ent (entnext ent)) (not found))
      (setq etdata (entget ent))
      (if (and
	   (eq (cdr (assoc 0 etdata)) "ATTRIB")
	   (eq (strcase (cdr (assoc 2 etdata))) "NUMERO")
	  )
       (progn
        (entmod (subst (cons 1 dat) (assoc 1 etdata) etdata))
        (entupd ent)
        (setq found t)
       ); progn
      ); if
     ); inner while
    ); repeat
   ); outer while
  ); progn
 ); if

 (princ)
); c:test
Message 12 of 15

Anonymous
Not applicable

@cadffm  Thanks for noticing !!!
was picking up the wrong entity.

0 Likes
Message 13 of 15

Anonymous
Not applicable

Thank you @Moshe-A

It works perfectly!!!

 

@dlanorh @dlanorh @ВeekeeCZ   Thank you all, you guys are the best !!!    Heart

0 Likes
Message 14 of 15

ВeekeeCZ
Consultant
Consultant

@Moshe-A wrote:

 

... the ":s" argument will let the user to select only one time. that means he can choose to select by pick or any other windows or crossing but only once and if he misses? it is true it is in a while loop but it is better to let the user to select objects as much as he wants and after that to iterate the selection set. ...

Using the ":s" argument has definitely its point! You can avoid noted issue of missed pick quite easily... And the rest you're saying still applies, the user can select as much objects as he wants...

 

@Anonymous

Made some other improvements as well at the code... (allowing no prefix, start with 0...)

 

(defun c:test (/ pre n i ss1 ent etd)
  
  (setq pre (getstring "\nPrefix: "))
  (initget 4)
  (setq n (1- (cond ((getint "\nInitial number <1>: "))
		    (1))))
  
  (while (progn
	   (setvar 'ERRNO 0)
	   (setq ss1 (ssget "_:S" '((0 . "INSERT") (2 . "Rogers CC") (66 . 1))))
	   (/= (getvar 'ERRNO) 52)
	   )
    (if ss1
      (repeat (setq i (sslength ss1))
	(setq ent (ssname ss1 (setq i (1- i))))
	(while (and (setq ent (entnext ent))
		    (setq etd (entget ent))
		    (= (cdr (assoc 0 etd)) "ATTRIB")
		    )
	  (and (= (strcase (cdr (assoc 2 etd))) "NUMERO")
	       (entmod (subst (cons 1 (strcat pre (itoa (setq n (1+ n)))))
			      (assoc 1 etd)
			      etd))
	       (entupd ent)
	       )))))
  (princ)
  )
0 Likes
Message 15 of 15

ВeekeeCZ
Consultant
Consultant

@ВeekeeCZ wrote:

@Moshe-A wrote:

 

... the ":s" argument will let the user to select only one time. that means he can choose to select by pick or any other windows or crossing but only once and if he misses? it is true it is in a while loop but it is better to let the user to select objects as much as he wants and after that to iterate the selection set. ...

Using the ":s" argument has definitely its point! You can avoid noted issue of missed pick quite easily... And the rest you're saying still applies, the user can select as much objects as he wants...

 

@Anonymous

Made some other improvements as well at the code... (allowing no prefix, start with 0...)

 

(defun c:test (/ pre n i ss1 ent etd)
  
  (setq pre (getstring "\nPrefix: "))
  (initget 4)
  (setq n (1- (cond ((getint "\nInitial number <1>: "))
		    (1))))
  
  (while (progn
	   (setvar 'ERRNO 0)
	   (setq ss1 (ssget "_:S" '((0 . "INSERT") (2 . "Rogers CC") (66 . 1))))
	   (/= (getvar 'ERRNO) 52)
	   )
    (if ss1
      (repeat (setq i (sslength ss1))
	(setq ent (ssname ss1 (setq i (1- i))))
	(while (and (setq ent (entnext ent))
		    (setq etd (entget ent))
		    (= (cdr (assoc 0 etd)) "ATTRIB")
		    )
	  (and (= (strcase (cdr (assoc 2 etd))) "NUMERO")
	       (entmod (subst (cons 1 (strcat pre (itoa (setq n (1+ n)))))
			      (assoc 1 etd)
			      etd))
	       (entupd ent)
	       )))))
  (princ)
  )

One more thing, probably mentioned before, your block is a Dynamic Block. We cannot use a block name filter for the ssget function, because if you change any of dynamic features the block become a clone with its anonymous name.

 

Just remove that - it remains filtering by ATT name "NUMERO", which should be fine.

Or if you want to learn some, then search for how to filter blocks by An Effective name.

 

The noted above applies on @Moshe-A's solution as well, because I've just modified his version and did not see that.

 

0 Likes