Learning iLogic. One-line Rule Won't Work.

Learning iLogic. One-line Rule Won't Work.

SometimesInventorMakesMeAngry
Advocate Advocate
896 Views
11 Replies
Message 1 of 12

Learning iLogic. One-line Rule Won't Work.

SometimesInventorMakesMeAngry
Advocate
Advocate

Previously, I used the Snippets in the iLogic rule editor to pass parameters from part to assembly and suppress components/features with conditional statements.  However, I've seen some of the really cool stuff some people here have come up with and I want to get there eventually. So I read through the first few paragraphs of the "AutoDesk Inventor 2015 API Help" document to attempt to recreate passing parameters  using fully-qualified references so I can start getting the hang of "traversing" Inventor's Object Model. So I looked at their 2013 API Object Model and tried to create a parameter based on a previous post I found here

oMyParameter=ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters
oParameter=oMyParameter.AddByExpression("Length_inch", "3", UnitsTypeEnum.kInchLengthUnits)

Which I figured is the same thing as

ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters.AddByExpression("Width_mm", "3", "mm")

So that works perfectly, but based on what I read in the Help document, it seems that "This Application" and "ActiveDocument" are shortcuts of sorts to avoid having to type out the whole

Application.Documents.AssemblyDocument.AssemblyComponentDefinition

path. So I just followed the full path based on the Object diagram linked above and came up with

Application.Documents.AssemblyDocument.AssemblyComponentDefinition.Parameters.UserParameters.AddByExpression("Width_mm", "3", "mm")

But when I run it, I get an error "Error on Line 1 : Reference to a non-shared member requires an object reference."

I've tried variations of this like substituting "Inventor" in place of "Application" and substituting the actual file name in place of "Documents" and/or "AssemblyDocument" and deleting "UserParameters" but nothing seems to work. Can someone tell me what I'm doing wrong? I'm sure it's something really basic, but I couldn't find it in the Help Doc.

I've also tried to reverse engineer other rules posted on here, but I've been unsuccessful. I find that people often use

"Dim oDoc As PartDocument" or something like that and then "oDoc=ThisApplication.ActiveDocument", but I'm not sure how that works. The first seems like they're declaring a variable but the data types I've found are integers, strings, etc. I haven't seem "Part Document" as a data type. The second seems straightforward. I think they're just condensing the long "ThisApplication.ActiveDocument" into "oDoc" to make it shorter and easier to read.

 

I am new to programming (though I know some related things like for loops, while loops, variables, conditional statements, arrays, etc from using an automation app for smartphones) so please keep that in mind and if you have any resources for me to look at, that would be great.

0 Likes
Accepted solutions (3)
897 Views
11 Replies
Replies (11)
Message 2 of 12

Sergio.D.Suárez
Mentor
Mentor

Hi, I'm also like your navigator and I investigate, I try again and again, going through many mistakes along the way.
I think what is recommended in ilogic is to use the fragment

Dim doc as document = ThisDoc.Document

Then you agree to its definition

Dim oCD as componentdefinition = doc.componentdefinition

and finally you continue in that structure accessing the internal properties, for example

oMyParameter = oCD.Parameters.UserParameters

The difference in accessing the document in ilogic as "ThisDoc.Document" with "ThisApplication.ActiveDocument" is that with the first one you always access the document where the rule can be found and another document can be activated, while with Activedocument you access the active document and this It can give some conflicts. For example if you are in an assembly and you want to run a rule within a component while editing the component from assembly, if in the rule the document would be defined as "ThisApplication.ActiveDocument" would reference the assembly and give us an error.
I hope it was clear, show us an example of what you are trying to achieve, maybe we can help you. regards


Please accept as solution and give likes if applicable.

I am attaching my Upwork profile for specific queries.

Sergio Daniel Suarez
Mechanical Designer

| Upwork Profile | LinkedIn

Message 3 of 12

Thank you. That was very clear, but I still have a few questions:

1. Why do you have to go through this seemingly wasteful method of assigning variables to portions of the API object path instead of typing the whole path?

2. What does 

Dim doc as document = ThisDoc.Document

even mean? Can you just type

Dim doc as ThisDoc.Document

instead?

 

I'm just trying to make a rule that creates a list of new variables in a part and in an assembly,  but I'm trying to first accomplish that using fully qualified references so that I can understand the API object model. After I do this, then I can consider moving on to using shortcuts like "ThisApplication.ActiveDocument" and "ThisDoc.Document" (where can I find documentation for these, by the way?).

 

Based on the diagram here, I would think that creating a parameter in an assembly can be accomplished like this:

Application.Documents.AssemblyDocument.AssemblyComponentDefinition.Parameters.UserParameters.AddByExpression("Width_mm", "3", "mm")

and creating a parameter in a part can be accomplished like this:

Application.Documents.PartDocument.PartComponentDefinition.Parameters.UserParameters.AddByExpression("Width_mm", "3", "mm")

But neither works. I get the error:

"Error on Line 1 : Reference to a non-shared member requires an object reference.
Error on Line 2 : Reference to a non-shared member requires an object reference."

