Use ThisDoc.Document within a VB Class?

Use ThisDoc.Document within a VB Class?

DRoam
Mentor Mentor
2,068 Views
18 Replies
Message 1 of 19

Use ThisDoc.Document within a VB Class?

DRoam
Mentor
Mentor

I'm trying to write a function within Class that can either work on a specified document (if one is supplied) or the current document (if no document is supplied). I can put the exact same function in the rule space and it works perfectly.

 

However, when I try and use the function within my Class, I get a "Reference to a non-shared member requires an object reference" compile error on the ThisDoc.Document line.

 

This is how I'm trying to use the class:

 

 

Sub Main()
	MessageBox.Show(TestFun())
	
	MessageBox.Show(TestClass.TestFun(ThisDoc.Document))
	
        'The following line will not work unless commented-out line within TestClass can be made to work:
	'MessageBox.Show(TestClass.TestFun())
End Sub

Function TestFun(Optional oDoc As Inventor.Document = Nothing)
	If oDoc Is Nothing Then oDoc = ThisDoc.Document
	
	Return oDoc.DisplayName
End Function

Class TestClass
	Shared Function TestFun(Optional oDoc As Inventor.Document = Nothing)
		'If oDoc Is Nothing Then oDoc = ThisDoc.Document
		
		Return oDoc.DisplayName
	End Function
End Class

 

Is it possible for ThisDoc.Document to work within a VB Class?

 

0 Likes
Accepted solutions (1)
2,069 Views
18 Replies
Replies (18)
Message 2 of 19

philip1009
Advisor
Advisor

Is this for VBA or iLogic?  I think ThisDoc is an iLogic snippet that can't be used outside of iLogic rules.

0 Likes
Message 3 of 19

DRoam
Mentor
Mentor

Sorry, I should have mentioned that. This is an iLogic rule.

0 Likes
Message 4 of 19

philip1009
Advisor
Advisor

Were you successful putting other classes outside of Sub Main in the past?  I think iLogic rules are declared as classes themselves and in order to add more classes in the same rule you have to put the main rule containing Sub Main and the related subs and functions under Class ThisRule and End Class like below:

 

SyntaxEditor Code Snippet

Class ThisRule
	Sub Main
		
	End Sub
	Function A1
		
	End Function
End Class
Class NewClass End Class

 I also think outside of Sub Main you can't use iLogic snippets.  But I've only used class functions to declare variables shared between subs and functions, I haven't needed to add more classes to the same rule since it's typically easier to just make more iLogic rules and use either Parameters or Shared Variables to share info with those other rules.

0 Likes
Message 5 of 19

DRoam
Mentor
Mentor

@philip1009 wrote:

Were you successful putting other classes outside of Sub Main in the past?

...

I also think outside of Sub Main you can't use iLogic snippets.


Answer is yes to the first part, and no to the second. The code in my OP is actually functioning code, and it both includes a class outside of the Main sub, and uses iLogic methods outside of the Main sub (i.e. ThisDoc in the TestFun function).

 

The only thing I'm having trouble with is using ThisDoc within the Class itself.

 


@philip1009 wrote:

But I've only used class functions to declare variables shared between subs and functions, I haven't needed to add more classes to the same rule since it's typically easier to just make more iLogic rules and use either Parameters or Shared Variables to share info with those other rules.


I've seen Classes used to share variables between subs and functions before, but I think the more proper way to do that is to declare the variables as Private variables, just after the Main sub. Then you can share them between subs and functions.

 

In this case I'm trying to use Classes as intended -- as a definition of a new object type with its own variables, properties, methods, etc. It just so happens that in one of the methods for this Class, I want to be able to get the current Document object if necessary.

0 Likes
Message 6 of 19

DRoam
Mentor
Mentor

Bump... any more suggestions?

0 Likes
Message 7 of 19

philip1009
Advisor
Advisor

Sorry, that was all I had, I don't use VB or any coding outside of iLogic, so using multiple classes is a foreign concept for me right now.  Unfortunately there's no real good documentation of iLogic that I've found to determine exactly what can and can't be done between iLogic and regular VB, and what kind of changes need to be done to use certain VB inside of iLogic.  I'd say the best thing to do is spread the different classes into different rules that are suppressed and called on by one or a few central rules.

0 Likes
Message 8 of 19

HermJan.Otterman
Advisor
Advisor

try using : "public class" and "public sub" instead of just "Class" and "sub"

If this answers your question then please select "Accept as Solution"
Kudo's are also appreciated Smiley Wink

Succes on your project, and have a nice day

Herm Jan


0 Likes
Message 9 of 19

clutsa
Collaborator
Collaborator

This types out like it doesn't work but seems to... I don't know that my "ActiveDocument" is really the same as "ThisDoc.Document" but it should put you closer...

Sub Main()
	MessageBox.Show(TestFun())
	
	MessageBox.Show(TestClass.TestFun(ThisDoc.Document))
	
        'The following line will not work unless commented-out line within TestClass can be made to work:
	MessageBox.Show(TestClass.TestFun())
