ThisApplication.ActiveDocumentType wrong value in call from event

ThisApplication.ActiveDocumentType wrong value in call from event

sebastien_forman
Enthusiast Enthusiast
818 Views
14 Replies
Message 1 of 15

ThisApplication.ActiveDocumentType wrong value in call from event

sebastien_forman
Enthusiast
Enthusiast

Hello,

 

I have a small issue with my code. This code is executed before each saving of an ipt, iam, ipn, or idw file, depending on conditions such as "isDrawing().

 

The code should execute differently depending on the type of file we are dealing with.

However, when the script is launched from an idw, and the script will modify the ipt or iam file via the function "copyIpropValueFromidwToIptIamIpn()", the ipt or iam file is also modified, and therefore the code also executes for it.

The problem is that the function "isDrawing()" always returns "true" at the time of saving the ipt or iam, when it should not be the case.

I suppose this is because the original script call is made from the idw, and ThisApplication.ActiveDocumentType always reports this idw.

I also tried to use the line "ThisApplication.ActiveEditDocument.DocumentType", but without success.

I hope I made myself clear.

In summary, "isDrawing()" always returns "true" even if the script concerns an ipt or iam.

 

Can you help me please?

 

Thank you

 

Sébastien

 

Sub main() 'This Sub is automatically called for each ipt, iam, idw, or ipn just before saving time with trigger event.

	' Check if the active document is a drawing
	If isDrawing() Then
		MsgBox(isDrawing() & "   " & ThisDoc.FileName)
		'Call restorIpropCustom
		'Call FindDepartementIfNotExist
		'Call copyDataFromTitleBlockToIdwIprop
		Call copyIpropValueFromidwToIptIamIpn
		'Call replaceTitleBloc2			
	End If	
	If isIptIamIpn() Then
		MsgBox(isIptIamIpn() & "   " & ThisDoc.FileName)
				
	End If	

End Sub

' Function to check if the active document is a drawing
Function isDrawing()
	If ThisApplication.ActiveDocumentType = DocumentTypeEnum.kDrawingDocumentObject Then
		isDrawing = True
	Else
		isDrawing = False
	End If
End Function

' Function to check if the active document is a drawing
Function isDrawing2() As Boolean
    Try
        If ThisApplication.ActiveEditDocument.DocumentType = DocumentTypeEnum.kDrawingDocumentObject Then
            ' If the active document is a drawing
            EstEnModeMiseEnPlan = True
        Else
            ' If the active document is not a drawing
            EstEnModeMiseEnPlan = False
        End If
    Catch ex As Exception
        MsgBox("An error occurred: " & ex.Message)
        EstEnModeMiseEnPlan = False
    End Try
End Function

' Function to check if the active document is an assembly, part, or presentation
Function isIptIamIpn()
	If ThisApplication.ActiveDocumentType = DocumentTypeEnum.kAssemblyDocumentObject Or ThisApplication.ActiveDocumentType = DocumentTypeEnum.kPartDocumentObject Or ThisApplication.ActiveDocumentType = DocumentTypeEnum.kPresentationDocumentObject Then
		isIptIamIpn = True
	Else
		isIptIamIpn = False
	End If
End Function

Function copyIpropValueFromidwToIptIamIpn
	Dim oDDoc As DrawingDocument = ThisApplication.ActiveDocument
	If oDDoc.AllReferencedDocuments.Count > 0 Then
		'a Drawing can contain more than one 'Model' document, but the first is always used
		Dim oMDoc As Document = oDDoc.AllReferencedDocuments.Item(1)
		If Not iProperties.Value("Project", "Description") = oMDoc.PropertySets.Item("Design Tracking Properties").Item("Description").Value Then 
			oMDoc.PropertySets.Item("Design Tracking Properties").Item("Description").Value = iProperties.Value("Project", "Description")
		End If
	End If
End Function

 

