Loop through subassemblies and suppress components by search string

Loop through subassemblies and suppress components by search string

karl-andreas_gross
Contributor Contributor
1,024 Views
9 Replies
Message 1 of 10

Loop through subassemblies and suppress components by search string

karl-andreas_gross
Contributor
Contributor

Dear Community,

i tried to create a code that does the following:

1) define a new model state in an assembly

2) Define a search string

3) Loop through an assembly and find all components that do NOT contain the search string.

4) suppress all found components regardless of their parent

 

If followed this topic:

Solved: Create a Model State and suppres parts based om modelbrowser name - Autodesk Community

 

 

But i could not figure out on how to deal with the case when an sub-assembly has a component name that does NOT include the search string, but included components that DO have the search string in their name.  Means, the subassembly has to active, even if its component name includes the "wrong" search string.

Example: Searchstring is "shaft" --> all components that do not contain the string "shaft" should be suppressed. But there is a subassembly called "Group", and that subassembly contains a part called "shaft". in that case, the subassembly should remain active in order to have its children active, even though it should be suppressed because of its name. 

i got this so far (which not works for the problem mentioned above):

Dim oAsmDef As AssemblyDocument
doc = ThisDoc.Document


myCount = 0 'create a counter
Dim searchTerm As String = "___"

Dim oComp As ComponentOccurrence
oComps = doc.ComponentDefinition.Occurrences


For Each oComp In oComps
	oName = oComp.Name
	If oName.Contains(searchTerm)
	myCount = myCount+1 'if found increment counter by 1
	Else
		oComp.Suppress
	End If
Next

If myCount = 0
	MessageBox.Show("None Found", "None Found Message")
	Else
		MessageBox.Show(myCount & " of " & searchTerm & " found", "Found This Many")
End If



 

Are there any ideas on how to proceed? Thank you in advance! 

0 Likes
Accepted solutions (3)
1,025 Views
9 Replies
Replies (9)
Message 2 of 10

BM_Ashraf
Advocate
Advocate

Are you looking for leave only the parts that contain that strin name?

If this solved your problem, or answered your question, please click ACCEPT SOLUTION.

Blue Mech

Add-ins for Inventor!

0 Likes
Message 3 of 10

karl-andreas_gross
Contributor
Contributor

Hi Ashraf,

yes, that is the case. The Search string should be the filter for what is left to active. But both parts and assemblies can contain the search string.

0 Likes
Message 4 of 10

BM_Ashraf
Advocate
Advocate

Got it, Let me prepare something for you

If this solved your problem, or answered your question, please click ACCEPT SOLUTION.

Blue Mech

Add-ins for Inventor!

0 Likes
Message 5 of 10

BM_Ashraf
Advocate
Advocate
Accepted solution

Hi @karl ,

Sorry, it took a while to get you the script.
Here is a quick one, please adjust it to your needs 🙂

Sub main
Dim oDoc As AssemblyDocument = ThisApplication.ActiveDocument
Dim oCDEF As AssemblyComponentDefinition = oDoc.ComponentDefinition
Dim oComponentOccurrencesEnumerator As ComponentOccurrencesEnumerator= oCDEF.Occurrences.AllLeafOccurrences
 oParentOBJColl = ThisApplication.TransientObjects.CreateObjectCollection
For Each oCC As ComponentOccurrence In oComponentOccurrencesEnumerator
	If oCC.Suppressed Then Continue For
	If oCC.Name.Contains("ADD THE STRING") = False Then  f_Supress_ (oCC) : Continue For
	If oCC.ParentOccurrence Is Nothing Then Continue For
	f_AddAllParents(oCC)
Next

If oParentOBJColl.Count < 1 Then Exit Sub
'MsgBox(oParentOBJColl.Count)
f_SuppressAllAssemblies(oCDEF)
	

End Sub
Private oParentOBJColl As ObjectCollection

