Run macro in assembly occurrences

Run macro in assembly occurrences

isidro.nunez
Contributor Contributor
3,619 Views
26 Replies
Message 1 of 27

Run macro in assembly occurrences

isidro.nunez
Contributor
Contributor

Hello again,

 

I'm trying to create a rule which can be run from an assembly and update/create all the ilogics of each part in that assembly. I have a macro that works fine when I open a part one by one. This macro creates or updates all the ilogic rules, parameters and iproperties needed, no problem here.

 

The problem comes when I try to run a simple rule from an assembly and iterate through all the part or occurrecces.

 

This code is from hoppend.nl, I simply modified it a bit.

Sub Main()
'Define the Assembly Document
Dim oDoc As AssemblyDocument
Dim RuleName As String = "Check"

' check if active document is an assembly
Try
	oDoc = ThisApplication.ActiveDocument
Catch
	MessageBox.Show("Please run on assembly", "Run Rule")
End Try

Dim oOcc As ComponentOccurrence

GoThrough:
For Each oOcc In oDoc.ComponentDefinition.Occurrences
		'Get Document from Occurrence
		Dim oOccDoc As Document
		oOccDoc = oOcc.Definition.Document

		'Check if document is a part
		If oOccDoc.DocumentType = DocumentTypeEnum.kPartDocumentObject Then

			oOccDoc = oOcc.Definition.Document
			Try
			InventorVb.RunMacro("Default", "Importar_ilogic", "Importar_ilogic")
			iLogicVb.RunRule(oOccDoc.DisplayName, RuleName)
			'MessageBox.Show("Rule run in: " & oOccDoc.DisplayName, "Message for debugging purposes")
			Catch
				'MessageBox.Show("Rule not present in: " & oOccDoc.DisplayName, "Message for debugging purposes")
			End Try
		'if the document is an assembly we need to run the same code in each occurrence of that assembly (we uses a goto function)
		Else If oOccDoc.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject	Then
			oDoc = oOccDoc
			GoTo GoThrough
		End If
Next

End Sub

 

And I also tried this code (just ignore the vendor check):

 

Dim openDoc As Document
openDoc = ThisDoc.Document

Dim docFile As Document

If openDoc.DocumentType = 12291 Then
On Error Resume Next

	For Each docFile In openDoc.AllReferencedDocuments
		
		If docFile.DocumentType = 12290 Then
			
			prov_data = iProperties.Value(docFile.DisplayName, "Project", "Vendor")
			
			If prov_data = "Prov1" Then
				
				InventorVb.RunMacro("Default", "Importar_ilogic", "Importar_ilogic")
				'iLogicVb.RunRule("PartA:1", "ruleName")
			End If
		End If 
	Next
End If 

 

Any idea how I can solve this?

Thank you a lot in advance.

0 Likes
Accepted solutions (2)
3,620 Views
26 Replies
Replies (26)
Message 2 of 27

WCrihfield
Mentor
Mentor

Have you tried running an empty rule with just your RunMacro line in it, to make sure you're accessing the macro correctly?

InventorVb.RunMacro("Default", "Importar_ilogic", "Importar_ilogic")

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 3 of 27

tonythm
Advocate
Advocate

Hello @isidro.nunez 

 

You can try with excel vba, them will quickly and easier.

Sub UpdateParameterPartInAssy()
    Dim oWkbk As Workbook
    Set oWkbk = ThisWorkbook
    Dim oSheet As Worksheet
    Set oSheet = oWkbk.ActiveSheet
    Dim oInv As Inventor.Application
    Set oInv = GetObject(, "Inventor.Application")
    'Define sheet name where information resides
    Dim sSheetName As String
    sSheetName = "Sheet1"
    Dim oAssy As AssemblyDocument
    Set oAssy = oInv.ActiveDocument
    Dim sParamRange As String
        sParamRange = "A2:A20"
    Dim oDoc As Document
    For Each oDoc In oAssy.AllReferencedDocuments
        If oDoc.DocumentType = kPartDocumentObject Then
            Dim oPartDoc As PartDocument
            Set oPartDoc = oDoc
            Dim oUserParams As UserParameters
            Set oUserParams = oPartDoc.ComponentDefinition.Parameters.UserParameters
            Dim oUserParam As UserParameter
            Dim oPartNumProperty As Property
            Set oPartNumProperty = oDoc.PropertySets.Item("Design Tracking Properties").Item("Part Number")
            For Each oCell In oSheet.Range(sParamRange)
                For Each oUserParam In oUserParams
                    If oCell.Value = oPartNumProperty.Value Then
                        If Range("B1").Value = oUserParam.Name Then
                            oUserParam.Expression = oCell.Offset(0, 1).Value & oCell.Offset(0, 3).Value
                        End If
                    End If
                Next
            Next
        End If
    Next