0 Likes
Accepted solutions (2)
819 Views
14 Replies
Replies (14)
Message 2 of 15

Walliguy
Contributor
Contributor

Morning,

 

Your script worked for me, I added a few more details in your message boxes to help determine where the message box was being called. I so added another message box on line 25 to see when the function was called.

 

I also changed the second if to and "Else if", see line 12.

 

 

 

Sub main() 'This Sub is automatically called for each ipt, iam, idw, or ipn just before saving time with trigger event.

	' Check if the active document is a drawing
	If isDrawing() Then
		MsgBox(isDrawing() & " Drawing Caught  " & ThisDoc.FileName)
		'Call restorIpropCustom
		'Call FindDepartementIfNotExist
		'Call copyDataFromTitleBlockToIdwIprop
		'Call copyIpropValueFromidwToIptIamIpn
		'Call replaceTitleBloc2			

	Else If isIptIamIpn() Then
		MsgBox(isIptIamIpn() & " Model or IPN  " & ThisDoc.FileName)
				
	End If	

End Sub

Function copyIpropValueFromidwToIptIamIpn()
	Dim oDDoc As DrawingDocument = ThisApplication.ActiveDocument
	
	If oDDoc.AllReferencedDocuments.Count > 0 Then
		'a Drawing can contain more than one 'Model' document, but the first is always used
		Dim oMDoc As Document = oDDoc.AllReferencedDocuments.Item(1)
		MsgBox(oMDoc.DisplayName)
		If Not iProperties.Value("Project", "Description") = oMDoc.PropertySets.Item("Design Tracking Properties").Item("Description").Value Then 
			oMDoc.PropertySets.Item("Design Tracking Properties").Item("Description").Value = iProperties.Value("Project", "Description")
		End If
	End If
End Function

 

 

 

 

Hope this helps,

Chris

0 Likes
Message 3 of 15

WCrihfield
Mentor
Mentor
Accepted solution

Hi @sebastien_forman.  Try changing 'ThisApplication.ActiveDocument' or 'ThisApplication.ActiveEditDocument' to 'ThisDoc.Document'.  When an iLogic rule was triggered to run by an Event Triggers dialog setting, then the 'ThisDoc.Document' will pretty much always represent the document that the event was triggered by.  It is a pretty dynamic term, and points to different documents in different situations, to ensure the most appropriate document is being worked with.

Edit:  You may also want to eliminate the use of the 'iProperties.Value()' iLogic snippet, in favor of the Inventor API route, which allows you to start from an actual Document object, that way you know which document it will be working with.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 4 of 15

sebastien_forman
Enthusiast
Enthusiast

thank you @WCrihfield , that seem work well now. Can you confirm that this line: 

iProperties.Value("Project", "Part Number")

 is dynamic too? and each call will be in relation of current object call by event? (like ThisDoc.Document)

 

Have a nice day.

 

Sébastien

0 Likes
Message 5 of 15

Walliguy
Contributor
Contributor

@WCrihfield,

 

I think I understand.

 

So because Inventor.ActiveDocument == the document that is being shown in a window, when the OnSave event is raised in any document that requires a save, it uses the ActiveDocument?

 

Thanks for your explanation helped me,

Chris

 

 

0 Likes
Message 6 of 15

WCrihfield
Mentor
Mentor
Accepted solution

Hi @sebastien_forman.  Glad that worked OK for you.  As for the 'iProperties.Value()' snippet, and which document it will target in different situations, I can not be 100% certain, because that aspect of the 'iProperties' (or IiProperties Interface) it is not 'officially' documented very well.  Yes, I believe it will act similarly to the 'ThisDoc' term, but I usually do not fully 'trust' it to, opting for a more 'sure' option, where an actual Document can be specified.  I believe that if it is used within an 'internal' iLogic rule (one that is saved within an Inventor Document), then it will focus on that Document that the rule is saved within, by default, but may focus on another in special situations.  But I believe that if it is used in an external iLogic rule, it will most likely focus on whichever document was 'active' (visibly showing on your screen) when the rule began.  There are ways to force it to focus on a specific document, but those ways are also not very well documented yet.  Therefore, when it is critical, I opt for the Inventor API route.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 7 of 15

