IF Visibility State, THEN "Value from an attribute"

IF Visibility State, THEN "Value from an attribute"

nikospur
Contributor Contributor
4,157 Views
20 Replies
Message 1 of 21

IF Visibility State, THEN "Value from an attribute"

nikospur
Contributor
Contributor

Morning!

 

I´ve been struggling with this for a couple of days now.

I have a block which identifies several different emergency signs. Each different sign is an individual visibility state. This is mainly because the top part of the block shows its ID  number, and the bottom one shows its dimensions, but because some signs are circular, others square, others rectangular and others triangular, the dimension shown will be either a diameter, a length or two dimensios. 

Therefore I created a table which includes all the possible dimensions and format for a sign based on the distance from which it will be seen, and through visibility states I show only the "size" format I need for a specific sign (Diameter, length...)

I ran into some trouble with data extraction. I want to combine Diameter, length by width, Length of triangle side, etc into a single column.

To achieve this in an automated manner, I tried several things with no success. Now to my latest idea:

 

If I can create an Attribute that uses an IF/Then Variable I could combine all the dimensions into a single column as follows:

 

If visibility=x then display the content of attribute "diameter". However...

If visibility=y then display the content of the attribute (LxH)

 

The fields have other names because it's in portuguese, but that´s the general idea. I got a feeling I could do this through a Diesel expression but have no idea how to create one myself.

 

I thought adapting this (from another post) might be a good starting point, but I need help:

$(if,$(eq,$(getenv,username),JOSM),"John Smith",$(if,$(eq,$(getenv,username),MAST),"Mary Stewart",Next))

 

I will upload the block to illustrate my point. There are also some jpg that will be missing but are irrelevant.

 

Thanks!!!

 

 

 

0 Likes
4,158 Views
20 Replies
Replies (20)
Message 2 of 21

SeeMSixty7
Advisor
Advisor

Looking at what you are trying to do. It seems you basically have a block that has multiple states. Some offer different radii for I think visibility, is that right? If each block has it's own dimensional data, 1 of three types, right? (Radius, Length and Length and Width) It seems like you should just have two, if it has a length then it has a width doesn't it, even if it is square it just has the same value?

 

Point being if you have 10 signs all with predefined widths based on the identifier. Data is stored for each value of the selected sign type. You have these values stored in several attributes that are controlled by visibility. When you extract that data, you want to try and have a single attribute to extract, is that right? That data field to extract is supposed to be a representation of the sign for that instance. If your data is in one or multiples of the 9 attributes, why not use that data in the system you are extracting it to. I extract all sorts of blocks to a database, then conditionally use the data based on their visibility states. If you are extracting this to excel, you could apply some logic inside it instead of inside the AutoCAD block itself. Take advantage of the system you are using to manage and analyze the data with. It will provide you more flexibility in the long run. The more functionality you develop into your dynamic block the more limited it becomes in use. That might not make much sense. But consider this. What happens when you add a triangle sign or a 3 sided (viewable from 3 sides) sign. Would you rather go back and redesign the block and have to update however many blocks you have to meet the new requirements, or simply update the backend system that uses the data, and instruct it how to process the information.

 

Basically I'm saying provide the raw data in AutoCAD, as little as needed to identify and provide the information needed, then have your back end or reporting system lookup any data it needs and apply whatever conditional data manipulation is needed.

 

Hope that helps,

0 Likes
Message 3 of 21

john.uhden
Mentor
Mentor

If the problem is having multiple identifiers for the dimensions, could you use just one identifier... "size?"

John F. Uhden

0 Likes
Message 4 of 21

nikospur
Contributor
Contributor

I think you got most of it right. Thanks for your answer.

The visibility state defines the content of the sign and the radii defines the size (the further away the observer, the larger the sign must be).

 

I understand. You suggest to extract only the sign ID and radius, and generate the third column directly in excel? It is a good idea. I will still need to keep the other formulas in the block though, because sign size must be displayed for every instance of the block.

 

If I did this I guess I won´t be able to have it automated, and any corrections made to the drawing will imply manually remaking the excel spreadsheet.

It´s not a problem for me, but I was hoping for a better solution that did it automatically so that my co-workers didn´t have to go through so many steps.

 

I will see if anyone else´s answer fits my needs (wants?) a little better before making my decision, but thanks for the input! 

 

 

0 Likes
Message 5 of 21

nikospur
Contributor
Contributor

The formula that defines size varies depending on the sign shape, but derives from the same variable.

 

