Change Block Entity To Another Color

Change Block Entity To Another Color

RocksterB
Advocate Advocate
2,573 Views
28 Replies
Message 1 of 29

Change Block Entity To Another Color

RocksterB
Advocate
Advocate

I need a routine that changes all blocks in a file containing overriding colored entities from one color to another color. The routine should prompt me for both colors. This would include changing the containing nested blocks as well. Example, change color 9 to color 253. Thanks in advance.  

0 Likes
Accepted solutions (1)
2,574 Views
28 Replies
Replies (28)
Message 2 of 29

MrJSmith
Advocate
Advocate
(defun c:BlockEntityUpdate ( / oldColor newColor blks ct)
	(or *acdoc* (setq *acdoc* (vla-get-activedocument (vlax-get-acad-object))))
	(vla-StartUndoMark *acdoc*) ;set an undo point for quickly reverting changes
	(setq oldColor (getint "Enter number of OLD color of block entities to change from:  ")) ;old color
	(setq newColor (getint "Enter number of NEW color of block entities to change into:  ")) ;new color
	(setq blks (vla-get-blocks *acdoc*)) ;vla blocks collection
	(setq ct 0) ;count for how many entities colors were changed
	
	(vlax-for blk blks ;loop through each block in the blocks collection
		(vlax-for obj blk ;loop through each entity in the block
			(if (= (vla-get-color obj) oldColor) ;entity color compare
				(progn
					(vla-put-color obj newColor) ;update entity color
					(setq ct (+ ct 1)) ;count the entity color change
				)
			)
		)
	)
	(vla-regen *acdoc* acActiveViewport) ;regen the viewport to display the updates to the user
	(print (strcat "Updated " (itoa ct) " entities from color: " (itoa oldColor) " into new color: " (itoa newColor) ".")) ;notify the user of the changes
	(vla-EndUndoMark *acdoc*) ;end the undo point
	(princ)
)
Message 3 of 29

RocksterB
Advocate
Advocate

Thank you for the prompt response. However, I noticed that your routine made changes to all entity types in the file that had an overriding color, instead of just the ones within blocks. This is more than I had anticipated, but could have unexpected results. Your routine is very useful in situations where all the entities in a file must be changed. Is it possible to restrict the routine to only modify the blocks?

0 Likes
Message 4 of 29

komondormrex
Mentor
Mentor

check this one

(defun c:change_block_color (/ from_color to_color)
	(setq from_color (getint "\nChange Block Enames color From: ")
	      to_color (getint "\nChange Block Enames color To: ")
      	)
	(vlax-map-collection (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
				'(lambda (block) (if (and (zerop (vlax-get block 'islayout))
							  (zerop (vlax-get block 'isxref))
						 )
							(vlax-map-collection block 
								'(lambda (object) (if (= from_color (vla-get-color object))
											(vla-put-color object to_color))
										  )
								 )
						 	)
				 )
	)
	(vla-regen (vla-get-activedocument (vlax-get-acad-object)) acactiveviewport)
	(princ)
)
0 Likes
Message 5 of 29

MrJSmith
Advocate
Advocate

While I am sure @komondormrex solution works, this is how I would have handled it.

 

 

(defun c:BlockEntityUpdate ( / oldColor newColor blks ct)
	(or *acdoc* (setq *acdoc* (vla-get-activedocument (vlax-get-acad-object))))
	(vla-StartUndoMark *acdoc*) ;set an undo point for quickly reverting changes
	(setq oldColor (getint "Enter number of OLD color of block entities to change from:  ")) ;old color
	(setq newColor (getint "Enter number of NEW color of block entities to change into:  ")) ;new color
	(setq blks (vla-get-blocks *acdoc*)) ;vla blocks collection
	(setq ct 0) ;count for how many entities colors were changed
	
	(vlax-for blk blks ;loop through each block in the blocks collection
		(if (not (or (= :vlax-true (vla-get-islayout blk)) (= :vlax-true (vla-get-isxref blk)))) ;make sure not an xref or paper/model/layout block
			(vlax-for obj blk ;loop through each entity in the block
				(if (= (vla-get-color obj) oldColor) ;entity color compare
					(progn
						(vla-put-color obj newColor) ;update entity color
						(setq ct (+ ct 1)) ;count the entity color change
					)
				)
			)
		)
	)
	(vla-regen *acdoc* acActiveViewport) ;regen the viewport to display the updates to the user
	(print (strcat "Updated " (itoa ct) " entities from color: " (itoa oldColor) " into new color: " (itoa newColor) ".")) ;notify the user of the changes
	(vla-EndUndoMark *acdoc*) ;end the undo point
	(princ)
)

 

 