sebastien_forman
Enthusiast
Enthusiast

@WCrihfield ,

Thank you for your feedback. I understand that you don't have the information due to lack of documentation. I thought you were an employee of Autodesk... The rule is indeed an external rule and seems to handle the document that calls it by changing "ThisDoc.Document.DocumentType", so it also handles elements not visible in the window, which is what I wanted. The same goes for "iProperties.Value("Project", "Description")". I will use this script carefully to see if it doesn't cause any issues later on. Have a good day.

 

@Walliguy Thank too participate of discution and trying help me.

 

Sébastien

0 Likes
Message 8 of 15

WCrihfield
Mentor
Mentor

The most complex situations to watch out for, is when you are working with an assembly (or possibly a drawing of an assembly), and you are planning on using code means to access and/or edit the other documents being referenced within the assembly (or the models being shown in the drawing).  This is because the main assembly (or the drawing) will usually remain the 'active' document the whole time.  So, you need to be extra sure that each line of code is accessing the correct document.  When using some of the simpler iLogic snippets, you can plainly see that no document is being specified within that line of code, so the question arises...is this line of code going to be accessing the 'active' assembly/drawing, or is it going to be accessing the referenced document I want it to access.  To eliminate that uncertainty in critical working codes in situations like that, I generally prefer to go the Inventor API route, where the code path for accessing things like Parameters or iProperties actually starts from an actual Document object.  Then I know for sure which document that code is working with.

 

There is a relatively new (2020 or 2021, I think) iLogic resource that can help with these situations too though, which will allow you to more confidently use those simpler / shorter iLogic snippets.  When in an iLogic rule window, you can type in "StandardObjectFactory" (without the quotes), then type the dot (.) after it, and a Create method is available.  That Create method wants you to specify a Document as input, then it returns a IStandardObjectProvider Interface object, which can be assigned as the value of a variable.  Then you can use that variable to initiate most of the common iLogic snippets from.  And when you do it that way, all of those snippets you initiate that way, will be focused on that Document object you specified.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 9 of 15

WCrihfield
Mentor
Mentor

No, I am not an employee of Autodesk.  I am just a member of the Autodesk Expert Elite program.  Regular users can get involved with that program, if you meet certain prerequisites, and can keep up with what is required.  It can be pretty rewarding, if that is something that you may be interested in.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 10 of 15

sebastien_forman
Enthusiast
Enthusiast

@WCrihfield,

 

Interresting, i am interested to see an exemple of that if you can.

 

Thank you

 

Sébastien

0 Likes
Message 11 of 15

sebastien_forman
Enthusiast
Enthusiast

Yes, with plenty of free time, we can do lots of nice things.

0 Likes
Message 12 of 15

WCrihfield
Mentor
Mentor

This is just a quickie example I typed up, to show how to use it.  Often not needed in simple internal iLogic rules, but can be helpful in external rules, and rules that deal with referenced documents, and such.

'just one example, among many possible (variable name and value not important)
Dim oDoc As Inventor.Document = ThisDoc.Document
'supply whichever Document you want to be working with here
'then, when you want to be working with another document, set its value using different Document
Dim SOP As IStandardObjectProvider = StandardObjectFactory.Create(oDoc)
Dim oModel As Document = SOP.ThisDrawing.ModelDocument
Dim sPropVal As String = SOP.iProperties.Value("Project", "Description")
Dim oListOfValues As IList = SOP.MultiValue.List("ParamName")
Dim oParamVal As Object = SOP.Parameter("ParamName")
Dim dSMLength As Double = SOP.SheetMetal.FlatExtentsLength
SOP.Component.IsActive("Part1:1") = True
SOP.Constraint.IsActive("Mate:21") = True
SOP.Feature.IsActive("Extrude:1") = True
SOP.Sketch.Redefine("SketchName", "PlaneName", "OriginName", "AxisName")
SOP.WorkPlane.FlipNormal("WPlaneName", "RefAxisName")
'...and so on...

  

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 13 of 15

