Community
Inventor Forum
Welcome to Autodesk’s Inventor Forums. Share your knowledge, ask questions, and explore popular Inventor topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

iLogic: use same variable in multiple subs/functions

12 REPLIES 12
Reply
Message 1 of 13
DRoam
6328 Views, 12 Replies

iLogic: use same variable in multiple subs/functions

I have an iLogic rule in which I'm trying to set three user parameters for the gage of each leg of a steel angle. I want Inventor to set the gage based on the length of each leg. Here's the table I referenced for gages: ftp://ftp.clarkson.edu/.class/ce442/public_html/workshop_2.pdf.

 

In my code, I have a sub called DetermineGage which takes the leg length, whether it's the short leg or the long leg, and determines the gages that should belong to that leg. Inside of that sub it calls on a sub called ApplyGage which then applies the determined gage to the rule's gage variables. The main sub then grabs those variables and applies those values to the actual user parameters.... In theory.

 

The rule executes ok with no errors, but doesn't change the value of the user parameters; they're always "0". As best I can tell, the "oGage" variables I used in the rule don't even get assigned the correct value, which makes me think the DetermineGage and ApplyGage subs can't even access the oLegLength or oGage parameters to read or set them. I don't want to use global parameters because I've heard that can make programs very unstable over time and is just bad practice. How can I make these variables accessible to all subs IN THIS RULE, no more no less? Is this possible? See my code below. Thanks for any support!

 

My code:

 

Sub Main()
Dim oLegShort As Double = Min(G_W,G_H)
Dim oLegLong As Double = Max(G_W,G_H)
Dim oLegLength As Double

Dim oGage As Double
Dim oGage1 As Double
Dim oGage2 As Double

'Short Leg:
	oLegLength = oLegShort
	'Call DetermineGages sub to set oGage variables:
	DetermineGages()
	
	On Error Resume Next
	'If gage parameter does not equal true gage, set it equal:
	If Parameter("ShortLegGage") <> oGage Then
		Parameter("ShortLegGage") = oGage
	End If
	'Assume error means gage parameter does not exits. Create and set equal to true gage:
	If Err.Number <> 0 Then
		oMyParameter=ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters
		oParameter=oMyParameter.AddByExpression("ShortLegGage", oGage, "in")
	End If
	On Error Goto 0
	
	On Error Resume Next
	If Parameter("ShortLegGage1") <> oGage1 Then
	Parameter("ShortLegGage1") = oGage1
	End If
	If Err.Number <> 0 Then
	oMyParameter=ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters
	oParameter=oMyParameter.AddByExpression("ShortLegGage1", oGage1, "in")
	End If
	On Error Goto 0
	
	On Error Resume Next
	If Parameter("ShortLegGage2") <> oGage2 Then
	Parameter("ShortLegGage2") = oGage2
	End If
	If Err.Number <> 0 Then
	oMyParameter=ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters
	oParameter=oMyParameter.AddByExpression("ShortLegGage2", oGage2, "in")
	End If
	On Error Goto 0
	
'Long Leg:
	'[Will repeat above for long leg]
	
End Sub
	
Public Sub ApplyGages(ooGage As Double,ooGage1 As Double,ooGage2 As Double)
	oGage = ooGage
	oGage1 = ooGage1
	oGage2 = ooGage2
End Sub

Public Sub DetermineGages()
	Select Case oLegLength
		Case 8
			ApplyGages(4.5,3,3)
		Case 7
			ApplyGages(4,2.5,3)
		Case 6
			ApplyGages(3.5,2.25,2.5)
		Case 5
			ApplyGages(3,2,1.75)
		Case 4
			ApplyGages(2.5,0,0)
		Case 3.5
			ApplyGages(2,0,0)
		Case 3
			ApplyGages(1.75,0,0)
		Case 2.5
			ApplyGages(1.375,0,0)
		Case 2
			ApplyGages(1.125,0,0)
		Case 1.75
			ApplyGages(1,0,0)
		Case 1.5 Or 1.375
			ApplyGages(0.875,0,0)
		Case 1.25
			ApplyGages(0.75,0,0)
		Case 1
			ApplyGages(0.625,0,0)
	End Select