Note: Attribute blocks will not update unless they are synced afterwards. I am hesitant to force sync them as people often times make modifications to them improperly (using grips or other methods). 

0 Likes
Message 6 of 29

RocksterB
Advocate
Advocate

MrJSmith, I get an error when I run you latest routine: "; error: no function definition: DEBUG".

 

komondormrex, Your routine seems to work as requested.

 

I don't want to include XREF's in this routine's task. If possible, could tables also be included in the change routine?

0 Likes
Message 7 of 29

MrJSmith
Advocate
Advocate

You can delete that line. I updated it with it removed. Both should filter out xrefs. I think tables are different, I don't use them often, but it shouldn't be hard to include them.

0 Likes
Message 8 of 29

RocksterB
Advocate
Advocate

Great! I'll keep an eye you for your update that includes tables and the error fix.

0 Likes
Message 9 of 29

komondormrex
Mentor
Mentor

the code will miss the xrefs, however. what tables do you mean - ones outside any block?

0 Likes
Message 10 of 29

RocksterB
Advocate
Advocate

AutoCAD tables (Excel'ish) that are within the file, usually on a paperspace sheet but not always. These are standalone tables not within blocks.  

0 Likes
Message 11 of 29

komondormrex
Mentor
Mentor

check update below

 

(defun c:change_table_block_color (/ from_color to_color)
	(setq from_color (getint "\nChange Block Enames/Tables color From: ")
	      to_color (getint "\nChange Block Enames/Tables color To: ")
      	)
	(vlax-map-collection (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
				'(lambda (block) (cond
				   			((minusp (vlax-get block 'islayout))
								 (vlax-map-collection block 
									'(lambda (object) (if (and (= "AcDbTable" (vla-get-objectname object))
												   (= from_color (vla-get-color object))
											      )
												(vla-put-color object to_color)
											  )
									)
								)
							 
							)
							((zerop (vlax-get block 'isxref))
								(vlax-map-collection block 
									'(lambda (object) (if (= from_color (vla-get-color object))
												(vla-put-color object to_color))
											  )
									 )
						 	)
							( t )
						)
				 )
	)
	(vla-regen (vla-get-activedocument (vlax-get-acad-object)) acactiveviewport)
	(princ)
)

 

0 Likes
Message 12 of 29

MrJSmith
Advocate
Advocate

This will change blocks and tables.

(defun c:BlockEntityUpdate ( / oldColor newColor blks ct)
	(or *acdoc* (setq *acdoc* (vla-get-activedocument (vlax-get-acad-object))))
	(vla-StartUndoMark *acdoc*) ;set an undo point for quickly reverting changes
	(setq oldColor (getint "Enter number of OLD color of block entities to change from:  ")) ;old color
	(setq newColor (getint "Enter number of NEW color of block entities to change into:  ")) ;new color
	
	;Change Blocks
	(setq blks (vla-get-blocks *acdoc*)) ;vla blocks collection
	(setq ct 0) ;count for how many entities colors were changed
	(vlax-for blk blks ;loop through each block in the blocks collection
		(if (not (or (= :vlax-true (vla-get-islayout blk)) (= :vlax-true (vla-get-isxref blk)))) ;make sure not an xref or paper/model/layout block
			(vlax-for obj blk ;loop through each entity in the block
				(if (= (vla-get-color obj) oldColor) ;entity color compare
					(progn
						(vla-put-color obj newColor) ;update entity color
						(setq ct (+ ct 1)) ;count the entity color change
					)
				)
			)
		)
	)
	
	;Change Tables
	(vlax-for layout (vla-get-layouts *acdoc*)
		(vlax-for obj (vla-get-block layout) 
			(if
				(and 
					(= "AcDbTable" (vla-get-objectname obj)) ;Check if it is a table
					(= (vla-get-color obj) oldColor)
				)
				(progn
					(vla-put-color obj newColor) ;update entity color
					(setq ct (+ ct 1)) ;count the entity color change
				)
			)
		)
	)
					
	(vla-regen *acdoc* acActiveViewport) ;regen the viewport to display the updates to the user
	(print (strcat "Updated " (itoa ct) " entities from color: " (itoa oldColor) " into new color: " (itoa newColor) ".")) ;notify the user of the changes
	(vla-EndUndoMark *acdoc*) ;end the undo point
	(princ)
)
0 Likes
Message 13 of 29