End Sub
Message 4 of 27

isidro.nunez
Contributor
Contributor

Hi @WCrihfield , I have tried that single line in a part and is working. However, when executed in the codes I posted before, the macro seems it's runing at the assembly level. Any way to force a macro to run in an assembly occurrence?

 

Thanks

0 Likes
Message 5 of 27

marcin_otręba
Advisor
Advisor

when you want to use:

iLogicVb.RunRule("PartA:1", "ruleName")

 "PartA:1" - it is occurrence name inside assembly from wchich you run rule.

so in your code you should change:

iLogicVb.RunRule(oOccDoc.DisplayName, RuleName)

to

iLogicVb.RunRule(oOcc.Name, RuleName)

and it should be ok.

 

Hi, maybe you want to vote my:

Ideas

or check my apps:

DrawingTools   View&ColoringTools   MRUFolders

Message 6 of 27

isidro.nunez
Contributor
Contributor

Hi @tonythm , thanks for the code, but how I use it in my case? I have an unknown number of components in each assembly, and in some case, there are auxiliary sub-assemblies. I need to run a macro that is working right now and run another ilogic rule after the macro run.

 

Thank you

0 Likes
Message 7 of 27

isidro.nunez
Contributor
Contributor

Thank you @marcin_otręba , I fix that but the InventorVb.RunMacro is still running in assembly level, so the rule is not in the occurrence. Thats why I need to run the macro before.

I have pieces without ilogic rules on them, so I need to create them with that macro.

 

 

 

 

0 Likes
Message 8 of 27

marcin_otręba
Advisor
Advisor

what this macro actually do ?

Hi, maybe you want to vote my:

Ideas

or check my apps:

DrawingTools   View&ColoringTools   MRUFolders

Message 9 of 27

marcin_otręba
Advisor
Advisor

Check this one:

https://adndevblog.typepad.com/manufacturing/2015/11/pass-parameters-to-a-vba-macro-from-an-ilogic-r...

 

you can have parameter doc as document in your macro and pass it to it using oocc.definition.document.

Hi, maybe you want to vote my:

Ideas

or check my apps:

DrawingTools   View&ColoringTools   MRUFolders

Message 10 of 27

isidro.nunez
Contributor
Contributor

@marcin_otrębathe macro does the following:

-Read the rules .txt files from a server.

-Create iLogic rules in the part and paste the codes from the server. If there was rules, it updates them.

-Create the parameters needed for the imported rules.

-Set the event triggers for all the rules as needed.

 

Thank you

 

0 Likes
Message 11 of 27

isidro.nunez
Contributor
Contributor

I will try this, thanks!

0 Likes
Message 12 of 27

tonythm
Advocate
Advocate

Hi @isidro.nunez 

 

You should be know Part Number of part in Assy. You place them into new file assy(include only part) for refer to input parameter. After that use excel file run macro.

Excel vba control everything you need.

0 Likes
Message 13 of 27

_dscholtes_
Advocate
Advocate

I removed some code for clarity and it quickly shows this code will not do what you want it to do: process all components in the assembly (even sub-assemblies).

 

Sub Main()

GoThrough:
For Each oOcc In oDoc.ComponentDefinition.Occurrences

    'Get Document from Occurrence
    Dim oOccDoc As Document
    oOccDoc = oOcc.Definition.Document

    'Check if document is a part
    If oOccDoc.DocumentType = DocumentTypeEnum.kPartDocumentObject Then
	oOccDoc = oOcc.Definition.Document
        <do something>

    'if the document is an assembly we need to run the same code in each occurrence of that assembly (we uses a goto function)
    Else If oOccDoc.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
        oDoc = oOccDoc
        GoTo GoThrough
    End If
Next

End Sub

 

Lets say halfway through processing the occurrences in your top assembly, you find an occurrence representing a sub-assembly. Through the lines 'oDoc = oOccDoc' and 'Goto GoThrough' you think you continue with the sub assembly, but even if that would happen, there is no code to return back to the top assembly, meaning the occurrences below the sub-assembly in the top assembly are never processed.

I deliberately stated 'you think' and 'even if that would happen' because what actually happens is that the line 'oDoc = oOccDoc' messes up the loop created by 'For Each oOcc In oDoc.ComponentDefinition.Occurrences'.

I wonder why you want to go through all the occurrences and get their documents when it's possible to go through all documents directly. You can read a clear article about accessing assembly components, including example code, by Brian Ekins here. It has helped me a lot.

 

 

 

Message 14 of 27