Private Function f_SuppressAllAssemblies(oCDEF As AssemblyComponentDefinition) As Boolean
	For Each oCC As ComponentOccurrence In oCDEF.Occurrences
	If oCC.Suppressed Then Continue For
		Dim oRDoc As Document = Nothing
		Try
			oRDoc  = oCC.ReferencedDocumentDescriptor.ReferencedDocument
		Catch 
		End Try
	 If oRDoc Is Nothing Then Continue For
	If oRDoc.DocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then Continue For
	'MsgBox(oCC.Name)
	f_SuppressAllAssemblies(oRDoc.ComponentDefinition)
	If F_Check_DocInOBJColl(oRDoc)	= False Then  f_Supress_ (oCC)
Next
End Function


Private Function f_Supress_(Occ As Object) As Boolean
	Try
	If Occ.type = ObjectTypeEnum.kComponentOccurrenceObject Then Occ.Suppress : Return True
        If Occ.type <> ObjectTypeEnum.kComponentOccurrenceProxyObject Then Return True
     If  Occ.ParentOccurrence Is Nothing Then Return True
	Dim oParentCDEf As Object = Occ.ParentOccurrence.Definition
	'MsgBox(Occ.ParentOccurrence.name)
	f_GetAllOCCSAndSuppress(oParentCDEf,Occ.ReferencedDocumentDescriptor.ReferencedDocument)
Catch 
End Try

End Function 

Private Function f_GetAllOCCSAndSuppress(ByRef oParentCDEf As Object, oTDoc As Document) As Boolean
For Each oCC As Object In oParentCDEf.Occurrences
	If oCC.Suppressed Then Continue For 
		Dim oRDoc As Document = Nothing
		Try
		oRDoc	 = oCC.ReferencedDocumentDescriptor.ReferencedDocument
		Catch 
		End Try
		If oRDoc Is Nothing Then Continue For	
	If oRDoc Is oTDoc Then oCC.Suppress
Next	
End Function

Private Function f_AddAllParents(oCC As ComponentOccurrence) As Boolean
Do
	Try
	Dim oCCParent As ComponentOccurrence = oCC.ParentOccurrence
	If oCCParent Is Nothing Then Return True
	Dim oRD As Document = oCCParent.ReferencedDocumentDescriptor.ReferencedDocument
	If oRD Is Nothing Then Continue Do
	If oRD.DocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then Continue Do
	If F_Check_DocInOBJColl(oRD) Then Return True
	oParentOBJColl.Add(oRD)
	Catch 
		Return True
	End Try
Loop

End Function


Private Function F_Check_DocInOBJColl(oRDoc As Document) As Boolean
Try
	For Each oTDoc As Document In oParentOBJColl
		If oTDoc Is oRDoc Then Return True
	Next 
Catch 
End Try
Return False
End Function
	





If this solved your problem, or answered your question, please click ACCEPT SOLUTION.

Blue Mech

Add-ins for Inventor!

Message 6 of 10

karl-andreas_gross
Contributor
Contributor

Hi Ashraf,

this code works 100% as expected. Thank you so much! this is a pretty impressive solution (at least for a coding noob). Well Done!

One question tough: what exactly does :

oParentOBJColl = ThisApplication.TransientObjects.CreateObjectCollection  

 Can you give a short hint on that? I've never seen this function.

Message 7 of 10

BM_Ashraf
Advocate
Advocate
Accepted solution

Hi @karl-andreas_gross ,

To simplify it, you can think of it as temporary Container. You can add Objects like Documents in our case.
You can add temporary, non-persistent objects within the application, but not stored in the final model. 

 

Here you can find more about it.
https://help.autodesk.com/view/INVNTOR/2026/ENU/?guid=GUID-1695423A-6BD4-41DB-8771-45DEE8F64D85
https://help.autodesk.com/view/INVNTOR/2026/ENU/?guid=TransientObjects_CreateObjectCollection