RocksterB
Advocate
Advocate

Both of the two routines work and satisfy the request. Thank you for your assistance.

0 Likes
Message 14 of 29

RocksterB
Advocate
Advocate

I ran across an issue with both of your routines on the changed table. At first the table appears to except the color change. When the table is moved, copied, etc. the table entities reverts back to the old colors. The changes don't stick to the table entities.

0 Likes
Message 15 of 29

MrJSmith
Advocate
Advocate

I can not reproduce this issue. Created a table, set color to 3, ran the program to change it to color 1, moved/copied/changed text/etc table and it still remained color 1. Tried this for both paper space and model space, table retained its color. Do you have another script/reactor that is auto changing the colors?

0 Likes
Message 16 of 29

RocksterB
Advocate
Advocate

I wonder if the properties in the table style itself are overriding the changes by your routine?

0 Likes
Message 17 of 29

MrJSmith
Advocate
Advocate

Potentially. As I mentioned I am not familiar with tables, personally hate them. They could be like Mleaders though which have multiple different components/ways to control its colors and thereby require additional code to complete its color changing. 

 

In AutoCAD, how would you typically change their colors so that the changes stick?

0 Likes
Message 18 of 29

RocksterB
Advocate
Advocate

Typically, I would click on/into the table's cell and change the text property of the cell(s). I've never had the cell text revert itself back due to a move or copy action. 

0 Likes
Message 19 of 29

MrJSmith
Advocate
Advocate

So you are changing the text color inside the cell itself? Rather than the table entity color? 

0 Likes
Message 20 of 29

MrJSmith
Advocate
Advocate

This should handle cell color changes.

 

(defun c:BlockEntityUpdate ( / oldColor newColor blks ct ss oldTxt newTxt elist replaceAll)
	(defun replaceAll (oldtext newtext textstring / i n)
		(setq n (strlen newtext))
		(while (setq i (vl-string-search oldtext textstring i))
			(setq 
			textstring (vl-string-subst newtext oldtext textstring i)
			i (+ i n))
		)
		textstring
	)
	(or *acdoc* (setq *acdoc* (vla-get-activedocument (vlax-get-acad-object))))
	(vla-StartUndoMark *acdoc*) ;set an undo point for quickly reverting changes
	(setq oldColor (getint "Enter number of OLD color of block entities to change from:  ")) ;old color
	(setq newColor (getint "Enter number of NEW color of block entities to change into:  ")) ;new color
	
	;Change Blocks
	(setq blks (vla-get-blocks *acdoc*)) ;vla blocks collection
	(setq ct 0) ;count for how many entities colors were changed
	(vlax-for blk blks ;loop through each block in the blocks collection
		(if (not (or (= :vlax-true (vla-get-islayout blk)) (= :vlax-true (vla-get-isxref blk)))) ;make sure not an xref or paper/model/layout block
			(vlax-for obj blk ;loop through each entity in the block
				(if (= (vla-get-color obj) oldColor) ;entity color compare
					(progn
						(vla-put-color obj newColor) ;update entity color
						(setq ct (+ ct 1)) ;count the entity color change
					)
				)
			)
		)
	)
	
	;Change Tables
	(setq ss (ssget "_X" '((0 . "ACAD_TABLE"))))
	(setq oldTxt (strcat "\\C" (itoa oldColor)))
	(setq newTxt (strcat "\\C" (itoa newColor)))
	(foreach table (sslist ss)
		(setq elist (entget table))
		(setq elist (mapcar '(lambda (x) 
			(cond
				((= 1 (car x))
					(cons 1 (replaceAll oldTxt newTxt (cdr x))) 
				)
				((= 302 (car x))
					(cons 302 (replaceAll oldTxt newTxt (cdr x)))
				)
				((= 62 (car x))
					(if (= oldColor (cdr x))
						(progn (setq ct (+ 1 ct))(cons 62 newColor))
						x
					)
				)
				(1 x)
			)
		) elist)) 
		(entmod elist)
	)
					
	(vla-regen *acdoc* acActiveViewport) ;regen the viewport to display the updates to the user
	(print (strcat "Updated " (itoa ct) " entities from color: " (itoa oldColor) " into new color: " (itoa newColor) ".")) ;notify the user of the changes
	(vla-EndUndoMark *acdoc*) ;end the undo point
	(princ)
)

 

0 Likes