If I knew how to script all the formulas into just one field and have Acad choose the formula needed on its own, it would be great.

 

To have an unique Size identifier, maybe I could separate into rectangular, square, triangular and circular blocks each with it´s own formula..... hmmmm

0 Likes
Message 6 of 21

SeeMSixty7
Advisor
Advisor

You could automate it as much as you like. What mechanism were you planning to use to data extract originally. That same process applies to the method I suggested. The spreadsheet or code to automate can be in either AutoCAD, DOS (Powershell), or Excel. It all depends on where you want to drive from. If you display the data in the AutoCAD drawing as part of the blocks annotation, make sure it stays there. You can extract all of the data to Excel and then only use what is correct for that ID or type.

 

Hopefully that makes sense.

0 Likes
Message 7 of 21

nikospur
Contributor
Contributor

@john.uhden wrote:

If the problem is having multiple identifiers for the dimensions, could you use just one identifier... "size?"


What do you mean by Identifier? Attribute Tag? I tried using the same attribute tag, but when I try to extract the data it assigns each att a number and thus Size becomes Size(1), Size(2), etc...

 

 

0 Likes
Message 8 of 21

nikospur
Contributor
Contributor

@SeeMSixty7 wrote:

You could automate it as much as you like. What mechanism were you planning to use to data extract originally. That same process applies to the method I suggested. The spreadsheet or code to automate can be in either AutoCAD, DOS (Powershell), or Excel. It all depends on where you want to drive from. If you display the data in the AutoCAD drawing as part of the blocks annotation, make sure it stays there. You can extract all of the data to Excel and then only use what is correct for that ID or type.

 

Hopefully that makes sense.


Probably to someone smarter than me hehehe...

The way my block is set up, if I extract directly to a Cad Table I get too many columns, as I haven´t found a way to combine that information (yet).

So I was extracting to excel, creating an additional column which combines all the shape Sizes into one column. Then I would link that excel to a Table inside AutoCad.

But If I alter the data, extraction will make a new xls file in which I will have to re-create that special column.

 

The Only way I can imagine automating this step is by not messing around with the extracted data spreadsheet, and then creating a new xls sheet which gets only the information I want from the original xls and has an extra "combined" column.  This would be the file I link inside Autocad.  That way when I insert more blocks and do a data extraction, the new extraction file doesn´t mess with the xls file inserted in autocad.  Is this more or less what you were thinking?

I would still have to account for additional rows every time I make a new extraction.  do you know another way?

0 Likes
Message 9 of 21

SeeMSixty7
Advisor
Advisor

Ahhh. I see, missing component is that you are resulting into a Table in CAD. that makes things a bit different. I thought you were extracting the data to excel to use in excel report of some sort. I fit is all in AutoCAD, skip the excel file completely. AutoLISP stands for LIST Processing and does a great job of it. You can do everything you need via AutoLISP.

 

Build your selection set of your blocks, or just this one block and all it's instances. Cycle through each one recognizing the display state and retrieving the appropriate Attributes for that state, place this data into a list variable and then add it to a global list variable of all the instances of the blocks. When you have done this for every block, cycle through the entire list and populate your Table, assuming it is in the same drawing with the blocks. If it is in a different table, write the data to a file then process in the drawing your table is located.

 

Does that help?

Message 10 of 21

nikospur
Contributor
Contributor

@SeeMSixty7 wrote:

Ahhh. I see, missing component is that you are resulting into a Table in CAD. that makes things a bit different. I thought you were extracting the data to excel to use in excel report of some sort. I fit is all in AutoCAD, skip the excel file completely. AutoLISP stands for LIST Processing and does a great job of it. You can do everything you need via AutoLISP.

 

Build your selection set of your blocks, or just this one block and all it's instances. Cycle through each one recognizing the display state and retrieving the appropriate Attributes for that state, place this data into a list variable and then add it to a global list variable of all the instances of the blocks. When you have done this for every block, cycle through the entire list and populate your Table, assuming it is in the same drawing with the blocks. If it is in a different table, write the data to a file then process in the drawing your table is located.

 

Does that help?



You sound so confident that i believe you nailed it!!.  However, I barely understood anything! hehehe

I have no knowledge of Lisp programming other than downloading them and using them. Smiley Embarassed

Am I doomed?

 

 

0 Likes
Message 11 of 21

SeeMSixty7
Advisor
Advisor

Doomed???? NOT AT ALL! grin.

 

That's what this forum is about. We are all here to help you out. This may take some time, but we can work through this if you like an detach you some AutoLISP in the process.

 

