View Full Version : Redefine selected block with attributes
jpaulsen
2007-10-10, 01:06 AM
I just wrote this routine to update selected titleblocks in a drawing. It is working fine but I have a question.
I was having trouble but once I added the line (setq vss (entget vss)) it started working. What does that line do?
It would be generous to call me a novice lisp programmer (this took me 4 hours :)) so I am open to any comments/suggestions on the code.
(defun titleblockupdate ( / sync tbname ntbname)
(setq vss (car (entsel "\nSelect Titleblock to Update: ")))
(setq vss (entget vss))
(setq tbname (cdr (assoc 2 vss)))
(setq sync (getstring "\nUpdate attributes [Yes/No] <Y>: "))
(if (findfile (setq ntbname (strcat "Z:/Autodesk 2008/JRSym/TitleBlocks/"tbname".dwg")))
(progn
(command "-insert" (strcat tbname"="ntbname) "y")
(command)
(princ (strcat "\n"tbname" redefined."))
)
(princ (strcat "\nCould not find "ntbname))
)
(if (or (= (substr sync 1 1) "Y") (= (substr sync 1 1) "y") (= sync ""))
(progn
(command "attsync" "n" tbname)
)
)
(princ)
)
(defun c:titleblockupdate () (titleblockupdate))
(defun c:tbud () (titleblockupdate))
T.Willey
2007-10-10, 01:27 AM
If you don't know you should look into the help, but here is a quick run down of the beginning of your code.
entsel = lets you select an entity, and returns a list in the fashion of the ename and the a point near or on the object selected.
So (car (entsel)) assigns one of your variables to the ename of the object selected.
Then you want the block name, but you have to get the dxf code about the object selected, so that is why you have to use 'entget'.
entget = gets the dxf information about an ename. This lists lots of important items (see help for specifics), but you are only concerned about the name of the block, that is why you use
(cdr (assoc 2 (entget (car (entsel)))))
Hope that makes sense.
Mike_R
2007-10-10, 03:39 PM
I am open to any comments/suggestions on the code.
I see 2 places where it could use some improvement...
1) You can use a single setq function to set multiple variables, the format is
(setq var1 value1
var2 value2
var3 value3
)
and so on.
2) Using initget allows you to set keywords and other parameters for the next get**** function, so you won't have to check so deeply to see if the user entered the proper data. For your code, getkword will probably work best. Using initget, you can disallow a response of <enter>, but in this code we won't... I just hate doing it. We'll default to "Yes" instead.
Here's a quick revision of your code...
(defun titleblockupdate ( / sync tbname ntbname)
(setq vss (entget (car (entsel "\nSelect Titleblock to Update: ")))
tbname (cdr (assoc 2 vss))
)
(initget "Yes No")
(setq sync (getkword "\nUpdate attributes [Yes/No] <Y>: "))
(if (findfile (setq ntbname (strcat "Z:/Autodesk 2008/JRSym/TitleBlocks/"tbname".dwg")))
(progn
(command "-insert" (strcat tbname"="ntbname) "y")
(command)
(princ (strcat "\n"tbname" redefined."))
)
(princ (strcat "\nCould not find "ntbname))
)
(if (or (= sync "Yes") (= sync nil))
(progn
(command "attsync" "n" tbname)
)
)
(princ)
)
(defun c:titleblockupdate () (titleblockupdate))
(defun c:tbud () (titleblockupdate))
That's the major stuff I see. The rest are trivial.
jpaulsen
2007-10-10, 05:07 PM
Thanks for the replies.
Tim,
I was refering to the developer help as I wrote this program (hence the 4 hours :)). I was just having a hard time figuring out some of it. Your explaination helped me to understand what enget does and why that line was needed. Thank you.
Mike,
Thanks for the tips. I probablly won't use a single setq in this code but I will keep it in mind for future projects. I will try the initget. I was actually trying to figure out how do that. With my current code a user could have typed F or any character and it would be treated as a Yes.
T.Willey
2007-10-10, 05:12 PM
I'm glad I could help then Jeff. Sorry if I can off bad, it's just some people post questions without doing the research.
Mike_R
2007-10-10, 05:42 PM
Glad to help Jeff. Just remember, if you ever have trouble with something, don't hesitate to ask. Simple or complicated, there's bound to be somebody who has the time and knowledge to answer it for you.
Good luck! You'll be a novice before you know it. ;)
jpaulsen
2007-10-10, 06:01 PM
No worries Tim. I didn't take an offense.
jpaulsen
2007-10-12, 10:22 PM
Thanks for all the help.
Here is my final code. I added functionality to updated a nested logo block too.
(defun updatetitleblock ( / vss tbname sync ntbname BlkEnt EntData lgname)
(setq vss (car (entsel "\nSelect Titleblock to Update: ")))
(setq tbname (cdr (assoc 2 (entget vss))))
(if (findfile (setq ntbname (strcat "Z:/Autodesk 2008/JRSym/TitleBlocks/"tbname".dwg")))
(progn
(command "-insert" (strcat tbname"="ntbname) "y")
(command)
(initget "Yes No")
(setq sync (getkword "\nUpdate attributes [Yes/No] <Y>: "))
(princ (strcat "\n"tbname" redefined."))
)
(princ (strcat "\nCould not find "ntbname))
)
(setq BlkEnt (tblobjname "block" tbname)) ; get titleblock block definition ename
(while (setq BlkEnt (entnext BlkEnt)) ; this will step through all the entities within the block
(setq EntData (entget BlkEnt)) ; get the dxf list of the entity
(if
(and
(= (cdr (assoc 0 EntData)) "INSERT") ; make sure it is a block
(wcmatch (strcase (cdr (assoc 2 EntData))) "LOGO*") ; make sure the block name starts with LOGO
)
(progn
(setq lgname (cdr (assoc 2 EntData)))
(command "-insert" (strcat lgname"=Z:/Autodesk 2008/JRSym/Logos/JRLogos/"lgname) "y")
(command)
(princ (strcat " "lgname" redefined."))
)
)
)
(if (or (= (substr sync 1 1) "Y") (= (substr sync 1 1) "y") (= sync ""))
(progn
(command "attsync" "n" tbname)
)
)
(princ)
)
(defun c:updatetitleblock () (updatetitleblock))
(defun c:udtb () (updatetitleblock))
vBulletin® v3.6.7, Copyright ©2000-2010, Jelsoft Enterprises Ltd.