End Sub

Function TestFun(Optional oDoc As Inventor.Document = Nothing)
	If oDoc Is Nothing Then oDoc = ThisDoc.Document
	
	Return oDoc.DisplayName
End Function

Class TestClass
	Shared Function TestFun(Optional oClassDoc As Inventor.Document = Nothing)
		If oClassDoc Is Nothing Then 
			Dim myApp As Inventor.Application = GetObject(, "Inventor.Application")
			oClassDoc = myApp.ActiveDocument
		End If
		
		Return oClassDoc.DisplayName
	End Function
End Class
If I've helped you, please help me by supporting this idea.
Mass Override for Each Model State

Custom Glyph Icon for iMates

Message 10 of 19

MjDeck
Autodesk
Autodesk

The standard iLogic objects are defined only in the default class, or the first class in the rule. (The first class might be a default class which contains Sub Main).

To use iLogic objects in another class, you can make a copy of them. Here's a sample.

In 2018.2 and later, you can see the types of the predefined objects by hovering over them in the rule editor. They are also listed in the online help.

Sub Main()
TestClass.ThisDoc = ThisDoc
TestClass.ThisApplication = ThisApplication

MessageBox.Show(TestClass.TestFun())	

' Clear the memory:
TestClass.ThisDoc = Nothing
TestClass.ThisApplication = Nothing

End Sub

Class TestClass
Shared Property ThisDoc As ICadDoc
Shared Property ThisApplication As Inventor.Application	

Shared Function TestFun(Optional oDoc As Inventor.Document = Nothing)
Dim sv = ThisApplication.SoftwareVersion
If oDoc Is Nothing Then oDoc = ThisDoc.Document

Return oDoc.DisplayName
End Function
End Class

Mike Deck
Software Developer
Autodesk, Inc.

Message 11 of 19

clutsa
Collaborator
Collaborator

I was trying to come up with something like that but couldn't figure out how. I was still trying to use the GetObject and get the ICadDoc. Thank you so much for sharing!

 

What's with ...

Dim sv = ThisApplication.SoftwareVersion

I don't see sv used anywhere else in the code. 

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

Custom Glyph Icon for iMates

0 Likes
Message 12 of 19

MjDeck
Autodesk
Autodesk

@clutsa, you're right: sv is not actually being used for anything. It just demonstrates that the ThisApplication object is available in that class.


Mike Deck
Software Developer
Autodesk, Inc.

0 Likes
Message 13 of 19

DRoam
Mentor
Mentor

I'd forgotten to come back to this thread, but I found a couple methods that I think are the simplest and closest to what I was trying to do. Both of them allow me to use ThisDoc and ThisApplication in my custom class (or multiple custom classes) without having to pass them to each class first. This is accomplished by creating private shared variables in the main rule class (after Sub Main), and initializing those first-thing within Sub Main. This allows any class within the rule access to those variables.

 

This first version is simpler but requires replacing any reference to ThisDoc within the custom class with "_ThisDoc" (with an underscore at the beginning):

 

Sub Main()
	_ThisDoc = ThisDoc
	_ThisApplication = ThisApplication
	
	MessageBox.Show(TestFun())
	
	MessageBox.Show(TestClass.TestFun(ThisDoc.Document))
	
    'The following line now works:
	MessageBox.Show(TestClass.TestFun())
End Sub

Private Shared _ThisDoc As ICadDoc
Private Shared _ThisApplication As Inventor.Application

Function TestFun(Optional oDoc As Inventor.Document = Nothing)
	If oDoc Is Nothing Then oDoc = ThisDoc.Document
	
	Return oDoc.DisplayName
End Function

Class TestClass
	Shared Function TestFun(Optional oDoc As Inventor.Document = Nothing)
		If oDoc Is Nothing Then oDoc = _ThisDoc.Document
		
		Return oDoc.DisplayName
	End Function
End Class