If you are wanting to learn,

 

Let's start with learning how to get a selection set of blocks inserted into your drawing and stepping through it.

The following will show you how. Copy an paste this into the command line of your drawing then run the STEPSS command. Let me know when you are ready for the next part.

 

(defun C:STEPSS() 		;define in the new command STEPSS
	(setq myss (ssget "X" '((0 . "INSERT")))) ; Create a selection set of all the inserts (blocks) in your drawing
	(if myss ;Check and see if there is a selection set 
		(progn ;group all the following commands into one process block
			(setq mynum (sslength myss) ; get the length of the selection set 
			      mycnt 0 ; set up a counter to step through 
			)
			(while (< mycnt mynum) ;see if we have step through them all 
			    (setq blkent (ssname myss mycnt) ; retrieve the insert definition based on the index position of the counter
			          blkdata (entget blkent) ; get the DXF data of the insert entity
			          blkname (cdr (assoc 2 blkdata)) ; get the traditional block name
			          blkobj (vlax-ename->vla-object (cdr (assoc -1 blkdata))) ; get the entity object
			          blktruename (vla-get-EffectiveName blkobj); get the effective block name (dynamic block store actual name here)
			          mycnt (1+ mycnt); bump the counter
			    ); close the setq
			    (princ (strcat "\n Insert number " (itoa mycnt))) ;
			    (princ (strcat "\nBlockname:[" blkname "]"))
			    (princ (strcat "\nEffective Name:[" blktruename "]"))
		   ); close the while loop
	    ); close the progn
	    (princ "\nNo BLOCKS Found") ; no blocks found if the myss var is nil
	 ); close the if statement
	 (princ) ; end the command cleanly
);close the defun
Message 12 of 21

nikospur
Contributor
Contributor

Just learnt that you can paste long pieces of script into the command line! yeah!

 

Ok, so I saw a long list of all my inserted blocks with their "Anonymous Name"(As appears with list command.)

 

in this format 

 

Blockname:[*U1278]
Effective Name:[Sinalização de emergência]
Insert number 50

 

what´s next?? 🙂

0 Likes
Message 13 of 21

SeeMSixty7
Advisor
Advisor

Excellent! Yes you can actually paste AutoLISP code directly to the command line, just make sure your closing Parens are all good as well as any string identifiers the double Quotes.

 

There is a lot more to learn. I am just writing this stuff for you to Post here. Erro Trapping is something I am not putting in here just yet. You will eventually get to adding that to your code.

 

Next let's add a new AutoLISP Function to retrieve the display state of each of your blocks.

 

Below is the updated code. I added some new functionality to the STEPSS command. Try this out and play with the code. I will check in on you tomorrow. Good luck.

(defun C:STEPSS() 		;define in the new command STEPSS
	(setq myss (ssget "X" '((0 . "INSERT")))) ; Create a selection set of all the inserts (blocks) in your drawing
	(if myss ;Check and see if there is a selection set 
		(progn ;group all the following commands into one process block
			(setq mynum (sslength myss) ; get the length of the selection set 
			      mycnt 0 ; set up a counter to step through 
			)
			(while (< mycnt mynum) ;see if we have step through them all 
			    (setq blkent (ssname myss mycnt) ; retrieve the insert definition based on the index position of the counter
			          blkdata (entget blkent) ; get the DXF data of the insert entity
			          blkname (cdr (assoc 2 blkdata)) ; get the traditional block name
			          blkobj (vlax-ename->vla-object (cdr (assoc -1 blkdata))) ; get the entity object
			          blktruename (vla-get-EffectiveName blkobj); get the effective block name (dynamic block store actual name here)
			          blkvisstate (myGetDisplayStateFunction blkobj) ; Here we call our function ot get visstate
			          mycnt (1+ mycnt); bump the counter
			    ); close the setq
			    (princ (strcat "\n Insert number " (itoa mycnt))) ;
			    (princ (strcat "\nBlockname:[" blkname "]"))
			    (princ (strcat "\nEffective Name:[" blktruename "]"))
			    (princ (strcat "\nVisibility State: [" blkvisstate "]"))
		   ); close the while loop
	    ); close the progn
	    (princ "\nNo BLOCKS Found") ; no blocks found if the myss var is nil
	 ); close the if statement
	 (princ) ; end the command cleanly
);close the defun
(defun myGetDisplayStateFunction (myBlockObject) ; function dedicated to accepting a block object and will return the vis state
   (if (= (vla-get-isdynamicblock myBlockObject) :vlax-true) ; Check and see if it is a dynamic block
		(progn ; Same as before create a process block for this conditon of the if statement
			(setq myBlockDynProps(vlax-safearray->list (vlax-variant-value (vla-getdynamicblockproperties myBlockObject))))
			; The above line digs in dyamic block properties and creates a list of them for us to cycle through
			(foreach dynprop myBlockDynProps ; For each loops through each item(property) in the list
				(setq propname (vla-get-propertyname dynprop)) ; get the name of the property
				(if (= propname "Visibility") ; We are looking for visibility state
					(progn 
						(setq retVisstate (vlax-variant-value (vla-get-Value dynprop))) ;create a return value when we find it
					)
				)
			)
		)
		(setq retVisstate "") ; Not a dynamic block so no vis state
	)
	retVisstate
)
0 Likes
Message 14 of 21

john.uhden
Mentor
Mentor

You have so much patience you should be a doctor,

 

SeeMSixty9, almost SeeMSeventy0

John F. Uhden

0 Likes
Message 15 of 21

SeeMSixty7
Advisor
Advisor

Thanks John. I think. LOL

0 Likes
Message 16 of 21

nikospur
Contributor
Contributor

Hi!

I´ve been away from the office for a while and I decided to continue this today. 

To refresh my memory, I copied and pasted the original code into the command line.  Then I typed in STEPPS

And this time nothing happened!

I tried the same thing with the updated code and got the same result! Any idea why?

I get -Unknown command "STEPPS"-.  in both cases

 

0 Likes
Message 17 of 21

Anonymous
Not applicable

Hello all,

I sure could use some help here. I've been beating my head against the wall, desk, and monitors for a few weeks now trying to figure out how to make this work. I have a block with "x" amount of visibility states, I have purchased the AutoField program from CADIG to reference an Excel spreadsheet that will put the calculated values, AND text into a field in AutoCAD. (An option that I can't believe that AutoDesk has not yet incorporated.) Anyway, I want to use an input from my Excel table to drive the visibility state of my dynamic block. I will attach a sample dwg & the Excel file. Basically, what I would like to do is to put an input in my Excel table, and have the visibility state of the dynamic block change to the corresponding input. Is this possible? Or am I living in a pipe dream? Thanks for the help.

0 Likes
Message 18 of 21

SeeMSixty7
Advisor
Advisor

No Not impossible at all. Question is do you want it to automatically do the update from the spreadsheet or do the update on request of the user.

 

I would start another thread for this one, if I was you though.

 

Steps to complete this would be to store the entity handle with the row entry in excel. then you could update the excel spreadsheet to the desired visibility state as you desire, save it, then from AutoCAD have AutoCAD read the excel file and then update your block inserts based on the excel data.

 

Good  luck,

 

 

0 Likes
Message 19 of 21

Anonymous
Not applicable
That sounds exactly like what I'm trying to accomplish. The update doesn't
have to be automatic. Per se, but i want it to where there is less need to
actually manipulate the drawing. All data is input into excel, but
updated when the cad operator either opens, regens, prints, or saves the
dwg. I'm not entirely sure how to reference the entity handle in excel and
have it change the visibility states. Is there a link, forum discussion,
black magick voodoo priestess or something that i can use as a guide for
that? Thank you for any and all help you've given so far.
0 Likes
Message 20 of 21

SeeMSixty7
Advisor
Advisor

I don't have time available right now to walk you through it, but basically the process could be.

 

User Implemented method:

First you need to have the correct data in excel file. The entity handle can be accessed from within AutoCAD pretty easily. either using the LIST command and noting the entity handle and inputting it into the excel file as a column next to the blocks insert data. Or an easy method would be to write a routine that extracts all your blocks out to a data file with the current state and the entity handle, then you could use that data file as the driver to change the states. You need to figure out if you are going to read and write directly to excel files or use a csv(text) type file. There are various methods to do either. I personally prefer directly writing to a SQL Server database for all my data. Once you have that data, you create a command to perform the update. It then looks at the current drawing number and then reads the data file to find the records that correspond to the current drawing file. NOTE: Entity handles are unique per drawing file and not across multiple drawings files. So you will need the drawing name, preferably the full path to avoid confusing it with other drawings with the same filename. Once you locate the records, you then process the records, use the enthandle to locate the inserted block then use lisp to toggle the state.

 

I wish I had more time to help more, but I'm pretty swamped lately.

 

Hopefully that gets you started. Good luck.

0 Likes