sebastien_forman
Enthusiast
Enthusiast

waw super, i will try that in my next code if there is too many bug 🙂

0 Likes
Message 14 of 15

sebastien_forman
Enthusiast
Enthusiast

@WCrihfield,

 

Do you thing that this code is correct?

 

Function isDrawing() As Boolean
    Dim oDoc As Inventor.Document = ThisDoc.Document
    Dim SOP As IStandardObjectProvider = StandardObjectFactory.Create(oDoc)
    If SOP.ThisDocument.DocumentType = DocumentTypeEnum.kDrawingDocumentObject Then
        Return True
    Else
        Return False
    End If
End Function
0 Likes
Message 15 of 15

WCrihfield
Mentor
Mentor

That relatively simple example does not seem to be an efficient use of that resource to me.  There are several ways a function like that could be defined / work.  I will show a few alternatives below.

These first two examples ask the user to supply the Document object that should be checked.

Function IsDrawing(oDoc As Inventor.Document) As Boolean
    If oDoc.DocumentType = DocumentTypeEnum.kDrawingDocumentObject Then
        Return True
    Else
        Return False
    End If
End Function

or

Function IsDrawing(oDoc As Inventor.Document) As Boolean
	If TypeOf oDoc Is DrawingDocument Then
		Return True
	Else
		Return False
	End If
End Function

These second two examples do not ask for the Document to be supplied.

Function IsDrawing() As Boolean
	If ThisDoc.Document.DocumentType = DocumentTypeEnum.kDrawingDocumentObject Then
		Return True
	Else
		Return False
	End If
End Function

 

Function IsDrawing() As Boolean
	If TypeOf ThisDoc.Document Is DrawingDocument Then
		Return True
	Else
		Return False
	End If
End Function

 A third option could be to make that 'input' Document object 'Optional', so that you could either supply it, or not supply it.  It would pretty much always be better, and more accurate, to supply the Document object though.  That way you can be sure it is working with the Document that you intend for it to work with.

Function IsDrawing(Optional oDoc As Inventor.Document) As Boolean
	If oDoc Is Nothing Then oDoc = ThisDoc.Document
	If oDoc.DocumentType = DocumentTypeEnum.kDrawingDocumentObject Then
		Return True
	Else
		Return False
	End If
End Function

There are some situations where you may actually want to be working with the 'active' document, even when the 'ThisDoc.Document' term would refer to a different document.

If you are using an external rule, and you want the rule to be able to work on either a part, or drawing, but never on an assembly, then the first thing I would do is use the 'ThisDoc.Document' term to get a reference to Document.  Then, if you really wanted to be super thorough (but I do not normally recommend this), you could use both of the other common Inventor API general terms to get a reference to the Document objects that they return (ThisApplication.ActiveDocument & ThisApplication.ActiveEditDocument).  Then, you could compare all 3 Document objects against each other.  I already described the ThisDoc term quite a bit.  If the other two are different from each other, then you know you are dealing with an odd situation, such as in-place editing a component, within an assembly, because the assembly will be the 'active' one, and the document that the component references will be the 'active edit' one.  Also keep in mind the 'ThisDoc.ModelDocument' term.  If used on a part or assembly, it will return the same as 'ThisDoc.Document', but if used on a drawing, it will return its 'model' document.  However, if used on a drawing, and that drawing does not have any views of models in it yet, it will return 'Nothing'.  However (again), if your drawing is referencing more than one model document directly, then it will return the one being referenced by the first view of a model in the drawing.

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes