How do I change ALL the material properties for PARTS at the ASSEMBLY level?

How do I change ALL the material properties for PARTS at the ASSEMBLY level?

gavin.allenHSSRX
Enthusiast Enthusiast
3,746 Views
18 Replies
Message 1 of 19

How do I change ALL the material properties for PARTS at the ASSEMBLY level?

gavin.allenHSSRX
Enthusiast
Enthusiast

I have a little bit of code and being a novice, complete beginner, cannot understand what is wrong. Please can someone help.

    Sub Main()
        Dim oAsmDoc As AssemblyDocument = ThisApplication.ActiveDocument
        Dim oOccurrence As ComponentOccurrence

        ' Get the material name to apply to all components
        Dim materialName As String = "Stainless Steel"

        ' Iterate through each component occurrence in the assembly
        For Each oOccurrence In oAsmDoc.ComponentDefinition.Occurrences
            ' Check if the component has a PartDocument
            If TypeOf oOccurrence.Definition.Document Is PartDocument Then
                Dim oPartDoc As PartDocument = oOccurrence.Definition.Document
                Dim currentMaterialName As String = oPartDoc.ComponentDefinition.Material.Name
                If currentMaterialName = materialName Then
                    ' Set the material for the component occurrence
                    oPartDoc.ComponentDefinition.Material.SetMaterial(materialName)
                End If
            End If
        Next

        ' Save the changes
        oAsmDoc.Save()
    End Sub

 

Regards

K.I.S.S. (keep it simple stupid)
Life doesn't have to be complicated.
Designs don't have to be complicated.
GOD Bless you.
Accepted solutions (1)
3,747 Views
18 Replies
Replies (18)
Message 2 of 19

Andrii_Humeniuk
Advisor
Advisor
Accepted solution

Hi @gavin.allenHSSRX . I modified your code a bit. Please check if everything works as you wanted.

 

 

Sub Main()
	Dim oAsmDoc As AssemblyDocument = ThisApplication.ActiveDocument
	Dim oOccurrence As ComponentOccurrence
	' Get the material name to apply to all components
	Dim materialName As String = "Stainless Steel"
	Dim oAssetlib As AssetLibrary
	Dim oAsset As Asset
	For Each oAssetlib In ThisApplication.AssetLibraries
		For i As Integer = 1 To oAssetlib.MaterialAssets.Count
			If oAssetlib.MaterialAssets.Item(i).DisplayName = materialName Then
				oAsset = oAssetlib.MaterialAssets.Item(i)
				GoTo NextStep
			End If
		Next
	Next
	NextStep :
	If oAsset Is nothiong Then Exit Sub
	' Iterate through each component occurrence in the assembly
	For Each oOccurrence In oAsmDoc.ComponentDefinition.Occurrences
		' Check if the component has a PartDocument
		If TypeOf oOccurrence.Definition.Document Is PartDocument Then
			Dim oPartDoc As PartDocument = oOccurrence.Definition.Document
			If oPartDoc.IsModifiable Then
				Dim currentMaterialName As String = oPartDoc.ActiveMaterial.DisplayName
				If Not String.IsNullOrEmpty(currentMaterialName) Then
					If currentMaterialName <> oAsset.DisplayName Then
						' Set the material for the component occurrence
						oPartDoc.ActiveMaterial = oAsset
					End If
				End If
			End If
		End If
	Next
	' Save the changes
	oAsmDoc.Update()
	oAsmDoc.Save()
End Sub

Andrii Humeniuk - CAD Coordinator, Autodesk Certified Instructor

LinkedIn | My free Inventor Addin | My Repositories

Did you find this reply helpful ? If so please use the Accept as Solution/Like.

EESignature

Message 3 of 19

gavin.allenHSSRX
Enthusiast
Enthusiast
Thank you so much, this has rune without any erros.
K.I.S.S. (keep it simple stupid)
Life doesn't have to be complicated.
Designs don't have to be complicated.
GOD Bless you.
0 Likes
Message 4 of 19

romu51
Advocate
Advocate

I Like this one.... now added to my list. 

it will work as long as the material exists in the library. 

it also changed my content centre part i had in my assembly. 

I tried to supress the components i didn't want to change by supressing them  before i ran the rule but it gave me an error.

is there an easy way to omit the CC parts?

 

 

romu51_0-1684998666498.png

 

0 Likes
Message 5 of 19

Andrii_Humeniuk
Advisor
Advisor

Hi @romu51 . Try this code:

 

 

Sub Main()
	Dim oAsmDoc As AssemblyDocument = ThisApplication.ActiveDocument
	Dim oTM As TransactionManager = ThisApplication.TransactionManager
	Dim oOccurrence As ComponentOccurrence
	' Get the material name to apply to all components
	Dim materialName As String = "Stainless Steel"
	Dim oAssetlib As AssetLibrary
	Dim oAsset As Asset
	For Each oAssetlib In ThisApplication.AssetLibraries
		For i As Integer = 1 To oAssetlib.MaterialAssets.Count
			If oAssetlib.MaterialAssets.Item(i).DisplayName = materialName Then
				oAsset = oAssetlib.MaterialAssets.Item(i)
				GoTo NextStep
			End If
		Next
	Next
	NextStep :
	If oAsset Is nothiong Then Exit Sub
	' Iterate through each component occurrence in the assembly
	Dim newTM As Transaction = oTM.StartTransaction(oAsmDoc, "ChangeMaterial")
	Dim strLocName, strLocType, currentMaterialName As String
	For Each oOccurrence In oAsmDoc.ComponentDefinition.Occurrences
		' Check if the component has a PartDocument
		If Not oOccurrence.Suppressed Then
			If TypeOf oOccurrence.Definition.Document Is PartDocument Then
				Dim oPartDoc As PartDocument = oOccurrence.Definition.Document
				If oPartDoc.IsModifiable Then
					oPartDoc.GetLocationFoundIn(strLocName, strLocType)
					If Not strLocType = kLibraryLocation Then
						currentMaterialName = oPartDoc.ActiveMaterial.DisplayName
						If currentMaterialName <> oAsset.DisplayName Then
							' Set the material for the component occurrence
							oPartDoc.ActiveMaterial = oAsset
						End If
					End If
				End If
			End If
		End If
	Next
	newTM.End()
	' Save the changes
	oAsmDoc.Update()
	oAsmDoc.Save()
End Sub

Andrii Humeniuk - CAD Coordinator, Autodesk Certified Instructor

LinkedIn | My free Inventor Addin | My Repositories

Did you find this reply helpful ? If so please use the Accept as Solution/Like.

EESignature

Message 6 of 19

romu51
Advocate
Advocate

@Andrii_Humeniuk 

That works fine!

Many thanks!

I'll probably start a new thread to make this one evolve a bit more. 

0 Likes
Message 7 of 19

ch_giacomo
Enthusiast
Enthusiast

hello good rule.
would it be possible to modify it so that not all the components are modified but only those that you want with the click of the mouse?
Do you think it is possible?

0 Likes
Message 8 of 19

MichaëlStienstra
Participant
Participant

Some small arrangements on the code. It will let you chose out of an material list instead of only "Stainless Steel". It could be written smaller, but I used some code form an older project of mine. 

