Jump to content

AutoLisp routine that finds correct Attributes to replace by matching values


Da Ballz

Recommended Posts

I'm new to AutoLisp, so any help is greatly appreciated.

 

I have hundreds of drawings with two different title blocks:

A) Drawing_Sheet_22X34

B) Drawing_Sheet_22X34-H

The attributes (tags, prompts, values) are set up the same. The only difference is that one is a vertical arrangement and the other horizontal.

 

I need to iterate through all of the drawings (no command prompts), find the title block, and replace certain attribute values (for the revisions attributes) with the following:

 

A) DATE* "29-JUN-15"

The DATE* is one of the DATE attributes in the revision area of the title block. The * represents a number, so it could be DATE1, DATE2, DATE3, DATE4, ect. The key is finding the right one to replace.

 

B) DESC* "BASELINE UPDATE - 101/111 RENOVATIONS"

Same as with DATE*, the DESC* is DESC1, DESC2, ect.

 

REV1, DATE1 and DESC1 represent part of one revision (REV2, DATE2 and DESC2 the second revision, ect), I need to find DATE* and DESC* and replace both values with the values above.

 

There is also a lone REV Attribute in the bottom corner of the title block. In order to find the correct DATE* and DESC* pair to modify, the REV* attribute value must be found and matched with the REV attribute value. That's the only way the routine will be able to find the correct revision attributes to modify, but the overall REV attribute value for the title block which should match one of the REV* attribute values.

 

For example REV2 has the value 26 (Revision 26). The REV attribute in the bottom corner also has the value 26, therefore REV2 is the revision where DATE2 and DESC2 values will need to be replaced with the values stated above.

 

Does that make sense? Any code will be greatly appreciated.

 

Title blocks are attached.

Link to comment
Share on other sites

  • Replies 26
  • Created
  • Last Reply

Top Posters In This Topic

  • Da Ballz

    14

  • pBe

    6

  • Commandobill

    3

  • Dadgad

    2

I forgot to mention. The drawings I attached are "empty". There aren't any values for the revision information. So to test the code, some values will have to be added.The horizontal border can hold 4 revisions, and I believe the vertical border can hold 6 revisions.

Link to comment
Share on other sites

Dadgad, thank you. It's great to be here.

 

That is an excellent lisp. However, it assumes I know where the find and replace will occur, and that it will be the same in every instance.

 

In my case, the lisp routine must first determine which revision to alter, because it be different for every drawing. So I need an additional piece that identifies which attributes to find replace.

 

In other words, it needs to determine the most recent revision. So first it must read the value of REV and then find the REV* that has the same value. Let's say REV has a value of 23, REV2 also has a value of 23. Therefore DATE2 and DESC2 are the attributes that need to be updated. Or if REV had a value of 89 and REV6 had a value of 89, it would be attributes DATE6 and DESC6 that needed to be updated. Every drawing varies, that's why I need something to match REV with REV* (again, REV* being attribute REV1, or REV2, or REV3, ect, whichever one has the same value as REV).

Link to comment
Share on other sites

Sounds like you will need something written then.

I hope you have bookmarked Lee's website, as there are tons of very useful lisps there, a few of which deal with attribute syncing, but probably not what you will need in this case.

Link to comment
Share on other sites

Ok the answer is here but I dont have it bookmarked and replacing a blocks attribute is pretty easy, I know that I have posted comments about searching through revision blocks and look for a blank entry and add to next entry. Search here using "REVISION". There is a method of looking at a block attributes by there position, say you have as suggested a 3x4 attribute block you can look at value 1 5 & 9 etc. I know I have code somewhere.

 

But others jump in.

Link to comment
Share on other sites

......In my case, the lisp routine must first determine which revision to alter, because it be different for every drawing. So I need an additional piece that identifies which attributes to find replace.

 

 

Easy, Here's a question, What will take precedence? REV* or REV value? what if the REV value is 23 and REV2 is 24 and REV1 is 23, what then? Change REV value to 24 and update DATE2 and DESC2? or delete REV2 and update DATE1 and DESC1?

Link to comment
Share on other sites

Someone can feel free to clean up the main function, I wasn't sure if you had multiple layouts, but I had all the sub functions written, so...

 