The script checks for the Occurrences that contain the search string, then Checks all Parent Assemblies of that Occurrence and add them to the oParentOBJColl.
At the end, it checks all Assemblies(occurrences) and suppress them if they are not in the oParentOBJColl.

If this solved your problem, or answered your question, please click ACCEPT SOLUTION.

Blue Mech

Add-ins for Inventor!

Message 8 of 10

karl-andreas_gross
Contributor
Contributor

Hi Ashraf, one thing to mention: the code alters the structure of the subassemblies by suppressing the items, which may  cause issues. Would it be possible to 

Improve The code by adding a loop that stores Potential changes in the respective subassemblies by adding an extra Model state in each subassembly that experiences a change by a suppresion of one of its children?

Message 9 of 10

BM_Ashraf
Advocate
Advocate
Accepted solution

Hi @karl-andreas_gross ,

Yeah, That is an issue if you want to save the files.
Here is a better one, please adjust it to your needs!

 

Sub main
 oMAss = ThisApplication.ActiveDocument
Dim oCDEF As AssemblyComponentDefinition = oMAss.ComponentDefinition
oCDEF.ModelStates.Item(1).Activate
S_DOEvents
Dim oComponentOccurrencesEnumerator As ComponentOccurrencesEnumerator= oCDEF.Occurrences.AllLeafOccurrences
 oParentOBJColl = ThisApplication.TransientObjects.CreateObjectCollection
 oStringOBJColl = ThisApplication.TransientObjects.CreateObjectCollection
For Each oCC As ComponentOccurrence In oComponentOccurrencesEnumerator
	If oCC.Suppressed Then Continue For
	If oCC.Name.Contains(oSearchString) = False Then Continue For '  f_Supress_ (oCC) : Continue For
	f_CheckToAddOCC(oCC)	
	f_AddAllParents(oCC)
Next
'MsgBox(oStringOBJColl.Item(1).displayname)
If oStringOBJColl.Count <1 Then Exit Sub
'If oParentOBJColl.Count < 1 Then Exit Sub
'MsgBox(oParentOBJColl.Item(1).displayname)
f_GetOrCreateModelState(oCDEF)
f_SuppressAllAssemblies(oCDEF)
S_DOEvents
oMAss.update
'You will need to Save the Main Assembly, otherwise the creatd model states won't be saved.
oMAss.save
End Sub
Private  oMAss As AssemblyDocument
Private oParentOBJColl As ObjectCollection
Private oStringOBJColl As ObjectCollection
Dim oSearchString As String = "TYPE Your String Here"
Private oMStateName As String = "MS_" & oSearchString


Private Function f_SuppressAllAssemblies(oCDEF As AssemblyComponentDefinition) As Boolean
	For Each oCC As ComponentOccurrence In oCDEF.Occurrences
'Try
	If oCC.Suppressed Then Continue For
	 Dim oRDoc As Document = f_GetRefDocFromOcc(oCC)
	 If oRDoc Is Nothing Then Continue For 
	 If F_Check_DocInOBJColl(oRDoc, oStringOBJColl) = False And F_Check_DocInOBJColl(oRDoc, oParentOBJColl) = False Then f_Supress_(oCC):Continue For 
	If F_Check_DocInOBJColl(oRDoc, oStringOBJColl) Then Continue For 	
	If oRDoc.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then 
		'	MsgBox(oRDoc.DisplayName)
			f_GetOrCreateModelState(oCDEF)
			S_DOEvents
			f_GetOrCreateModelState(oRDoc.ComponentDefinition)
			Try
				S_DOEvents : oCC.ActiveModelState = oMStateName : S_DOEvents
			Catch 
			End Try
			f_SuppressAllAssemblies(oRDoc.ComponentDefinition)
			S_DOEvents
	Else 
			f_Supress_(oCC)
	End If 
		S_DOEvents
	'Catch 
	'	MsgBox(oCC.Name)
	'end try