Sub Main()
	Dim oAsmDoc As AssemblyDocument = ThisApplication.ActiveDocument
	Dim oTM As TransactionManager = ThisApplication.TransactionManager
	Dim oOccurrence As ComponentOccurrence
	'Arraylist selection
	'Lijst labels
	Dim oSearchlabel As New ArrayList
	oSearchlabel.Add("Stainless Steel")
	oSearchlabel.Add("Steel")
	oSearchlabel.Add("Rubber")
	oSearchlabel.Add("ABS Plastic")
	oSearchlabel.Add("Aluminium 6061")
	oSearchlabel.Add("Concrete")
	oSearchlabel.Add("Generic")
	oSearchlabel.Add("Polythylene High Density")
	oSearchlabel.Add("Polythylene Low Density")

	oSearchlabel.Add("")
	oSearchlabel.Add("Custom Google search")
	
	'Basis lijst
	A1 = InputListBox("", oSearchlabel, oSearchlabel, Title := "Materials", ListName := "Material list")
	
	If A1 = "Stainless Steel" Then 
		B1 = "Stainless Steel" 
	End If
	If A1 = "Steel" Then
		B1 = "Steel"
	End If
	If A1= "Rubber" Then
		B1 = "Rubber"
	End If
	If A1 = "ABS Plastic" Then
		B1 = "ABS Plastic"
	End If
	If A1 = "Aluminium 6061" Then
		B1 = "Aluminium 6061"
	End If
	If A1 = "Concrete" Then
		B1 = "Concrete"
	End If
	If A1 = "Generic" Then
		B1 = "Generic"
	End If
	If A1 = "Polythylene High Density" Then
		B1 = "Polythylene High Density"
	End If
	If A1 = "Polythylene Low Density" Then
		B1 = "Polythylene Low Density"
	End If	
	
	' Get the material name to apply to all components
	Dim materialName As String = B1
	Dim oAssetlib As AssetLibrary
	Dim oAsset As Asset
	For Each oAssetlib In ThisApplication.AssetLibraries
		For i As Integer = 1 To oAssetlib.MaterialAssets.Count
			If oAssetlib.MaterialAssets.Item(i).DisplayName = materialName Then
				oAsset = oAssetlib.MaterialAssets.Item(i)
				GoTo NextStep
			End If
		Next
	Next
	NextStep :
	If oAsset Is nothiong Then Exit Sub
	' Iterate through each component occurrence in the assembly
	Dim newTM As Transaction = oTM.StartTransaction(oAsmDoc, "ChangeMaterial")
	Dim strLocName, strLocType, currentMaterialName As String
	For Each oOccurrence In oAsmDoc.ComponentDefinition.Occurrences
		' Check if the component has a PartDocument
		If Not oOccurrence.Suppressed Then
			If TypeOf oOccurrence.Definition.Document Is PartDocument Then
				Dim oPartDoc As PartDocument = oOccurrence.Definition.Document
				If oPartDoc.IsModifiable Then
					oPartDoc.GetLocationFoundIn(strLocName, strLocType)
					If Not strLocType = kLibraryLocation Then
						currentMaterialName = oPartDoc.ActiveMaterial.DisplayName
						If currentMaterialName <> oAsset.DisplayName Then
							' Set the material for the component occurrence
							oPartDoc.ActiveMaterial = oAsset
						End If
					End If
				End If
			End If
		End If
	Next
	newTM.End()
	' Save the changes
	oAsmDoc.Update()
	oAsmDoc.Save()
End Sub

 

Message 9 of 19

Andrii_Humeniuk
Advisor
Advisor

Hi @ch_giacomo . There are several options for solving this task:

  • Create an Array() in code with a list of your components, but this list needs to be constantly edited.
  • Add a MessageBox to the code that on each component will ask you if the code can change the material, but it's much more than one click.

Andrii Humeniuk - CAD Coordinator, Autodesk Certified Instructor

LinkedIn | My free Inventor Addin | My Repositories

Did you find this reply helpful ? If so please use the Accept as Solution/Like.

EESignature

0 Likes
Message 10 of 19

ch_giacomo
Enthusiast
Enthusiast

Sorry but I'm not good at programming.

I was thinking something like this: ThisApplication.CommandManager.Pick(SelectionFilterEnum.kAssemblyOccurrenceFilter, "Select a part in the assembly")

this is a copy and paste of another rule I just don't know how to adapt it to this one.

Do you think it is correct to start from this idea?

0 Likes
Message 11 of 19

ch_giacomo
Enthusiast
Enthusiast
Thanks, I'll take that into consideration
0 Likes
Message 12 of 19

Andrii_Humeniuk
Advisor
Advisor

No problem. This code changes the material for one or more selected components. You need to select the components before running the code.