The second version adds a bit more overhead within the custom class itself, but allows you to simply use "ThisDoc" like normal (if that's important):

Sub Main()
	_ThisDoc = ThisDoc
	_ThisApplication = ThisApplication
	
	MessageBox.Show(TestFun())
	
	MessageBox.Show(TestClass.TestFun(ThisDoc.Document))
	
    'The following line now works:
	MessageBox.Show(TestClass.TestFun())
End Sub

Private Shared _ThisDoc As ICadDoc
Private Shared _ThisApplication As Inventor.Application

Function TestFun(Optional oDoc As Inventor.Document = Nothing)
	If oDoc Is Nothing Then oDoc = ThisDoc.Document
	
	Return oDoc.DisplayName
End Function

Class TestClass
	Private Shared ThisDoc As ICadDoc
	
	Shared Sub New()
		ThisDoc = _ThisDoc
	End Sub
	
	Shared Function TestFun(Optional oDoc As Inventor.Document = Nothing)
		If oDoc Is Nothing Then oDoc = ThisDoc.Document
		
		Return oDoc.DisplayName
	End Function
End Class

The second version is handy if you want to be able to easily copy/move code between regular functions and functions within classes. If that's not important, then the first version allows for a few less lines in each custom class.

 

Hope this is helpful to others as well. Thanks all for the help getting to this point.

0 Likes
Message 14 of 19

johnster100
Collaborator
Collaborator

Hi,

I'm doing something similar, but I'd like to be able use parameters within the different classes. I created my own forum thread here:

https://forums.autodesk.com/t5/inventor-customization/parameter-in-ilogic-classes/td-p/9867029

 

before I found this one. 

 

Any help would be appreciated,

thanks,

John

0 Likes
Message 15 of 19

DRoam
Mentor
Mentor
Accepted solution

For anyone else looking to do this, I recently started using what I think is an even simpler way to use iLogic functions in custom classes.

 

Basically, if you have any sub-classes in your rule and want to use "ThisDoc", "Parameter(), etc. inside them, you need to do three things:

 

  1. Add the "ClassHelper" class (shown below) outside of "Sub Main".
  2. Add the "ClassHelper.ParentRule = Me" line at the very top of "Sub Main".
  3. Add the "Inherits ClassHelper" line at the very top of each sub-class.

And that's it. Now helpful iLogic features like "ThisApplication", "ThisDoc", and Parameter()" will work in your sub-classes! This could be very handy if you don't want to take the time to implement your own "straight-API" version of those functions. (Unfortunately, the "blue parameters" still won't work in sub-classes, but at least it's better than nothing.)

 

Sub Main
	ClassHelper.ParentRule = Me

	' Call CustomClass.TestParam ' (Must have parameter called "Test" to use)
	Call AnotherClass.ShowInfo
End Sub

Public Class CustomClass
	Inherits ClassHelper

	Public Shared Sub TestParam()
		MsgBox(Parameter("Test"))
	End Sub
End Class

Public Class AnotherClass
	Inherits ClassHelper

	Public Shared Sub ShowInfo()
		MsgBox(ThisDoc.Document.DisplayName)
		MsgBox(ThisApplication.Documents.Count)
	End Sub
End Class

Public MustInherit Class ClassHelper
	Public Shared ParentRule As ThisRule

	Public ReadOnly Shared Property ThisApplication As Inventor.Application
		Get
			Return ParentRule.ThisApplication
		End Get
	End Property

	Public ReadOnly Shared Property ThisDoc As ICadDoc
		Get
			Return ParentRule.ThisDoc
		End Get
	End Property

	Public ReadOnly Shared Property Parameter As IParamDynamic
		Get
			Return ParentRule.Parameter
		End Get
	End Property
End Class

 

PS, You can actually add other iLogic functions like GoExcel, Logger, ThisAssembly, etc., but from my testing it seems those may sometimes cause errors if the iLogic system doesn't think they're applicable to the current rule. But it's probably safe to add them on an as-needed basis.

Message 16 of 19

johnster100
Collaborator
Collaborator

thanks,

that helps a lot 🙂

0 Likes
Message 17 of 19

johnster100
Collaborator
Collaborator

Hi,

I have one more issue with this 😞

 

I would like to keep my classes in a separate rule with the straight vb code option set so that multiple rules can call these classes.  I then use the AddVbRule option in the other rules to access these variables / functions.

 

The problem is the line below no longer works:

Public Shared ParentRule As ThisRule

The rule no longer has the class ThisRule (or at least I think that's what's happening) as I have set the rule to straight vb code. 

 

Is it possible to make this work flow work?

 

I've attached an example part which explain better what I'm trying to achieve.

 

thanks again,

John

 

0 Likes
Message 18 of 19

MjDeck
Autodesk
Autodesk

@johnster100 , we might be able to improve this in a future release. But for now I would recommend changing the code so that you don't need ThisRule. You have to assign the properties one by one, but you can still inherit from a base class.
Here's a sample test rule:

AddVbRule "Classes"
Sub Main
	InitializeClassHelper()
	' Call CustomClass.TestParam ' (Must have parameter called "Test" to use)
	Call AnotherClass.ShowInfo
End Sub
Sub InitializeClassHelper
	ClassHelper.ThisDoc = ThisDoc
	ClassHelper.ThisApplication = ThisApplication
End Sub

And the Classes rule:

Imports Inventor

Public Class CustomClass
	Inherits ClassHelper

	Public Shared Sub TestParam()
		MsgBox(Parameter("Test"))
	End Sub
End Class

Public Class AnotherClass
	Inherits ClassHelper

	Public Shared Sub ShowInfo()
		MsgBox(ThisDoc.Document.DisplayName)
		MsgBox(ThisApplication.Documents.Count)
	End Sub
End Class

Public Class ClassHelper
	Public Shared Property ThisApplication As Inventor.Application
	Public Shared Property ThisDoc As ICadDoc
	Public Shared Property Parameter As IParamDynamic	
End Class

 


Mike Deck
Software Developer
Autodesk, Inc.

Message 19 of 19

johnster100
Collaborator
Collaborator

thanks for that, I've implemented and it's working well. 

 

0 Likes