frostrap Posted February 8, 2008 Posted February 8, 2008 Hello all, I need a program that I'm writing to change a text value in a block automatically without having the user pick the block. The program will also need to later retreive data directly from that block attribute. In another program I wrote, I managed to figure out how to get lisp change text in a block if a user selects the block, but I don't quite know how to tell lisp which block, and attribute within that block, to change without having the user make the selection. This program will always modify the same block, and there is only one of this particular block in the entire drawing. Getting lisp to modify block information is a pain in the neck... can any of you help me in the right direction? Thanks, Joe Quote
CarlB Posted February 8, 2008 Posted February 8, 2008 (setq SelSet (ssget "x" '((0 . "INSERT")(2 . "THEBLOCKNAME")))) (setq EntName (ssname SelSet 0)) OK now you have the block insert to manipulate. You can step through attributes with 'entnext' Quote
frostrap Posted February 8, 2008 Author Posted February 8, 2008 I'm not totally clear on what's going on in the code you've suggested... I know I probably sound like a total noob, but could you give me a little more detail? Thanks, joe Quote
wizman Posted February 9, 2008 Posted February 9, 2008 hi frostrap, carlb suggested the use of ssget function, have a look at it at the command reference help, it's one way for you to bypass a user input. in the example he has given, if you included that in your code, it will be selecting all the block entities with that blockname. may be you need to post a sample of your lisp routine so the guys here can guide you more clearly. Quote
ASMI Posted February 9, 2008 Posted February 9, 2008 Something like this function: (defun Change_Attribute(Block Tag Value) (vl-load-com) (if (setq blSet(ssget "_X" (list '(0 . "INSERT")(cons 2 Block)))) (progn (foreach bl (mapcar 'vlax-ename->vla-object (vl-remove-if 'listp (mapcar 'cadr(ssnamex blSet)))) (setq atLst(vlax-safearray->list (vlax-variant-value (vla-GetAttributes bl)))) (foreach at atLst (if (=(vla-get-TagString at)(strcase Tag)) (if(vl-catch-all-error-p (vl-catch-all-apply 'vla-put-TextString (list at Value))) nil ); end if ); end if ); end foreach ); end foreach ); end progn ); end if (princ) ); end of Change_Attribute Test with block "My_Block" and attribute "My_Tag": (Change_Attribute "My_Block" "My_Tag" "It's new attribute value") Quote
JeepMaster Posted August 11, 2008 Posted August 11, 2008 Something like this function: (defun Change_Attribute(Block Tag Value) (vl-load-com) (if (setq blSet(ssget "_X" (list '(0 . "INSERT")(cons 2 Block)))) (progn (foreach bl (mapcar 'vlax-ename->vla-object (vl-remove-if 'listp (mapcar 'cadr(ssnamex blSet)))) (setq atLst(vlax-safearray->list (vlax-variant-value (vla-GetAttributes bl)))) (foreach at atLst (if (=(vla-get-TagString at)(strcase Tag)) (if(vl-catch-all-error-p (vl-catch-all-apply 'vla-put-TextString (list at Value))) nil ); end if ); end if ); end foreach ); end foreach ); end progn ); end if (princ) ); end of Change_Attribute Test with block "My_Block" and attribute "My_Tag": (Change_Attribute "My_Block" "My_Tag" "It's new attribute value") ASMI, Is it possible to modify this lisp so it will select all the "fixture tag" blocks with an attribute = A10, and change it to attribute = A11. What I'm trying to do is modify a existing fixture tag so all the A10 tags are change to A11.:wink: Quote
BIGAL Posted August 11, 2008 Posted August 11, 2008 Search here I under VBA I think I posted the code to do what you want can be run form a menu toolbar etc. Quote
BIGAL Posted August 13, 2008 Posted August 13, 2008 Use "Search" this forum for "attribute update" or block update there is numerous responses and answers here already for your question. I try to always search first as the answer is already there. Quote
JeepMaster Posted August 14, 2008 Posted August 14, 2008 For the life of me I cannot figure out how to use the VBA code posted here. Searching only finds VBA codes. Does anyone have a lisp that can replace existing block attributes with a new value. Quote
Terry Cadd Posted August 15, 2008 Posted August 15, 2008 In the attached BlkAttrib.lsp there are three functions that may help you out. GetBlkAttrib, PutBlkAttrib and the ChangeAll function which I also pasted below. Both GetBlkAttrib and PutBlkAttrib use an argument named BlkOrEntity which can be either the Block or entity name. Which ever is easier for you to work with. I also added the ChangeAll function for you to revise as needed. If you don't know the attribute TagName you can explode the block and then do an undo, and note the TagName for reference. There may other methods of doing this but it works for me. Terry ; c:ChangeAll - Revise this function as needed. ; Note: Replace "[color=red]BlockName[/color]" with your block name, replace "[color=red]TagName[/color]" with your ; tag name, and replace "[color=red]Find[/color]" and "[color=red]Replace[/color]" with your attribute values. (defun c:ChangeAll (/ Cnt# Ctab$ EntName^ Layout$ SS&) (setq Ctab$ (getvar "CTAB")) (foreach Layout$ (cons "Model" (layoutlist)) (command "_LAYOUT" "_S" Layout$) (setq SS& (ssget "x" (list '(-4 . "<AND")'(2 . "[color=red]BlockName[/color]") (cons 410 (getvar "CTAB"))'(-4 . "AND>"))) );setq (if SS& (progn (setq Cnt# 0) (repeat (sslength SS&) (setq EntName^ (ssname SS& Cnt#)) (if (= (GetBlkAttrib EntName^ "[color=red]TagName[/color]") "[color=red]Find[/color]") (PutBlkAttrib EntName^ "[color=red]TagName[/color]" "[color=red]Replace[/color]") );if (setq Cnt# (1+ Cnt#)) );repeat );progn );if );foreach (setvar "CTAB" Ctab$) (princ) );defun c:ChangeAll BlkAttrib.lsp Quote
JeepMaster Posted August 15, 2008 Posted August 15, 2008 Thanks TerryCadd, That's what I was looking for, but it seems like it only works for normal blocks. Is it possible to make it work for dynamic blocks? Quote
Terry Cadd Posted August 15, 2008 Posted August 15, 2008 JeepMaster, I didn't know that about the dynamic blocks. What I just found out is that when you create a dynamic block the top level dxf entity list is referring to the block by it's new Anonymous Name, i.e. "*U25" and not by it's original Block Name, i.e. "TestBlock". But there's still hope! I ran a little function that looks deeper into the nesting of the top level dxf entity list, and I found all the information needed for the attributes. It just wasn't in the regular place. Terry Quote
JeepMaster Posted August 19, 2008 Posted August 19, 2008 JeepMaster,I didn't know that about the dynamic blocks. What I just found out is that when you create a dynamic block the top level dxf entity list is referring to the block by it's new Anonymous Name, i.e. "*U25" and not by it's original Block Name, i.e. "TestBlock". But there's still hope! I ran a little function that looks deeper into the nesting of the top level dxf entity list, and I found all the information needed for the attributes. It just wasn't in the regular place. Terry So is it possible to make it work with dynamic blocks, or is it too much work? This lisp is out of my league, so I have no idea how to modify it to make it work for dynamic blocks. Please help. Quote
ASMI Posted August 19, 2008 Posted August 19, 2008 Works with dynamic blocks. (defun c:chatt(/ cAtt cBl cTag efNm sStr nLst fSet oVal fLst fStr actDoc atLst cFrom cTo mCnt sucCnt errCnt) (vl-load-com) (if (and (setq cAtt(nentsel "\nPick sample attribute > ")) (= "ATTRIB"(cdr(assoc 0(entget(car cAtt))))) ); end and (progn (setq actDoc(vla-get-ActiveDocument (vlax-get-acad-object)) cBl(vla-ObjectIDtoObject actDoc (vla-get-OwnerID (setq cAtt (vlax-ename->vla-object(car cAtt))))) cTag(vla-get-TagString cAtt) mCnt 0 sucCnt 0 errCnt 0 ); end setq (if(vlax-property-available-p cBl 'EffectiveName) (progn (setq fStr(vla-get-EffectiveName cBl) nLst(mapcar 'vla-get-Name (vl-remove-if-not (function(lambda(x) (equal fStr(vla-get-EffectiveName x)))) (mapcar 'vlax-ename->vla-object (vl-remove-if 'listp (mapcar 'cadr(ssnamex (ssget "_X" '((0 . "INSERT") (66 . 1)(2 . "`*U*,"))))))))) ); end setq (foreach n nLst (setq fStr(strcat "`" n "*," fStr)) ); end foreach (setq fLst(list '(0 . "INSERT")(cons 2 fStr))) ); end progn (setq fLst(list '(0 . "INSERT")(cons 2(vla-getName cBl)))) ); end if (princ "\n<<< Select blocks >>> ") (if(setq fSet(ssget fLst)) (progn (princ(strcat "\n" (itoa(sslength fSet)) " block(s) found. ")) (setq cFrom(getstring T (strcat "\nChange from <" (setq oVal(vla-get-TextString cAtt)) ">: "))) (if(= "" cFrom)(setq cFrom oVal)) (if (and (setq cTo(getstring T "\nChange to: ")) (/= "" cTo) ); end and (progn (vla-StartUndoMark actDoc) (foreach b(mapcar 'vlax-ename->vla-object (vl-remove-if 'listp (mapcar 'cadr(ssnamex fSet)))) (setq atLst(vlax-safearray->list (vlax-variant-value (vla-GetAttributes b)))) (foreach at atLst (if(and (equal(vla-get-TagString at)cTag) (equal(vla-get-TextString at)cFrom) ); end and (progn (setq mCnt(1+ mCnt)) (if(vl-catch-all-error-p (vl-catch-all-apply 'vla-put-TextString (list at cTo))) (setq errCnt(1+ errCnt)) (setq sucCnt(1+ sucCnt)) ); end if ); end progn ); end if ); end foreach ); end foreach (princ(strcat "\n" (itoa sucCnt) " of " (itoa mCnt) " attributes chanded. ")) (if(/= 0 errCnt) (princ(strcat(itoa errCnt) " were on locked layer! ")) ); end if (vla-EndUndoMark actDoc) ); end progn ); end if ); end progn ); end if ); end progn (princ "\n<!> It isn't attribute <!> ") ); end if (princ) ); end of c:chatt Quote
JeepMaster Posted August 19, 2008 Posted August 19, 2008 Works with dynamic blocks. (defun c:chatt(/ cAtt cBl cTag efNm sStr nLst fSet oVal fLst fStr actDoc atLst cFrom cTo mCnt sucCnt errCnt) (vl-load-com) (if (and (setq cAtt(nentsel "\nPick sample attribute > ")) (= "ATTRIB"(cdr(assoc 0(entget(car cAtt))))) ); end and (progn (setq actDoc(vla-get-ActiveDocument (vlax-get-acad-object)) cBl(vla-ObjectIDtoObject actDoc (vla-get-OwnerID (setq cAtt (vlax-ename->vla-object(car cAtt))))) cTag(vla-get-TagString cAtt) mCnt 0 sucCnt 0 errCnt 0 ); end setq (if(vlax-property-available-p cBl 'EffectiveName) (progn (setq fStr(vla-get-EffectiveName cBl) nLst(mapcar 'vla-get-Name (vl-remove-if-not (function(lambda(x) (equal fStr(vla-get-EffectiveName x)))) (mapcar 'vlax-ename->vla-object (vl-remove-if 'listp (mapcar 'cadr(ssnamex (ssget "_X" '((0 . "INSERT") (66 . 1)(2 . "`*U*,"))))))))) ); end setq (foreach n nLst (setq fStr(strcat "`" n "*," fStr)) ); end foreach (setq fLst(list '(0 . "INSERT")(cons 2 fStr))) ); end progn (setq fLst(list '(0 . "INSERT")(cons 2(vla-getName cBl)))) ); end if (princ "\n<<< Select blocks >>> ") (if(setq fSet(ssget fLst)) (progn (princ(strcat "\n" (itoa(sslength fSet)) " block(s) found. ")) (setq cFrom(getstring T (strcat "\nChange from <" (setq oVal(vla-get-TextString cAtt)) ">: "))) (if(= "" cFrom)(setq cFrom oVal)) (if (and (setq cTo(getstring T "\nChange to: ")) (/= "" cTo) ); end and (progn (vla-StartUndoMark actDoc) (foreach b(mapcar 'vlax-ename->vla-object (vl-remove-if 'listp (mapcar 'cadr(ssnamex fSet)))) (setq atLst(vlax-safearray->list (vlax-variant-value (vla-GetAttributes b)))) (foreach at atLst (if(and (equal(vla-get-TagString at)cTag) (equal(vla-get-TextString at)cFrom) ); end and (progn (setq mCnt(1+ mCnt)) (if(vl-catch-all-error-p (vl-catch-all-apply 'vla-put-TextString (list at cTo))) (setq errCnt(1+ errCnt)) (setq sucCnt(1+ sucCnt)) ); end if ); end progn ); end if ); end foreach ); end foreach (princ(strcat "\n" (itoa sucCnt) " of " (itoa mCnt) " attributes chanded. ")) (if(/= 0 errCnt) (princ(strcat(itoa errCnt) " were on locked layer! ")) ); end if (vla-EndUndoMark actDoc) ); end progn ); end if ); end progn ); end if ); end progn (princ "\n<!> It isn't attribute <!> ") ); end if (princ) ); end of c:chatt THANK YOU ASMI again! It works great! How come you didn't put it in your website? This will save me so much time. Quote
ASMI Posted August 19, 2008 Posted August 19, 2008 How come you didn't put it in your website? This is fresh, created today. Thank you for kind words. Quote
JeepMaster Posted August 19, 2008 Posted August 19, 2008 This is fresh, created today. Thank you for kind words. In that case, thanks for creating the lisp for me. You've helped me so much in the pass, if you put a "donation" link on your site, I will donate. Seriouly, for the work that you do for others here(for free), you deserve some credit. Quote
ASMI Posted August 20, 2008 Posted August 20, 2008 > JeepMaster In that case, thanks for creating the lisp for me. I have written it because for me interestingly to solve this problem for dynamic blocks. It as solving of puzzles. You've helped me so much in the pass, if you put a "donation" link on your site, I will donate. Seriouly, for the work that you do for others here(for free), you deserve some credit. The page "Donate" exists, but probably the link to it is hardly noticeable (after each code). Now I have taken out it in the main menu. It is certanly not a way of earnings, but these some dollars can be estimated as an attention sign. Just as on incomes of clicks under advertisements it is possible to buy once a month ice-cream or a beer bottle. But to look that you has earned whole $ 2.50 for this month why that very pleasantly There is more advanced version of CHATT.LSP, it highlights blocks with the necessary values of attributes: http://www.asmitools.com/Files/Lisps/Chatt.html Quote
JeepMaster Posted August 20, 2008 Posted August 20, 2008 > There is more advanced version of CHATT.LSP, it highlights blocks with the necessary values of attributes: http://www.asmitools.com/Files/Lisps/Chatt.html This lisp works even better. Thanks. I've made a donation to your site. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.