How to use a wildcard to a occurrence name with ilogic?

How to use a wildcard to a occurrence name with ilogic?

DeerSpotter
Collaborator Collaborator
2,253 Views
13 Replies
Message 1 of 14

How to use a wildcard to a occurrence name with ilogic?

DeerSpotter
Collaborator
Collaborator

All,

I have a problem, i am targeting components (parts) based off what the mate name is and then running ilogic code to change the parents visibility on or off. 

The Code is run inside a Assembly as an "External Rule"

Here is my Current Code that works, but is not future proof since it still targets a hard coded string name like so:
somenameofpart:1

somenameofpart:2

somenameofpart:3

notice :1, :2, :3

 

here is the family tree of the mates:

image.png

Dim openDoc As Document
openDoc = ThisDoc.Document
Dim docFile As Document 
If openDoc.DocumentType = 12291 Then
	For Each docFile In openDoc.AllReferencedDocuments
		If docFile.DocumentType = 12290 Then
			Dim FNamePos As Long
			FNamePos = InStrRev(docFile.FullFileName, "\", -1)
			Dim docFName As String
			docFName = Right(docFile.FullFileName, Len(docFile.FullFileName) - FNamePos)
			'ShortName = Left(docFName, Len(docFName))
			'MessageBox.Show(ShortName)
			ShortName = Left(docFName, Len(docFName) - 4)
			'MessageBox.Show(ShortName & Right(docFName, Len(docFName) + 2))
			
			Try 
				If Constraint.IsActiveInComponent(ShortName & ":1", "VERTICAL") = True Then
				'do nothing
				Else 
				'turns off component that has Vertical Mate active
					Component.Visible(ShortName & "1") = True
					Constraint.IsActive("VERTICAL")=True
				End If
				
				If Constraint.IsActiveInComponent(ShortName & ":2", "LEFT") = True Then
					Component.Visible(ShortName & "2") = False
					Constraint.IsActive("LEFT")=False
				Else
				'dont try to turn off if you dont need to
				End If
				
				If Constraint.IsActiveInComponent(ShortName & ":3", "RIGHT") = True Then
					Component.Visible(ShortName & "3") = False
					Constraint.IsActive("RIGHT")=False
				Else
				'dont try to turn off if you dont need to
				End If
			Catch
			End Try
			
			ThisDoc.Document.Rebuild()
		End If 
	Next
	
Else
	MessageBox.Show("You must have a valid Assembly document open before using this code!", "File Type Mismatch!",MessageBoxButtons.OK,MessageBoxIcon.Exclamation)
End If

how can i get it to work with targeting a dynamic name a unkown component name that has a mate called:

VERTICAL, LEFT, RIGHT?

i dont want to rely on :1, :2, :3 as a hardcoded statement. 

Thanks

Image and video hosting by TinyPic
..........................................................................................................................
Did you find this reply helpful ? If so please use the Accept as Solution or Kudos button below.
..........................................................................................................................


See My LinkedIn Profile
0 Likes
Accepted solutions (1)
2,254 Views
13 Replies
Replies (13)
Message 2 of 14

richard.joseph.pollak
Advocate
Advocate
Dim oDoc As AssemblyDocument = TryCast(ThisDoc.Document, AssemblyDocument)
Dim compDef As AssemblyComponentDefinition = oDoc.ComponentDefinition

For Each oComp In compDef.Occurrences
	Messagebox.Show(oComp.Name)
	For Each oConstraint In oComp.Constraints
		MessageBox.Show(oConstraint.Name)
	Next
Next

Use this sample code as an example for how to access components and constraints without hard-coding their names.

 

I think you should be able to refactor your code to do what you want.

Message 3 of 14

BrianEkins
Mentor
Mentor

Here's a good post describing some ways to compare two strings using a wildcard.

 

https://stackoverflow.com/questions/37394439/compare-two-strings-with-wildcard

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
Message 4 of 14

DeerSpotter
Collaborator
Collaborator

I am curious like George, why the message box calls out the mates too. 

Image and video hosting by TinyPic
..........................................................................................................................
Did you find this reply helpful ? If so please use the Accept as Solution or Kudos button below.
..........................................................................................................................


See My LinkedIn Profile
0 Likes
Message 5 of 14

BrianEkins
Mentor
Mentor

I don't understand the last question about the message box and mates, and I'm not sure I fully understand the initial question but here's a little function and a test sub that finds an occurrence based on the name of a constraint it contains.  This probably doesn't do exactly what you need but hopefully, it's close.

 

    Private Sub FindOccurenceSample()
        Dim invApp As Inventor.Application = GetObject(, "Inventor.Application")
        Dim asmDoc As AssemblyDocument = invApp.ActiveDocument

        Dim occ As ComponentOccurrence = FindOccurrenceByConstraintName(asmDoc, "VERTICAL")
        If Not occ Is Nothing Then
            occ.Visible = False
        End If
    End Sub

    ' This finds a constraint of the specified name within the first top-level occurrence
    ' in the assembly that a constraint with that name exists.
    Private Function FindOccurrenceByConstraintName(asmDoc As AssemblyDocument, name As String) As ComponentOccurrence
        For Each occ As ComponentOccurrence In asmDoc.ComponentDefinition.Occurrences
            Dim asmComp As AssemblyComponentDefinition = occ.Definition
            Try
                Dim asmConst As AssemblyConstraint = asmComp.Constraints.Item(name)
                Return occ
            Catch ex As Exception
                Return Nothing
            End Try
        Next

        Return Nothing
    End Function
---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
Message 6 of 14

DeerSpotter
Collaborator
Collaborator

@richard.joseph.pollakwrote:
Dim oDoc As AssemblyDocument = TryCast(ThisDoc.Document, AssemblyDocument)
Dim compDef As AssemblyComponentDefinition = oDoc.ComponentDefinition

For Each oComp In compDef.Occurrences
	Messagebox.Show(oComp.Name)
	For Each oConstraint In oComp.Constraints
		MessageBox.Show(oConstraint.Name)
	Next
Next

Use this sample code as an example for how to access components and constraints without hard-coding their names.

 

I think you should be able to refactor your code to do what you want.


Wow, i get how it works, sorry for my stupid comment i made right away. 
This is great!

Image and video hosting by TinyPic
..........................................................................................................................
Did you find this reply helpful ? If so please use the Accept as Solution or Kudos button below.
..........................................................................................................................


See My LinkedIn Profile
0 Likes
Message 7 of 14

richard.joseph.pollak
Advocate
Advocate

@DeerSpotterwrote:

@richard.joseph.pollakwrote:
Dim oDoc As AssemblyDocument = TryCast(ThisDoc.Document, AssemblyDocument)
Dim compDef As AssemblyComponentDefinition = oDoc.ComponentDefinition

For Each oComp In compDef.Occurrences
	Messagebox.Show(oComp.Name)
	For Each oConstraint In oComp.Constraints
		MessageBox.Show(oConstraint.Name)
	Next
Next

Use this sample code as an example for how to access components and constraints without hard-coding their names.

 

I think you should be able to refactor your code to do what you want.


Wow, i get how it works, sorry for my stupid comment i made right away. 
This is great!


I apologize for not explaining my answer more in depth. I was heading out the door to lunch at the time. Glad you were able to make sense of it. I've done a lot of constraint manipulation through the API, so I'll be happy to help if you run into any more issues.

Message 8 of 14

richard.joseph.pollak
Advocate
Advocate

@BrianEkinswrote:

I don't understand the last question about the message box and mates, and I'm not sure I fully understand the initial question but here's a little function and a test sub that finds an occurrence based on the name of a constraint it contains.  This probably doesn't do exactly what you need but hopefully, it's close.

 

    Private Sub FindOccurenceSample()
        Dim invApp As Inventor.Application = GetObject(, "Inventor.Application")
        Dim asmDoc As AssemblyDocument = invApp.ActiveDocument

        Dim occ As ComponentOccurrence = FindOccurrenceByConstraintName(asmDoc, "VERTICAL")
        If Not occ Is Nothing Then
            occ.Visible = False
        End If
    End Sub

    ' This finds a constraint of the specified name within the first top-level occurrence
    ' in the assembly that a constraint with that name exists.
    Private Function FindOccurrenceByConstraintName(asmDoc As AssemblyDocument, name As String) As ComponentOccurrence
        For Each occ As ComponentOccurrence In asmDoc.ComponentDefinition.Occurrences
            Dim asmComp As AssemblyComponentDefinition = occ.Definition
            Try
                Dim asmConst As AssemblyConstraint = asmComp.Constraints.Item(name)
                Return occ
            Catch ex As Exception
                Return Nothing
            End Try
        Next

        Return Nothing
    End Function

Nice example!

 

With the message boxes, I was just trying to give a quick example of how you can anonymously access components and the constraints attached to them via iteration. The code I posted is fairly useless on its own, but throwing some filters inside the for-loops instead of message boxes would be a good way to achieve @DeerSpotter's goal.

0 Likes
Message 9 of 14

DeerSpotter
Collaborator
Collaborator

@richard.joseph.pollakwrote:

@DeerSpotterwrote:

@richard.joseph.pollakwrote:
Dim oDoc As AssemblyDocument = TryCast(ThisDoc.Document, AssemblyDocument)
Dim compDef As AssemblyComponentDefinition = oDoc.ComponentDefinition

For Each oComp In compDef.Occurrences
	Messagebox.Show(oComp.Name)
	For Each oConstraint In oComp.Constraints
		MessageBox.Show(oConstraint.Name)
	Next
Next

Use this sample code as an example for how to access components and constraints without hard-coding their names.

 

I think you should be able to refactor your code to do what you want.


Wow, i get how it works, sorry for my stupid comment i made right away. 
This is great!


I apologize for not explaining my answer more in depth. I was heading out the door to lunch at the time. Glad you were able to make sense of it. I've done a lot of constraint manipulation through the API, so I'll be happy to help if you run into any more issues.


I am running into the issue of how to get it to run on .ipt files only. 

Can you help me so that your snippet when it runs through everything it only shows a message box for part type files only? 

Thanks,
🙂

Image and video hosting by TinyPic
..........................................................................................................................
Did you find this reply helpful ? If so please use the Accept as Solution or Kudos button below.
..........................................................................................................................


See My LinkedIn Profile
0 Likes
Message 10 of 14

richard.joseph.pollak
Advocate
Advocate
Accepted solution

 

'Some quick error handling:
If Not ThisDoc.Document.DocumentType = kAssemblyDocumentObject Then
	MessageBox.Show("Whoops! This only works on assembly documents.", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Hand)
	Return
End If

Dim oDoc As AssemblyDocument = TryCast(ThisDoc.Document, AssemblyDocument)
Dim compDef As AssemblyComponentDefinition = oDoc.ComponentDefinition

For Each oComp In compDef.Occurrences 'Loops through each component in the assembly
	If oComp.Definition.Document.DocumentType = kPartDocumentObject Then 'Filters to check only part documents
		For Each oConstraint In oComp.Constraints 'Loops through the constraints attached to the part
			If oConstraint.Name = "VERTICAL" Or oConstraint.Name = "LEFT" Or oConstraint.Name = "RIGHT" Then 'Filters to constraints for which we're looking
				MessageBox.Show(oComp.Name & ": " & oConstraint.Name)
				'This just announces the name of the component found with the constraint we are looking for. Replace this with your code
			End If
		Next
	End If
Next

It's a bit un-intuitive getting the document object from a component occurrence. I always forget and have to look it up. You have to access the component occurrence's definition property and then the document property of that definition (oComp.Definition.Document).  Take a look at the code above to see how to filter by document type with the Inventor API using conditionals.

 

Message 11 of 14

Hmm,

TryCast(ThisDoc.Document, AssemblyDocument)

is a bit superfluous with the error-check that I added at the beginning. The document will definitely be an AssemblyDocument if we hit this part of the code. It doesn't hurt to leave it like that, but it could be written more succinctly as

Dim oDoc As AssemblyDocument = ThisDoc.Document
Message 12 of 14

Sorry... This probably all should have been one post from me, but I reread your original post and realized that what you're trying to do is fairly simple after filtering is done.

 

This should be a complete solution:

 

'Some quick error handling:
If Not ThisDoc.Document.DocumentType = kAssemblyDocumentObject Then
	MessageBox.Show("Whoops! This only works on assembly documents.", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Hand)
	Return
End If

Dim oDoc As AssemblyDocument = ThisDoc.Document
Dim compDef As AssemblyComponentDefinition = oDoc.ComponentDefinition

For Each oComp In compDef.Occurrences 'Loops through each component in the assembly
	If oComp.Definition.Document.DocumentType = kPartDocumentObject Then 'Filters to check only part documents
		For Each oConstraint In oComp.Constraints 'Loops through the constraints attached to the part
			Select Case oConstraint.Name
			Case "VERTICAL"
				If oConstraint.Suppressed = False Then
					oComp.Visible = True
					oConstraint.Suppressed = True
				End If
			Case "LEFT", "RIGHT"
				If oConstraint.Suppressed = True Then
					oComp.Visible = False
					oConstraint.Suppressed = False
				End If
			Case Else
				'This is where you can put code for what you want to happen to items that don't hit any of your select filters.
				'You can leave the 'Case Else' line out in this case. I just wanted to mention how it can be used.
			End Select
		Next
	End If
Next
Message 13 of 14

DeerSpotter
Collaborator
Collaborator

@richard.joseph.pollakwrote:

Sorry... This probably all should have been one post from me, but I reread your original post and realized that what you're trying to do is fairly simple after filtering is done.

 

This should be a complete solution:

 

'Some quick error handling:
If Not ThisDoc.Document.DocumentType = kAssemblyDocumentObject Then
	MessageBox.Show("Whoops! This only works on assembly documents.", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Hand)
	Return
End If

Dim oDoc As AssemblyDocument = ThisDoc.Document
Dim compDef As AssemblyComponentDefinition = oDoc.ComponentDefinition

For Each oComp In compDef.Occurrences 'Loops through each component in the assembly
	If oComp.Definition.Document.DocumentType = kPartDocumentObject Then 'Filters to check only part documents
		For Each oConstraint In oComp.Constraints 'Loops through the constraints attached to the part
			Select Case oConstraint.Name
			Case "VERTICAL"
				If oConstraint.Suppressed = False Then
					oComp.Visible = True
					oConstraint.Suppressed = True
				End If
			Case "LEFT", "RIGHT"
				If oConstraint.Suppressed = True Then
					oComp.Visible = False
					oConstraint.Suppressed = False
				End If
			Case Else
				'This is where you can put code for what you want to happen to items that don't hit any of your select filters.
				'You can leave the 'Case Else' line out in this case. I just wanted to mention how it can be used.
			End Select
		Next
	End If
Next




First off: 
Can i please tell you how amazing you are at coding?

Second:

We are almost there, i don't want to turn off the visibility or suppress the constraints themselves, rather use the constraint name to find the component it is related to and then turn the visibility of that component off or on. 

I want to stay away from suppressing anything, only visibility. (the dimension in the .idw then remember where they are attached if visibility is turned off or on.)

Image and video hosting by TinyPic
..........................................................................................................................
Did you find this reply helpful ? If so please use the Accept as Solution or Kudos button below.
..........................................................................................................................


See My LinkedIn Profile
0 Likes
Message 14 of 14

richard.joseph.pollak
Advocate
Advocate

Aww shucks, thanks. I've been messing with iLogic and the Inventor API for about 5 years now, struggling and using resources like these forums. It mostly takes practice and the stubbornness to not give up on an impossible problem. If you want to progress quickly, I recommend taking community college courses if you have the opportunity. iLogic uses Visual Basic. I also like C#, but there isn't as much sample code for the Inventor API in C#.

 

As far as the rest of your solution goes, you can take out the parts that change the suppression state of the constraints and modify the visibility adjustments to match what you're looking for. If you want to make this more modular, you could add a user input dialog to ask for the constraint name and another message box later on that asks yes/no to whether or not you want the component to be visible (It would definitely help to display the name of the component in the message box at that point).

 

If you haven't already, I suggest stepping through the solution I wrote and making sure you understand what is happening at each step. This is a good representation of what the majority of my iLogic code looks like. Usually the way to find something with code in Inventor involves writing some kind of loop to search through different objects.

 

I've done a lot of copying and pasting code over the years. It's a good way to learn if you also work through and modify that code because then you have to actually figure out how it works and how to implement similar solutions for your own purposes.

 

Good luck!