(defun c:test11 ( / )
 (if
   (setq blockSS (ssget "X" (list (cons 0 "INSERT") (cons 2 "Drawing_Sheet_22x34"))))
   (progn
     (setq blockList (mapcar 'cadr (ssnamex blockSS)))
     (setq attName (vla-get-tagstring (car (cb:matchAtts "REV" "REV" (vlax-ename->vla-object(car blockList))))))
     (setq attNumber (substr attName (strlen attName) 1))
   (cb:replaceAttributeValue (strcat "DATE" attNumber) "29-JUN-15" (vlax-ename->vla-object(car blockList)))
   (cb:replaceAttributeValue (strcat "DESC" attNumber) "BASELINE UPDATE - 101/111 RENOVATIONS" (vlax-ename->vla-object(car blockList))))
   )
 
 )

(defun cb:matchAtts (baseAttName attPrefix Blk / )
 (setq baseAtt (car (vl-remove-if-not '(lambda (x) (= baseAttName (vla-get-tagstring x))) (cb:variantToList (vla-getattributes Blk)))))
 (vl-remove-if-not '(lambda (x)
	       (and
		 (wcmatch (vla-get-tagstring x) (strcat attPrefix "*"))
		 (not (eq (vla-get-tagstring x) baseAttName))
		 (eq (vla-get-textstring x) (vla-get-textstring baseAtt))
		 ))
   (cb:variantToList (vla-getattributes Blk)))
 )

(defun cb:variantToList (theVariant / )
 (if (= 'variant (type theVariant))
 (vlax-safearray->list (vlax-variant-value theVariant))
   nil
   )
 )

;;;;;Replace Attribute Value;;;;;;;;;
;;;;;By: CommandoBill;;;;;;;;;;;;;;;;;
;;;;;01/24/15;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;Send a block to this function with an attribute you want to replace with a new value
;;;;attName = the name of the attribute which value you want to replace
;;;;attNewVal = the new value you want in the attribute
;;;;Blk = the vla-object verision of the block which the attribute is in

(defun cb:replaceAttributeValue (attName attNewVal Blk / )
 (mapcar '(lambda (x) (if (= attName (vla-get-tagstring x))
		 (vla-put-textstring x attNewVal))) (cb:variantToList (vla-getattributes Blk)))
 (princ)
     )

Link to comment
Share on other sites

REV takes precedence since it will always have the value of the REV* which will be the DATE*, and DESC* that I'm trying to modify. Nothing will be deleted. There may be attributes with empty values. For example: REV is 23 and REV2 is 23 (so I will only be updated DATE2 and DESC2 out of all the attributes), but REV4 is empty (it's not being used yet, the revisions haven't gone that high). The difficulty is in the positioning. The REV* I'm looking for will always be the latest revision of the drawing, hence it will always match REV. But it could be anyone of the REV* attributes depending on how many revisions are in the title block.

Link to comment
Share on other sites

Commandobill, thank you! This code looks like it's getting closer to what I'm looking for.

 

Forgive my ignorance here, but when I load this routine I get the following:

 

Command: (LOAD ".//") CB:REPLACEATTRIBUTEVALUE

 

How do I initialize the main function? I type test11, but it isn't recognized.

 

Also, does there need to be a vl-load-com in there somewhere? Forgive my ignorance, I am still in the beginner stages.

Link to comment
Share on other sites

Guys, mostly good news! Commandobill, your code works good!

 

However, I forgot to mention, I have 3 title blocks, not two (sorry). Once blockSS is set, it retains the title block it found in the first drawing. So if the first drawing had "Drawing_Sheet_22x34", it will only update drawings with that title block when I run this as a batch process (script mode). But if I drag/drop the lisp into individual drawings, it fixes all of them, regardless of the title block.

 

I added (ssdel ent blockSS) at the end of the if statement, no effect on drag and drop, but stopped the lisp from working in multibatch.

 

There must be a variable issue. How do I reset the variables so that on the next drawing it starts over with blockSS and finds whichever titleblock is in the drawing?

Link to comment
Share on other sites

Still not my best work as far as the main function goes, but gets the job done.

(vl-load-com)
(defun c:test11 ( / blockSS blockList attName attNumber)
 (if
   (setq blockSS (ssget "X" (list (cons 0 "INSERT") (cons -4 "<xor") (cons 2 "Drawing_Sheet_22x34") (cons 2 "Drawing_Sheet_22x34-H") (cons -4 "xor>"))))
   (progn
     (setq blockList (mapcar 'cadr (ssnamex blockSS)))
     (setq attName (vla-get-tagstring (car (cb:matchAtts "REV" "REV" (vlax-ename->vla-object(car blockList))))))
     (setq attNumber (substr attName (strlen attName) 1))
     (mapcar '(lambda (x)
   (cb:replaceAttributeValue (strcat "DATE" attNumber) "29-JUN-15" (vlax-ename->vla-object x))
   (cb:replaceAttributeValue (strcat "DESC" attNumber) "BASELINE UPDATE - 101/111 RENOVATIONS" (vlax-ename->vla-object x)))
      blockList)
   ))
 (princ)
 
 )

(defun cb:matchAtts (baseAttName attPrefix Blk / )
 (setq baseAtt (car (vl-remove-if-not '(lambda (x) (= baseAttName (vla-get-tagstring x))) (cb:variantToList (vla-getattributes Blk)))))
 (vl-remove-if-not '(lambda (x)
	       (and
		 (wcmatch (vla-get-tagstring x) (strcat attPrefix "*"))
		 (not (eq (vla-get-tagstring x) baseAttName))
		 (eq (vla-get-textstring x) (vla-get-textstring baseAtt))
		 ))
   (cb:variantToList (vla-getattributes Blk)))
 )

(defun cb:variantToList (theVariant / )
 (if (= 'variant (type theVariant))
 (vlax-safearray->list (vlax-variant-value theVariant))
   nil
   )
 )

;;;;;Replace Attribute Value;;;;;;;;;
;;;;;By: CommandoBill;;;;;;;;;;;;;;;;;
;;;;;01/24/15;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;Send a block to this function with an attribute you want to replace with a new value
;;;;attName = the name of the attribute which value you want to replace
;;;;attNewVal = the new value you want in the attribute
;;;;Blk = the vla-object verision of the block which the attribute is in

(defun cb:replaceAttributeValue (attName attNewVal Blk / )
 (mapcar '(lambda (x) (if (= attName (vla-get-tagstring x))
		 (vla-put-textstring x attNewVal))) (cb:variantToList (vla-getattributes Blk)))
 (princ)
     )

Link to comment
Share on other sites

Guys, mostly good news! Commandobill, your code works good!

 

However, I forgot to mention, I have 3 title blocks, not two (sorry). Once blockSS is set, it retains the title block it found in the first drawing. So if the first drawing had "Drawing_Sheet_22x34", it will only update drawings with that title block when I run this as a batch process (script mode). But if I drag/drop the lisp into individual drawings, it fixes all of them, regardless of the title block.

 

I added (ssdel ent blockSS) at the end of the if statement, no effect on drag and drop, but stopped the lisp from working in multibatch.

 

There must be a variable issue. How do I reset the variables so that on the next drawing it starts over with blockSS and finds whichever titleblock is in the drawing?

 

What I just posted should work for all title blocks in your drawing.

Link to comment
Share on other sites

...it's not being used yet, the revisions haven't gone that high

 

And if it does gone that high and the REV boxes are maxed out, Is the last REV* always the lasts one? and if it does not match? Does it "bump" the REV* values down?

 

 

13

 

12

11

10

 

9

 

If the answer is NO, Then how do you go about it?

 

Are you using multiple layout tabs?

Are the Tblocks on Model space?

Are there more than one Tblock per drawing?

 

One must consider all conditions Da Ballz, Hence the questions.

 

pBe

Edited by pBe
Link to comment
Share on other sites

Each title block has a different number of revisions. For example, the horizontal title block has room for 4 revisions, so there is REV1, REV2, REV3, REV4. Let's say REV is 1. REV1 is 0, REV2 is 1. Therefore REV2 and REV have matching values. REV3 and REV4 hold no values yet. Also, I already have a routine that shifts the revisions down once the revision area gets filled up. I don't need to remove any revision information. All I'm trying to do is find the correct DATE* and DESC* attributes and change their values.

 

 

There is only one layout (layout1) per drawing and all title blocks are in paper space.

Link to comment
Share on other sites

All I'm trying to do is find the correct DATE* and DESC* attributes and change their values.

 

And by this you mean the matching value for REV and REV* tag correct? The whole point of my question is what IF there are NO match? I do believe finding the correct DATE* and DESC* is easy as long as there is a match. I just throw in that question in case that condition ever happens.

 

Anyhoo I see that Commandobills' code works for you, there's no need to confuse the issue now.

 

Cheers

pBe

Link to comment
Share on other sites

Ah, good point. In this case there will always be a match. Basically what I'm doing is going back and changing ALL of the dates and descriptions for the latest revision to the same date and description. Otherwise, I'd have to go back manually and repetitively change them all. Since they will all be the same, the script saves hours. Also, since they will all be the same, now I can go in and update the database in excel quite easily. Thanks for your input.

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...