Next
End Function


Private Function f_Supress_(Occ As Object) As Boolean
	Try
	If Occ.type = ObjectTypeEnum.kComponentOccurrenceObject Then Occ.Suppress : Return True
        If Occ.type <> ObjectTypeEnum.kComponentOccurrenceProxyObject Then Return True
     If  Occ.ParentOccurrence Is Nothing Then Return True
	Dim oParentCDEf As Object = Occ.ParentOccurrence.Definition
	'MsgBox(Occ.ParentOccurrence.name)
	f_GetAllOCCSAndSuppress(oParentCDEf,Occ.ReferencedDocumentDescriptor.ReferencedDocument)
Catch 
End Try

End Function 

Private Function f_GetAllOCCSAndSuppress(ByRef oParentCDEf As Object, oTDoc As Document) As Boolean
For Each oCC As Object In oParentCDEf.Occurrences
	If oCC.Suppressed Then Continue For 
		Dim oRDoc As Document = Nothing
		Try
		oRDoc	 = oCC.ReferencedDocumentDescriptor.ReferencedDocument
		Catch 
		End Try
		If oRDoc Is Nothing Then Continue For	
	If oRDoc Is oTDoc Then oCC.Suppress
Next	
End Function

Private Function f_AddAllParents(oCC As ComponentOccurrence) As Boolean
Do
	Try
	Dim oCCParent As ComponentOccurrence = oCC.ParentOccurrence
	If oCCParent Is Nothing Then oParentOBJColl.Add( oMAss) : Return True
	Dim oRD As Document = f_GetRefDocFromOcc(oCCParent)
	If oRD Is Nothing Then Continue Do
	If oRD.DocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then Continue Do
	If F_Check_DocInOBJColl(oRD,oParentOBJColl) Then Return True
	oParentOBJColl.Add(oRD)
	Catch 
		Return True
	End Try
Loop

End Function


Private Function f_GetOrCreateModelState(oCDEF As AssemblyComponentDefinition) As Boolean
	Dim oMState As ModelState = Nothing
	Try
		oMState = oCDEF.ModelStates.Item(oMStateName)
			S_ActivateMS(oMState)
	        S_DOEvents
	Return True
	Catch 
	End Try
	Try
		oCDEF.ModelStates.Add(oMStateName)
		S_ActivateMS(oMState)
		S_DOEvents
	Return True
	Catch
    End Try
End Function
Private Sub S_ActivateMS (oMState As ModelState)
	Try
		oMState.Activate
	Catch 
    End Try
	End Sub


Private Sub S_DOEvents 
	ThisApplication.UserInterfaceManager.DoEvents
End Sub 

Private Function f_GetRefDocFromOcc(oCC As Object) As Document
	Try
	Return	oCC.ReferencedDocumentDescriptor.ReferencedDocument
	Catch 
	End Try
	Return Nothing
End Function 

Private Function F_Check_DocInOBJColl(oRDoc As Document, oBJColl As ObjectCollection) As Boolean
Try
	For Each oTDoc As Document In oBJColl
		If oTDoc Is oRDoc Then Return True
		If oTDoc.FullDocumentName = oRDoc.FullDocumentName Then Return True
	Next 
Catch 
End Try
Return False
End Function

Private Function f_CheckToAddOCC(oCC As Object) As Boolean
	Dim oDoc As Document = f_GetRefDocFromOcc(oCC)
	If oDoc Is Nothing Then Return False
	If F_Check_DocInOBJColl(oDoc,oStringOBJColl) = False Then oStringOBJColl.Add(oDoc)	
End Function	
If this solved your problem, or answered your question, please click ACCEPT SOLUTION.

Blue Mech

Add-ins for Inventor!

Message 10 of 10

karl-andreas_gross
Contributor
Contributor

Dear Ashraf,

this solution works as well as expected. I thank you very much for your support. Good work!