Sub Main()
	Dim oAsmDoc As AssemblyDocument = ThisApplication.ActiveDocument
	Dim oTM As TransactionManager = ThisApplication.TransactionManager
	Dim oSS As SelectSet = oAsmDoc.SelectSet
	If oSS.Count = 0 Then
		MessageBox.Show("You have not selected components.", "Error!",MessageBoxButtons.OK,MessageBoxIcon.Error)
		Exit Sub
	End If
	Dim oOccurrence As ComponentOccurrence
	Dim materialName As String = "Stainless Steel"
	Dim oAssetlib As AssetLibrary
	Dim oAsset As Asset
	For Each oAssetlib In ThisApplication.AssetLibraries
		For i As Integer = 1 To oAssetlib.MaterialAssets.Count
			If oAssetlib.MaterialAssets.Item(i).DisplayName = materialName Then
				oAsset = oAssetlib.MaterialAssets.Item(i)
				GoTo NextStep
			End If
		Next
	Next
	NextStep :
	If oAsset Is nothiong Then Exit Sub
	Dim newTM As Transaction = oTM.StartTransaction(oAsmDoc, "ChangeMaterial")
	Dim strLocName, strLocType, currentMaterialName As String
	For i As Integer = 1 To oSS.Count
		If oSS.Item(i).Type = ObjectTypeEnum.kComponentOccurrenceObject Then
			oOccurrence = oSS.Item(i)
			If Not oOccurrence.Suppressed Then
				If TypeOf oOccurrence.Definition.Document Is PartDocument Then
					Dim oPartDoc As PartDocument = oOccurrence.Definition.Document
					If oPartDoc.IsModifiable Then
						oPartDoc.GetLocationFoundIn(strLocName, strLocType)
						If Not strLocType = kLibraryLocation Then
							currentMaterialName = oPartDoc.ActiveMaterial.DisplayName
							If currentMaterialName <> oAsset.DisplayName Then
								oPartDoc.ActiveMaterial = oAsset
							End If
						End If
					End If
				End If
			End If
		End If
	Next i
	newTM.End()
	oAsmDoc.Update()
'	oAsmDoc.Save()
End Sub

Andrii Humeniuk - CAD Coordinator, Autodesk Certified Instructor

LinkedIn | My free Inventor Addin | My Repositories

Did you find this reply helpful ? If so please use the Accept as Solution/Like.

EESignature

Message 13 of 19

MichaëlStienstra
Participant
Participant

Arrangement of @Andrii_Humeniuk code. As before I've added the possibility to chose different materials. It could be written smaller, but I used some code form an older project of mine. 

Sub Main()
	Dim oAsmDoc As AssemblyDocument = ThisApplication.ActiveDocument
	Dim oTM As TransactionManager = ThisApplication.TransactionManager
	Dim oSS As SelectSet = oAsmDoc.SelectSet
	If oSS.Count = 0 Then
		MessageBox.Show("You have not selected components.", "Error!",MessageBoxButtons.OK,MessageBoxIcon.Error)
		Exit Sub
	End If
	Dim oOccurrence As ComponentOccurrence
	
	'Lijst labels
	Dim oSearchlabel As New ArrayList
	oSearchlabel.Add("Stainless Steel")
	oSearchlabel.Add("Steel")
	oSearchlabel.Add("Rubber")
	oSearchlabel.Add("ABS Plastic")
	oSearchlabel.Add("Aluminium 6061")
	oSearchlabel.Add("Concrete")
	oSearchlabel.Add("Generic")
	oSearchlabel.Add("Polythylene High Density")
	oSearchlabel.Add("Polythylene Low Density")

	oSearchlabel.Add("")
	oSearchlabel.Add("Custom")
	
	'Basis lijst
	A1 = InputListBox("", oSearchlabel, oSearchlabel, Title := "Title", ListName := "Material list")
	
	If A1 = "Stainless Steel" Then 
		B1 = "Stainless Steel" 
	End If
	If A1 = "Steel" Then
		B1 = "Steel"
	End If
	If A1= "Rubber" Then
		B1 = "Rubber"
	End If
	If A1 = "ABS Plastic" Then
		B1 = "ABS Plastic"
	End If
	If A1 = "Aluminium 6061" Then
		B1 = "Aluminium 6061"
	End If
	If A1 = "Concrete" Then
		B1 = "Concrete"
	End If
	If A1 = "Generic" Then
		B1 = "Generic"
	End If
	If A1 = "Polythylene High Density" Then
		B1 = "Polythylene High Density"
	End If
	If A1 = "Polythylene Low Density" Then
		B1 = "Polythylene Low Density"
	End If	
	
	' Get the material name to apply to all components
	Dim materialName As String = B1

	'Dim materialName As String = "Stainless Steel"
	Dim oAssetlib As AssetLibrary
	Dim oAsset As Asset
	For Each oAssetlib In ThisApplication.AssetLibraries
		For i As Integer = 1 To oAssetlib.MaterialAssets.Count
			If oAssetlib.MaterialAssets.Item(i).DisplayName = materialName Then
				oAsset = oAssetlib.MaterialAssets.Item(i)
				GoTo NextStep
			End If
		Next
	Next
	NextStep :
	If oAsset Is nothiong Then Exit Sub
	Dim newTM As Transaction = oTM.StartTransaction(oAsmDoc, "ChangeMaterial")
	Dim strLocName, strLocType, currentMaterialName As String
	For i As Integer = 1 To oSS.Count
		If oSS.Item(i).Type = ObjectTypeEnum.kComponentOccurrenceObject Then
			oOccurrence = oSS.Item(i)
			If Not oOccurrence.Suppressed Then
				If TypeOf oOccurrence.Definition.Document Is PartDocument Then
					Dim oPartDoc As PartDocument = oOccurrence.Definition.Document
					If oPartDoc.IsModifiable Then
						oPartDoc.GetLocationFoundIn(strLocName, strLocType)
						If Not strLocType = kLibraryLocation Then
							currentMaterialName = oPartDoc.ActiveMaterial.DisplayName
							If currentMaterialName <> oAsset.DisplayName Then
								oPartDoc.ActiveMaterial = oAsset
							End If
						End If
					End If
				End If
			End If
		End If
	Next i
	newTM.End()
	oAsmDoc.Update()
