Jump to content
Da Ballz

Match most current attribute value to another attribute in title block

Recommended Posts

Da Ballz

Commandobill wrote some code awhile back. I need to tweak. The blue code below needs to be changed and I'm racking my brain. Instead of the attribute values being replaced manually, I need the value for the highest REV attribute in the REV block to go into the "REV" attribute. The code currentlyfinds the highest REV attribute but then replaces that with manual text.

 

In place of the blue I need something like:

(cb:replaceAttributeValue "REV" (the attribute value for the highest REV, example: 5 for REV5) (vlax-ename->vla-object x))

 

Most of the code is already here, it's just getting the cb:replaceAttributeValue function to match the attribute value of "REV" with the attribute value of the highest REV in the revblock (5 for attribute REV 5, for example).

 

(vl-load-com)

(defun c:test11 ( / blockSS blockList attName attNumber)

(if

(setq blockSS (ssget "X" (list (cons 0 "INSERT") (cons -4 ""))))

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

)

Share this post


Link to post
Share on other sites
Da Ballz
 (cb:replaceAttributeValue (strcat "DATE" attNumber) "29-JUN-15" (vlax-ename->vla-object x)) [code]

 

The above code replaces the attribute value (strcat "DATE" attNumber), which could be an attribute with the tag DATE1, or DATE2, or DATE3, ect. depending on which line in the revision block has the most current revision.

 

What I want to do is replace attribute REV with the attribute value in (strcat "REV" attNumber). For this particular title block, let's say this attribute is REV5 and the value is 12. I need to pass the value of REV5 (12) to REV so they both say 12. Currently the value of REV is most likely X by default because the routine I use to swap title blocks doesn't know what REV should be.

Share this post


Link to post
Share on other sites
BIGAL

Post a dwg, two blocks Title block and Rev block ?

Share this post


Link to post
Share on other sites
Da Ballz

BIG AL,

 

Thank you kind Sir. I don't have access to the actual files at the moment, but I recreated a quick temporary title block that should be good enough for proof of concept.

 

There is a REV attribute at the bottom right corner that shows the current drawing REV.

 

Above that there is the REV block. It can hold 6 revisions. Each attribute is named REV1, REV2 through REV6. I currently have the drawing set at revision 5, and I have added a value of 5 to the REV5 attribute. In reality, that value could be anything since there are only 6 revisions possible, for example, the drawing could be up to revision 100 at the REV5 position, but I just kept it simple.

 

That said, I need code that will get the latest revision or most current revision attribute value (5 at REV5 in this case) and set that same value in the REV attribute at the bottom right hand corner. I literally have thousands of drawings where the old title block didn't have the REV attribute in the bottom right hand corner.

 

The cb:matchAtts subfunction in the code I posted at the beginning of this thread seems to work in finding the most current revision. I think what needs to be tweaked is the cb:replaceAttributeValue subfunction. Currently it replaces the value at REV with REV5, the tag name, it needs to be the actual value of the attribute (5) in this case.

Share this post


Link to post
Share on other sites
BIGAL

Just started from scratch much easier. This does only 1 layout as a test but can be modified pretty easy to check all layouts. Only one errror check that you don't have more than 1 block.

 

; daballz lisp 
; by Alan H june 2017
; hard coded for the block

(defun c:daballz  ( / blockss x y atts obj tagname lookfor revtemp)
(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>"))))

(if (> 1 (setq x (sslength blockss))) ; make sure only one title block
(progn
(Alert "You have more than 1 title block on this page\n\nprogram will exit")
(exit) ; hard coded exit not vey gracefull
)
(princ "ok") ; dummy statement
)

(setq obj (vlax-ename->vla-object (ssname blockss 0))) ; get the 1st obj inside the selection set
(setq atts (reverse  (vlax-invoke obj  'getattributes))) ; get all the attributes and convert to a list

(setq x 1)
(repeat (setq y (length atts )) ; loop for all attributes
(setq lookfor (strcat "REV" (rtos x 2 0))) ; add a number as a string to "REV"
(setq tagname (vla-get-tagstring (nth  (setq y (- y 1))  atts))) ; get attribute 1 at a time
(if (= tagname  lookfor) ; check for match tag names
(setq revtemp (vla-get-textstring (nth  y  atts))) ; if true set temp value repeat for highest number
)
(if  (and (/=  revtemp "" )(< x 7)) ; double check for a blank field and no more than 6 revisions
(progn
(setq revval revtemp)
(setq x (+ x 1))
(setq revtemp "") ; needed to make sure resets inside loop
)
)
)

(setq lookfor  "REV" ) ; destination tag name
(repeat  (setq y (length atts )) ; loop through the attributes 
(setq tagname (vla-get-tagstring (nth  (setq y (- y 1))  atts))) ; get tagstring of a attribute
(if (= tagname lookfor) ; test for match
(vla-put-textstring (nth  y  atts) revval) ; if match change value
)
)

)
(c:daballz)

Edited by BIGAL

Share this post


Link to post
Share on other sites
Da Ballz

My friend, truly phenomenal work. It's working for now. I'll have to tweak, but the bulk of the logic in the middle of the routine is what I was struggling with. Again, thanks.

Share this post


Link to post
Share on other sites
Da Ballz

I'm now running this on my actual title blocks in AutoCAD 2014, and I'm getting the following error:

 

Command: REVMATCH

ok; error: ActiveX Server returned an error: Parameter not optional

 

I put the code within (defun c:REVMATCH ( / ) ) and added a (vl-load-com), but I'm still getting this error.

 

Any ideas? It was working on AutoCAD 2015 with the mock block that had the exact same block name and attribute tag names...

Share this post


Link to post
Share on other sites
BIGAL

I have edited code above it to match your REVMATCH and checked against you sample dwg.

Share this post


Link to post
Share on other sites
Da Ballz

The block name and attribute names are identical, but does it matter if the block has other properties and other attributes that aren't included in the sample drawing? I will send you the actual title block as soon as I get a chance.

Share this post


Link to post
Share on other sites
Da Ballz

Here is the working title block. I may be having issues with my vcom.dll as well, working that now. If you run it on this one and it works...let me know. Also, I'm running AutoCAD 2014.

Share this post


Link to post
Share on other sites
BIGAL

Very simple your rev block does not have anything in it, we would do something like PA for Preliminary "A" or maybe "-1" for work in progress. The code uses if blank then stop.

Share this post


Link to post
Share on other sites
SLW210

Please read the Code Posting Guidelines and edit your Code to be included in Code Tags.[NOPARSE]

Your Code Here[/NOPARSE]

=

Your Code Here

Share this post


Link to post
Share on other sites
Da Ballz

I tried the routine on a title block with all of the attributes filled in. I still get the error:

 

Command: REMATCH

ok; error: Activex Server returned an error: Parameter not optional

 

I debugged in Vlide, but there is no obvious issue with syntax or anything.

 

The last break was on the following line:

 

 setq obj (vlax-ename->vlaobject (ssname blockss 0))) 

 

This is what made me think there was an issue with the vl library/activex plugin/app. But all of my other routines seem to be working fine, and they include visual lisp...so...

Share this post


Link to post
Share on other sites
Da Ballz

Forgot the left ( in that code, it's there...so that isn't the problem.

Share this post


Link to post
Share on other sites
BIGAL

Its very weird maybe a hidden character somewhere in code will find it.

 

Found the mistake (setq revtemp "")

 

See code update above so simple somewhere between testing, saving and copying dropped a line.

Edited by BIGAL

Share this post


Link to post
Share on other sites
Da Ballz

That did the trick my friend. Looks like it's good to go.

 

Stupid question, how would I add one more title block to look for? There are actually 3 title different title blocks. I tried to simply add

 

 (cons 2 "Drawing_Sheet_Vendor") 

 

How do the (cons -4 "") pieces work? Would I just change the parameters associated with "cons" so I can add the third, or do I need to rewrite the ssget for the main block list?

Share this post


Link to post
Share on other sites
ronjonp
That did the trick my friend. Looks like it's good to go.

 

Stupid question, how would I add one more title block to look for? There are actually 3 title different title blocks. I tried to simply add

 

 (cons 2 "Drawing_Sheet_Vendor") 

 

How do the (cons -4 "") pieces work? Would I just change the parameters associated with "cons" so I can add the third, or do I need to rewrite the ssget for the main block list?

 

You could simplify your filter to this: (setq blockss (ssget "X" '((0 . "INSERT") (2 . "Drawing_Sheet_*")))) to grab all blocks starting with Drawing_Sheet_.

Edited by ronjonp

Share this post


Link to post
Share on other sites
Da Ballz

I was going through some routines which I'm compiling in scripts and I ran into that exact same code in another lisp. Thanks! Gets the job done.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×