isidro.nunez
Contributor
Contributor

Hi @_dscholtes_ , as I said before, that code is from hoppend.nl , I just modified the minimun. I see the problem, but right now it's not running the macro, the main task of these rules.

 

If you look at my original post, you can see that I have used both, occurrences and documents in assembly, but the macro is not running on part level, only on assembly level.

 

I will try to modify the macro as suggested by @marcin_otręba 

 

Thank you

0 Likes
Message 15 of 27

WCrihfield
Mentor
Mentor

You may need to change your macro from using ThisApplication.ActiveDocument to ThisDoc.Document.

Or perhaps you need to modify your Macro to accept a variable, then pass the part document to the Macro as you would a reference within a Sub or Function.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 16 of 27

isidro.nunez
Contributor
Contributor

Hi @WCrihfield , when I change ThisApplication.ActiveDocument to ThisDoc.Document, it gives me an error, "ThisDoc is not defined"

Option Explicit

    Sub Importar_ilogic()
    
    Dim i As Object
    Set i = GetiLogicAddin(ThisApplication)
 
    Dim oDoc As Document
    Set oDoc = ThisDoc.Document
        
    Call Parametros
     <here the macro call other subs and functions>

   End Sub

 

I had before this code:

    Dim oDoc As Inventor.Document
    Set oDoc = ThisApplication.ActiveDocument

 

Thank you

0 Likes
Message 17 of 27

_dscholtes_
Advocate
Advocate

@isidro.nunez ThisDoc is used in iLogic (rules), not in VBA (macro). Your original code using ThisApplication.ActiveDocument is correct.

0 Likes
Message 18 of 27

isidro.nunez
Contributor
Contributor

Hi @_dscholtes_ , I just saw it in the help:

Screenshot_1.png

I tried a few week before to do it with iLogic, but I couldn't manage to create rules.

Thank you

 

0 Likes
Message 19 of 27

WCrihfield
Mentor
Mentor

That's right. For some reason I was thinking if your Macro was a simple one that is just running some other external iLogic rules. My mistake.  But the second suggestion is still valid.

Can you share your other Macro codes here so we can see the full picture of what's going on.

We can most likely find a way to keep it all either in iLogic or all in VBA, to make it simpler for you.

Or, if sharing the code isn't possible, due to privacy or proprietary info concerns, you may be able to create a very simplified assembly, iLogic rule, & macro that we can all use to test, as a proof of concept.

I know you can pass variables and values back and forth between iLogic rules, between VBA macros. and between rules & macros.

Otherwise, I'm not sure how your macro can know which specific part within your active assembly you want it to run on. 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 20 of 27

_dscholtes_
Advocate
Advocate

@isidro.nunez If I understand correctly, you have a part file with a rule in it. You don't want to open the part file to run the rule. You want to open an assembly containing that part and have a macro run this rule.

This works for me:

Private Sub RunPartRule()

    'Set reference to open document
    Dim oDoc As Document
    Set oDoc = ThisApplication.ActiveEditDocument
    
    'Check if it's an assembly. If so, quit
    If Not oDoc.DocumentType = kAssemblyDocumentObject Then Exit Sub
    
    'Initiate the iLogic component (required to run an rule)
    Dim iLogicAuto As Object
    Set iLogicAuto = GetiLogicAddin(ThisApplication)
    If (iLogicAuto Is Nothing) Then Exit Sub
    
    'Declaration
    Dim oRefDoc As Document
    
    'Go through each document in the assembly document
    For Each oRefDoc In oDoc.ReferencedDocuments
    
        'Check if it's a part document
        If oRefDoc.DocumentType = kPartDocumentObject Then
        
             'Run the rule named "Rule0" from within the part document
             iLogicAuto.RunRule oRefDoc, "Rule0"
        End If
    Next

End Sub

 

The above code requires the following sub

Public Function GetiLogicAddin(oApplication As Inventor.Application) As Object
    Dim addIn As ApplicationAddIn
    On Error GoTo NotFound
    Set addIn = oApplication.ApplicationAddIns.ItemById("{3bdd8d79-2179-4b11-8a5a-257b1c0263ac}")
    If (addIn Is Nothing) Then Exit Function
    addIn.Activate
    Set GetiLogicAddin = addIn.Automation
    Exit Function
NotFound:
End Function

 

When I run the macro "RunPartRule" in my openend test assembly, it successfully runs the rule "Rule0" which is in my test part file.

 

So, this code only processes the open assembly. It doesn't process sub assemblies. For this to happen, you need a recursive function. You can find an example in the link I posted earlier, but recursive functions have been discussed in various blogs and posts. Or just ask any of the helpful guys here.