'	oAsmDoc.Save()
End Sub
0 Likes
Message 14 of 19

ch_giacomo
Enthusiast
Enthusiast

Thank you for your time.

It gives me the error:

 

 

System.ArgumentException: Incorrect parameter. (Exception from HRESULT: 0x80070057 (E_INVALIDARG))
at System.RuntimeType.ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)
at Inventor.SelectSet.get_Item(Int32 Index)
in ThisRule.Main()
at Autodesk.iLogic.Exec.AppDomExec.ExecRuleInAssembly(Assembly assem)
at iLogic.RuleEvalContainer.ExecRuleEval(String execRule)

 

 

the first part is changed then the process seems to hang

0 Likes
Message 15 of 19

Andrii_Humeniuk
Advisor
Advisor

Sorry, I made a mistake, try this code:

Sub Main()
	Dim oAsmDoc As AssemblyDocument = ThisApplication.ActiveDocument
	Dim oTM As TransactionManager = ThisApplication.TransactionManager
	Dim oSS As SelectSet = oAsmDoc.SelectSet
	If oSS.Count = 0 Then
		MessageBox.Show("You have not selected components.", "Error!",MessageBoxButtons.OK,MessageBoxIcon.Error)
		Exit Sub
	End If
	Dim oOccurrence As ComponentOccurrence
	Dim oOccsList As New List(Of ComponentOccurrence)
	Dim materialName As String = "Stainless Steel"
	Dim oAssetlib As AssetLibrary
	Dim oAsset As Asset
	For Each oAssetlib In ThisApplication.AssetLibraries
		For i As Integer = 1 To oAssetlib.MaterialAssets.Count
			If oAssetlib.MaterialAssets.Item(i).DisplayName = materialName Then
				oAsset = oAssetlib.MaterialAssets.Item(i)
				GoTo NextStep
			End If
		Next
	Next
	NextStep :
	If oAsset Is nothiong Then Exit Sub
	Dim newTM As Transaction = oTM.StartTransaction(oAsmDoc, "ChangeMaterial")
	Dim strLocName, strLocType, currentMaterialName As String
	For i As Integer = 1 To oSS.Count
		If oSS.Item(i).Type = ObjectTypeEnum.kComponentOccurrenceObject Then
			oOccsList.Add(oSS.Item(i))
		End If
	Next i
	For i As Integer = 0 To oOccsList.Count -1
		oOccurrence = oOccsList.Item(i)
		If Not oOccurrence.Suppressed Then
			If TypeOf oOccurrence.Definition.Document Is PartDocument Then
				Dim oPartDoc As PartDocument = oOccurrence.Definition.Document
				If oPartDoc.IsModifiable Then
					oPartDoc.GetLocationFoundIn(strLocName, strLocType)
					If Not strLocType = kLibraryLocation Then
						currentMaterialName = oPartDoc.ActiveMaterial.DisplayName
						If currentMaterialName <> oAsset.DisplayName Then
							oPartDoc.ActiveMaterial = oAsset
						End If
					End If
				End If
			End If
		End If
	Next i
	newTM.End()
	oAsmDoc.Update()