Can you explain why?

 

 

0 Likes
Message 4 of 12

philip1009
Advisor
Advisor

iLogic works a bit differently than legit Visual Basic with the intent of making it easier to code with.  As for why starting with Application instead of ThisApplication is a problem, I can't answer that.  But, unless you're getting advanced with your code to involve Sub-Routines and Functions, you don't have to use the "Dim object As object" line whenever you make a new object, in iLogic, "oDoc = ThisDoc.Document" works just fine without the Dim.

 

The only objects you may have to dim ahead of time are those used for looping to avoid the "Objects contained in a With block" error:

 

Dim objOcc As ComponentOccurrence

For Each objOcc In ThisDoc.Document.ComponentDefinition.Occurrences

MsgBox(objOcc.Name)

Next

Message 5 of 12

SometimesInventorMakesMeAngry
Advocate
Advocate

Why do you do

Dim objOcc As ComponentOccurrence
For Each objOcc In ThisDoc.Document.ComponentDefinition.Occurrences
MsgBox(objOcc.Name)
Next

instead of

For Each ComponentOccurrence In ThisDoc.Document.ComponentDefinition.Occurrences
MsgBox(objOcc.Name)
Next

Would they both work or do you have to always assign a variable to an object?

0 Likes
Message 6 of 12

clutsa
Collaborator
Collaborator

I attached a screen-cast I made for someone else on finding object browser info (I know you said you were looking at the object model but didn't know how you're accessing it.)

If you want to get a better understanding of the declaring variables and why it's important read up on "Object Oriented Programming". 

I'm going to (try to) answer question 2 first and that will help explain question 1.

"Dim" tells the computer you want to make a variable. "doc" is your name for the variable. "As" lets the computer know you're about to tell it what the variable type is. "document" is the object type. In OOP the objects are kind of like small sub-programs. The object hold it's own variables and methods (rules). So at this point you now have all the stuff that makes an document do what a document does.... but the computer doesn't know which document to work with (as a human we assume the open document but the computer doesn't assume.) "=" lets the computer know you're about to give it something for the object to reference. "ThisDoc.Document" is what the variable will hold and know what to run it's code against.  It would be like if your boss walked up first thing in the morning and said "finish THE project" and walked away. You are working on 5 projects, which one is THE project?

 

For question 1 you can save a TON of time in longer bits of code by assigning variables... why would I want to type

ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters.AddByExpression("Width_mm", "3", "mm")
ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters.AddByExpression("Height_mm", "5", "mm")
ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters.AddByExpression("Depth_mm", "6", "mm")
ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters.AddByExpression("Hole_Size_mm", ".3", "mm")

when

oMyParam=ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters
oWidth=oMyParam.AddByExpression("Width_mm", "3", "mm")
oHeight=oMyParam.AddByExpression("Height_mm", "5", "mm")
oDepth=oMyParam.AddByExpression("Depth_mm", "6", "mm")
oHoleDia=oMyParam.AddByExpression("Hole_Size_mm", ".3", "mm")

works. 

 

 

If I've helped you, please help me by supporting this idea.
Mass Override for Each Model State

Custom Glyph Icon for iMates

Message 7 of 12

clutsa
Collaborator
Collaborator
Accepted solution
For Each ComponentOccurrence In ThisDoc.Document.ComponentDefinition.Occurrences
MsgBox(ComponentOccurrence.Name)
Next

"ComponentOccurrence" in the code above is only a name. Inventor has know idea what ComponentOccurrence can do, it has know idea ComponentOccurrence should have a variable in it called "Name" 

Dim objOcc As ComponentOccurrence
For Each objOcc In ThisDoc.Document.ComponentDefinition.Occurrences
MsgBox(objOcc.Name)
Next

But in the code above a very kind programmer has already written the code that lets Inventor know that objOcc has a variable that is called "Name" and how to set that variable and recall that variable and what is acceptable to be considered a legitimate name and all you have to do to leverage that kind programmers hard work is tell it "Dim objOcc as ComponentOccurrence"  and you now have all that code at your disposal (along with hundreds of other lines they've added to do many other things).

I totally get where you're coming from that it seems stupid to add all the "extra" lines but it's necessary for the computer to have clear instructions of what it can do, how to do them, and what are safe targets.

If I've helped you, please help me by supporting this idea.
Mass Override for Each Model State

Custom Glyph Icon for iMates

Message 8 of 12

philip1009
Advisor
Advisor

When going through the loop it assigns the next ComponentOccurrence in the collection of Occurrences to that Object so you can refer to it in the looping code.  It simply goes through Occurrences.Item(1) to however many Occurrences there are.  MsgBox than calls up the currently assigned occurrence in the loop by the assigned object objOcc.  You can't just simply use an Object Type as an Object.

 

If you're only going to loop through a collection once or are not going to call that object outside of that loop then you don't need to dim the object ahead of time, you could just use this:

For Each objOcc As ComponentOccurrence In ThisDoc.Document.ComponentDefinition.Occurrences

 

I don't know why Visual Basic is set up this way, it is what it is and I doubt Autodesk is going to attempt to revamp VB.

Message 9 of 12

SometimesInventorMakesMeAngry
Advocate
Advocate

@clutsa wrote:
For Each ComponentOccurrence In ThisDoc.Document.ComponentDefinition.Occurrences
MsgBox(ComponentOccurrence.Name)
Next

"ComponentOccurrence" in the code above is only a name. Inventor has know idea what ComponentOccurrence can do, it has know idea ComponentOccurrence should have a variable in it called "Name" 

Dim objOcc As ComponentOccurrence
For Each objOcc In ThisDoc.Document.ComponentDefinition.Occurrences
MsgBox(objOcc.Name)
Next

But in the code above a very kind programmer has already written the code that lets Inventor know that objOcc has a variable that is called "Name" and how to set that variable and recall that variable and what is acceptable to be considered a legitimate name and all you have to do to leverage that kind programmers hard work is tell it "Dim objOcc as ComponentOccurrence"  and you now have all that code at your disposal (along with hundreds of other lines they've added to do many other things).

I totally get where you're coming from that it seems stupid to add all the "extra" lines but it's necessary for the computer to have clear instructions of what it can do, how to do them, and what are safe targets.


Makes sense! Typing "For Each ComponentOccurrence In ThisDoc.Document.ComponentDefinition.Occurrences" is the same thing as typing "For Each RandomWord In ThisDoc.Document.ComponentDefinition.Occurrences" because the computer doesn't know what RandomWord is until I tell it that it's an object with all kinds of properties and methods underneath it by using the Dim As command. 

 

What is a little confusing, though is that it doesn't know what "ComponentOccurence" is but it does know what "ThisDoc.Document.ComponentDefinition.Occurrences" is without telling it beforehand. But, like @philip1009 says, I guess it's just how it was set up and it doesn't make sense to spend that much time questioning it because it isn't going to change.

 

I'm very interested to see that screencast you mentioned. I hope that you can send me a link if you decided you don't want to post it publicly. This is the flow chart/diagram I am referencing, by the way. It looks like one of your posts disappeared. Again, that was actually very helpful so I'm not sure why it was removed.

0 Likes
Message 10 of 12

clutsa
Collaborator
Collaborator
Accepted solution

@dlopez0682 

Thanks for pointing out that my post disappeared. I totally missed that! That's a bummer because I worked really hard on it. attached is the screen cast and I'll also throw in this youtube video that I found. It's long but I think it's very useful to people that are new to Inventor programming (if I remember what's actually in it.) 

 

https://www.youtube.com/watch?v=MFU_QaGdIDA

 

If I've helped you, please help me by supporting this idea.
Mass Override for Each Model State

Custom Glyph Icon for iMates

Message 11 of 12

clutsa
Collaborator
Collaborator
Accepted solution

Here is the post that disappeared (edited to make sense at this point in the conversation.

 

If you want to get a better understanding of the declaring variables and why it's important read up on "Object Oriented Programming". 

I'm going to (try to) answer question 2 first and that will help explain question 1.

"Dim" tells the computer you want to make a variable. "doc" is your name for the variable. "As" lets the computer know you're about to tell it what the variable type is. "document" is the object type. In OOP the objects are kind of like small sub-programs. The object hold it's own variables and methods (rules). So at this point you now have all the stuff that makes an document do what a document does.... but the computer doesn't know which document to work with (as a human we assume the open document but the computer doesn't assume.) "=" lets the computer know you're about to give it something for the object to reference. "ThisDoc.Document" is what the variable will hold and know what to run it's code against.  It would be like if your boss walked up first thing in the morning and said "finish THE project" and walked away. You are working on 5 projects, which one is THE project?

 

For question 1 you can save a TON of time in longer bits of code by assigning variables... why would I want to type

ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters.AddByExpression("Width_mm", "3", "mm")
ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters.AddByExpression("Height_mm", "5", "mm")
ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters.AddByExpression("Depth_mm", "6", "mm")
ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters.AddByExpression("Hole_Size_mm", ".3", "mm")

when

oMyParam=ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParametersoWidth=oMyParam.AddByExpression("Width_mm", "3", "mm")
oHeight=oMyParam.AddByExpression("Height_mm", "5", "mm")
oDepth=oMyParam.AddByExpression("Depth_mm", "6", "mm")
oHoleDia=oMyParam.AddByExpression("Hole_Size_mm", ".3", "mm")

works. 

End original post

 

The "ThisDoc.Document..." part works because they shortcutted the ThisDoc from

Dim ThisDoc as Document
Set ThisDoc = ThisApplication.Documents.ActiveDocument

and the ThisApplication works because it's shortcutted from 

Dim ThisApplication as Inventor.Application
Set ThisApplication = GetObject(, "Inventor.Application")
If I've helped you, please help me by supporting this idea.
Mass Override for Each Model State

Custom Glyph Icon for iMates

Message 12 of 12

SometimesInventorMakesMeAngry
Advocate
Advocate

@clutsa you've been incredibly helpful! Thank you so much! I think this will be enough to get me started and I'm sure I'll come back an re-read this over and over. Again, thanks.

0 Likes