End Sub

 

12 REPLIES 12
Message 2 of 13
DRoam
in reply to: DRoam

Any input on this? I suppose a simpler way to ask the question would be "How can I use functions in iLogic that modify variables used elsewhere in the code?"

Message 3 of 13
cwhetten
in reply to: DRoam

There may be some really slick way of doing this, but you could just create some extra user parameters.  User parameters should be available in any rule or sub.

 

Edit:  To be more clear, I mean to create user parameters for oLegLength and oGage.

 

Cameron Whetten
Inventor 2012

Message 4 of 13
mrattray
in reply to: DRoam

The problem is here: (I think)

ApplyGages(4,2.5,3)

I believe you need to use a two step process of assigning a value to the variable and then calling the sub with the variable referenced in the arguments. Also, you need to dim the variables in the sub in which they are used, not sub main (unless they're used there). Example:

 

Public Sub DetermineGages()
Dim ooGage, ooGage1, ooGage2 As Double
	Select Case oLegLength
		Case 8
                        ooGage = 4.5
                        ooGage1 = 3
                        ooGage2 = 3
               <all your other cases>
	End Select

        ApplyGages(ooGage,ooGage1,ooGage2)
End Sub

 

Try this and let me know how it works for you.

Mike (not Matt) Rattray

Message 5 of 13
DRoam
in reply to: mrattray

Thanks for the suggestions. Cameron, at first I thought that would do the trick, but the goal is to be able to run this rule on any angle's file, even if those user parameters haven't been set up yet. I'd rather not have to create more user parameters with iLogic if I don't have to.

 

Mike, I think you're close to the issue but not quite. The problem is not that the ApplyGages sub can't access the values sent to it by the DetermineGages function; that part is actually functioning fine. I think the issue is in two places:

 

1. The oLegLength parameter is not available to the DetermineGages sub. Therefore, it's not selecting one of the cases.

 

2. The Main sub doesn't have access to the same oGage parameters used in the ApplyGages sub. Therefore, even if I go into the DetermineGages sub and set the value of oLegLength from INSIDE the sub, while the ApplyGages sub WILL then set the values of oGage, oGage1, & oGage2 correctly, the main sub does not then have access to those variables, becasue they're within the scope of the ApplyGages sub and not the Main sub.

 

So my problem basically is scoping, which I don't have near enough programming experience to know how to deal with. All I know is every experienced programmer I know strongly discourages me from using use global variables.

Message 6 of 13
cwhetten
in reply to: DRoam

Variables that are available for all functions and subs--sounds to me like you are trying to use global variables.

 

If you are successfully passing the values of oLegLength and oGage to your functions, can't you also set up your subs to pass values back to the main?  Then the main could set those values to its own local oLegLength and oGage variables.

 

To expand on my earlier idea, you could have the iLogic check if those user parameters already exist, and if they do not, it could create them for you.  Then, it could remove them once the rule finishes so you don't have extra user parameters hanging about.  They would only exist for a moment in the background and be invisible to the user.

 

Cameron Whetten
Inventor 2012

Message 7 of 13
DRoam
in reply to: cwhetten

How could I have my subs pass those values to the main?

 

Yeah, I might need to do that, I'd just like for it all to work with variables within the rule if possible. I'd love to make using functions (I think of subs as functions. I think of them as being bits of code that can be used to do the same operation over and over with different inputs)... anyway, I'd love to make using functions like these a regular part of my iLogic rules, so I can do that I just said: perform the same operation multiple times throughout my code without having to write the operation out every time--just call the function.

 

So if I can just pass variables around between subs and functions without having to use arguments all the time, that would be great. If not, I might just have to work with creating temporary user parameters. Which would be a lot more work (and more code).

Message 8 of 13
mrattray
in reply to: DRoam

Now that I'm looking at your code again I see a couple of problems.

DetermineGages isn't receiving the value of oLegLength because your not passing the variable to it.

Change "Public Sub DetermineGages()" to "Public Sub DetermineGages(oLegLength as Double)" and add oLegLength to the arguments when you call DetermineGages from within Sub Main. This should solve that issue.

 

If you need Sub Main to see a value created from a sub that it calls then you need to change your subs to functions. There's a difference between a sub and a function, those terms are not interchangeable. The difference is that a function returns a value back to the sub that calls it where a sub does not return anything.

 

Also, it may help you to use the line "Option Explicit" at the very beginning of your rule. This forces all variables to be declared properly or it will throw an error. It makes it easier to diagnose bad variables and is usually recommended for newer programmers. (I use it.)

 

I'm working on rewriting your code for you to use functions and oGage as an array, but I'd really like to combine ApplyGages and DetermineGages into one function. Is there a reason I can't do that? Why are you using two subs now and two sets of variables (oGage and ooGage)?

 

Mike (not Matt) Rattray

Message 9 of 13
mrattray
in reply to: mrattray

While I was waiting on your reply about combining functions, I went ahead and rewrote your code maintaining your current architecture. In addition to changing two subs to functions and changing oGage to an array (the functions are also arrays now) I also changed your error catching statements to use Try Catch statements. They're much easier and more robust then that obsolete COM stuff you were using.

 

Try this out:

 

Sub Main()
Dim oLegShort As Double = Min(G_W,G_H)
Dim oLegLong As Double = Max(G_W,G_H)
Dim oLegLength As Double

Dim oGage() As Double

'Short Leg:
	oLegLength = oLegShort
	'Call DetermineGages sub to set oGage variables:
	oGage = DetermineGages(oLegLength)
	
	Try
	'If gage parameter does not equal true gage, set it equal:
	If Parameter("ShortLegGage") <> oGage(0) Then
		Parameter("ShortLegGage") = oGage(0)
	End If
	'Assume error means gage parameter does not exits. Create and set equal to true gage:
	Catch
		oMyParameter=ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters
		oParameter=oMyParameter.AddByExpression("ShortLegGage", oGage(0), "in")
	End Try
	
	Try
	If Parameter("ShortLegGage1") <> oGage(1) Then
	Parameter("ShortLegGage1") = oGage(1)
	End If
	Catch
	oMyParameter=ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters
	oParameter=oMyParameter.AddByExpression("ShortLegGage1", oGage(1), "in")
	End Try
	
	Try
	If Parameter("ShortLegGage2") <> oGage(2) Then
	Parameter("ShortLegGage2") = oGage(2)
	End If
	Catch
	oMyParameter=ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters
	oParameter=oMyParameter.AddByExpression("ShortLegGage2", oGage(2), "in")
	End Try
	
'Long Leg:
	'[Will repeat above for long leg]
	
End Sub
	
Function ApplyGages(ooGage As Double,ooGage1 As Double,ooGage2 As Double) As Double()
	ApplyGages(0) = ooGage
	ApplyGages(1) = ooGage1
	ApplyGages(2) = ooGage2
End Function 

Function DetermineGages(oLegLength As Double) As Double()
	Select Case oLegLength
		Case 8
			DetermineGages = ApplyGages(4.5,3,3)
		Case 7
			DetermineGages = ApplyGages(4,2.5,3)
		Case 6
			DetermineGages = ApplyGages(3.5,2.25,2.5)
		Case 5
			DetermineGages = ApplyGages(3,2,1.75)
		Case 4
			DetermineGages = ApplyGages(2.5,0,0)
		Case 3.5
			DetermineGages = ApplyGages(2,0,0)
		Case 3
			DetermineGages = ApplyGages(1.75,0,0)
		Case 2.5
			DetermineGages = ApplyGages(1.375,0,0)
		Case 2
			DetermineGages = ApplyGages(1.125,0,0)
		Case 1.75
			DetermineGages = ApplyGages(1,0,0)
		Case 1.5 Or 1.375
			DetermineGages = ApplyGages(0.875,0,0)
		Case 1.25
			DetermineGages = ApplyGages(0.75,0,0)
		Case 1
			DetermineGages = ApplyGages(0.625,0,0)
	End Select
End Function 

 



Mike (not Matt) Rattray

Message 10 of 13
DRoam
in reply to: mrattray

Matt, thanks a lot for taking the time to do that, I appreciate it. I'm looking over the changes you made so I can understand them, and I don't understand what's going on in the ApplyGages function. For example, what exactly does the line

ApplyGages(0) = ooGage

do? I would understand if it said

oGage(0) = ooGage

but... it looks like it's almost a circular reference between the function and itself. What am I misunderstanding? When does the correct value actually get applied to the oGage variables?

 

 

As far as combining the two functions into one, I suppose that could be done in this case, but like I said I'd love to learn how to pass variables between functions like this for cases when things are more complicated and I won't want to re-write the same bit of code over and over again for repetitive tasks. Does this make sense? Honestly when I started learning this stuff it surprised me how difficult it was to do that. I sort of thought that was the essence of programming, to be able to use functions in this manner to perform repetitive operations by taking in certain variables and modifying other variables accordingly. Apparently that's not the case.

Message 11 of 13
mrattray
in reply to: DRoam

No problem, I actually enjoy this stuff!

 

This is why I wanted to combine the functions, because the function "ApplyGages" is redundant.

 

This is where the values finally make their way back to "oGage" in "Sub Main":

oGage = DetermineGages(oLegLength)

 This calls the function "DetermineGages" and says that whatever the result of the function, assign it to "oGage".

 

Here, we are saying the value of "DetermineGages" is whatever "ApplyGages" returns when fed the arguments 4.5, 3, and 3.

Case 8
	DetermineGages = ApplyGages(4.5,3,3)

 

Here, we are assigning the "ooGage" values as the result of "ApplyGages". I call this redundant because the result of "ApplyGages" will always simply be it's inputs.

ApplyGages(0) = ooGage
ApplyGages(1) = ooGage1
ApplyGages(2) = ooGage2

 On second look, I could have written that as:

ApplyGages = ooGage, ooGage1, ooGage2

 

What I wanted to do was:

DetermineGages = 4.5,3,3

 This would eliminate the function "ApplyGages" and simplify everything for us. However, it's not necessary.

 

Moving variables around between functions isn't difficult, you just have to realize that unless you explicitly include that variable in the arguments of the sub or function it won't have access to it. You just need a bit of practice, don't get discouraged.

 

I hope I answered your questions and didn't get you even more confused.

Mike (not Matt) Rattray

Message 12 of 13
DRoam
in reply to: mrattray

No you're definitely helping a lot, thank you.

 

I finally had a chance to try your code and came up with this error:

 

Error on Line 48 : Argument not specified for parameter 'ooGage1' of 'Public Function ApplyGages(ooGage As Double, ooGage1 As Double, ooGage2 As Double) As Double()'.

 

There are two occurances of that error for each line of

 

ApplyGages(*) = ooGage*

 in the ApplyGages function. Do you know what this means?

 

------

 

I've also been experimenting with doing away with the ApplyGages function as you said, by simply stating

 

DetermineGages = *,*,*

 within the Determine Gages fuction for each case, but then I get the error

 

Error on Line 56 : Value of type 'Double' cannot be converted to '1-dimensional array of Double'.

 

for each case. I've been trying to search on how to cast and deal with array variables, but can't find anything useful. Can you (continue to) enlighten me? Thanks again!

Message 13 of 13
MechMachineMan
in reply to: DRoam

Dragging up an old topic here, but I have something to add:

 

To use the same variable across multiple subs you can put the "iLogic" rule inside a class and declare the variables as shared.

See below:

 

Option Compare Text

AddReference "Microsoft.Office.Interop.Excel" 'To use excel

Imports Microsoft.Office.Interop.Excel        'To use excel

'need the class to share variables across subs.
Public Class xlUsage

Shared xlWb As Microsoft.Office.Interop.Excel.Workbook
Shared xlWs As Microsoft.Office.Interop.Excel.WorkSheet
Shared oExcelApp As Microsoft.Office.Interop.Excel.Application

	Sub Main()
		oXLSheet = "Sheet1"

		OpenXL(True)
		xlWs = xlWb.Worksheets(oXLSheet)
		xlWs.Cells.Clear
		
		Dim oDoc As Document = ThisApplication.ActiveDocument
		Dim oSheet As Sheet = oDoc.ActiveSheet
		
		Dim oRow As Integer = 1
		Dim oColumn As Integer = 1

		Dim oSSD As SketchedSymbolDefinition = oDoc.SketchedSymbolDefinitions.Item("REV 1")
		For Each oTextBox In oSSD.Sketch.TextBoxes
			xlWs.Cells(oRow, oColumn).Value = oTextBox.Text
			oColumn = oColumn + 1
		Next
		
		oRow = 2
		oColumn = 1
		
		For Each oSketched In oSheet.SketchedSymbols
			If oSketched.Definition.Name = "REV 1"
				For Each oTextBox In oSketched.Definition.Sketch.Textboxes
					xlWs.Cells(oRow, oColumn).Value = oSketched.GetResultText(oTextBox)
					oColumn = oColumn + 1
				Next
				oRow = oRow + 1
			End If
			oColumn = 1
		Next
			
		Dim lastrow As Integer = xlWs.Cells(xlWs.Rows.Count, 1).End(xlDirection.xlUp).Row
		xlWs.Range("A2:D" & lastrow).Sort(Key1:=xlWs.Range("A2:A" & lastrow), Order1 :=XlSortOrder.xlAscending, Header:=XlYesNoGuess.xlNo, Orientation:=XlSortOrientation.xlSortColumns)			
					
		CloseXL(True)
		OpenXL(True)			
	End Sub

	Sub OpenXL(oMakeVisible As Boolean)	
		Dim oXLWorkBook As String = "C:\Users\Public\Documents\iLogic Buffer File.xlsx"
		
		Try
			oExcelApp = GetObject("", "Excel.Application")
		Catch ex As Exception
			MsgBox("Error opening excel!")
    	End Try

		xlWb = oExcelApp.Workbooks.Open(FileName:=oXLWorkBook)
		oExcelApp.Visible = oMakeVisible
	End Sub
	
	Sub CloseXL(oSaveBool As Boolean)
		xlWB.Close(oSaveBool,,)
    	oExcelApp.Quit
    
    	xlWs = Nothing
    	xlWb = Nothing
    	oExcelApp = Nothing
	End Sub
	
End Class

--------------------------------------
Did you find this reply helpful ? If so please use the 'Accept as Solution' or 'Like' button below.

Justin K
Inventor 2018.2.3, Build 227 | Excel 2013+ VBA
ERP/CAD Communication | Custom Scripting
Machine Design | Process Optimization


iLogic/Inventor API: Autodesk Online Help | API Shortcut In Google Chrome | iLogic API Documentation
Vb.Net/VBA Programming: MSDN | Stackoverflow | Excel Object Model
Inventor API/VBA/Vb.Net Learning Resources: Forum Thread

Sample Solutions:Debugging in iLogic ( and Batch PDF Export Sample ) | API HasSaveCopyAs Issues |
BOM Export & Column Reorder | Reorient Skewed Part | Add Internal Profile Dogbones |
Run iLogic From VBA | Batch File Renaming| Continuous Pick/Rename Objects

Local Help: %PUBLIC%\Documents\Autodesk\Inventor 2018\Local Help

Ideas: Dockable/Customizable Property Browser | Section Line API/Thread Feature in Assembly/PartsList API Static Cells | Fourth BOM Type

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report