'	oAsmDoc.Save()
End Sub

 

Andrii Humeniuk - CAD Coordinator, Autodesk Certified Instructor

LinkedIn | My free Inventor Addin | My Repositories

Did you find this reply helpful ? If so please use the Accept as Solution/Like.

EESignature

Message 16 of 19

ch_giacomo
Enthusiast
Enthusiast

WOW super.
thank you so much.
For us who know little about programming it is a lot of work saved in everyday comfort.

0 Likes
Message 17 of 19

ch_giacomo
Enthusiast
Enthusiast

good morning, could you modify the rule so that you can start the rule and after selecting the components you want to change the material? Thank you

0 Likes
Message 18 of 19

ch_giacomo
Enthusiast
Enthusiast

Hi everyone, I did a bit of research and came up with this rule, I'll post it if anyone needs it.

The rule makes you choose the material from a list and then you can select the parts of an assembly, to exit press ESC.

 

change this line to your materials
Dim materials As String() = {"Material1","Material2","Material3", "Material4", "Material5", "Material6", "Material7", "Material8", "Material9"}

 

' Default list of materials
Dim materials As String() = {"Material1","Material2","Material3", "Material4", "Material5", "Material6", "Material7", "Material8", "Material9"}

' Creation of the material selection dialog
Dim selectedMaterial As String
selectedMaterial = InputListBox("Select material:", materials)

' Check if the selected material is valid
If selectedMaterial = "" Then
     Call MsgBox("No material selected.", vbCritical, "iLogic")
     Exit Sub
End If

Dim App As Inventor.Application = ThisApplication

If Not ThisDoc.Document.DocumentType = kAssemblyDocumentObject Then
     Call MsgBox("Only in assemblies", vbCritical, "iLogic")
     Exit Sub
End If
    
Dim oAssDoc As AssemblyDocument = ThisDoc.Document
Dim bStop As Boolean = False
Dim oSel As Object

Do While bStop = False
     oSel = oApp.CommandManager.Pick(kAssemblyLeafOccurrenceFilter, "Select part (End with Esc)")
     If oSel Is Nothing Then
         bStop = True
     Else
         If oSel.Type = kComponentOccurrenceObject OrElse oSel.Type = kComponentOccurrenceProxyObject Then
             Dim oPartDoc As PartDocument = oSel.Definition.Document
                                
             ' Search for the material in the document's asset list
             Dim oMatAsset As MaterialAsset
             For Each oMatAsset In oPartDoc.MaterialAssets
                 If oMatAsset.DisplayName = selectedMaterial Then
                     Exit For
                 Else
                     oMatAsset = Nothing
                 End If
             Next
                                
             ' If the material is not present in the document, search the active asset library
             If oMatAsset Is Nothing Then
                 Dim oAssetLib As AssetLibrary = oApp.ActiveMaterialLibrary
                                    
                 Dim oLibAsset As MaterialAsset
                 For Each oLibAsset In oAssetLib.MaterialAssets
                     If oLibAsset.DisplayName = selectedMaterial Then
                         oMatAsset = oLibAsset.CopyTo(oPartDoc)
                         Exit For
                     End If
                 Next
             End If
                                
             ' If the material is not yet found, show an error message
             If oMatAsset Is Nothing Then
                 Call MsgBox("Material " & selectedMaterial & " not found.", vbCritical, "iLogic")
                 Exit Sub
             End If
                                
             ' Set the active material in the document
             oPartDoc.ActiveMaterial = oMatAsset
                                
             ' Update the active document
             Call oApp.ActiveDocument.Update
         End If
     End If
Loops

 

 

 

Message 19 of 19

Support_Charlies3DT
Contributor
Contributor

@gavin.allenHSSRX We have an app that can change the material and a lot of properties of all parts inside an assembly. If you are interested we can send you a test installer and you can have a look at the app. You can send me a pm if interested.