Jump to content

Match most current attribute value to another attribute in title block


Da Ballz

Recommended Posts

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)

)

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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...

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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...

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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.

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...