change material to Generic for all opened files

change material to Generic for all opened files

mallorn
Advocate Advocate
169 Views
3 Replies
Message 1 of 4

change material to Generic for all opened files

mallorn
Advocate
Advocate

Hello, my code is changing material to "Generic" only for the file which I have the tab active, it traverses correctly, showing file names, but material stays unchanged for all files, except activated one. There are 2 materials in all opened part files.

 

Help me to correct code, to change all opened parts.

Public Sub Main()
'this macro assumes that only Part documents are opened in Inventor
	Dim file As Inventor.Document
	For Each file In ThisApplication.Documents.VisibleDocuments
		setMaterialTo(file, "Generic")
	Next
End Sub

Function setMaterialTo(oDoc As Inventor.Document, oMaterial As String)
	oDoc.Activate
	iProperties.Material = oMaterial
	Logger.Trace(oDoc.ActiveMaterial.DisplayName)
	oDoc.Save
End Function

 the Trace output is like this:

TRACE|S235
TRACE|S235
TRACE|S235
TRACE|S235
TRACE|Generic
-------------------------
Tomasz Malinowski
0 Likes
170 Views
3 Replies
Replies (3)
Message 2 of 4

WCrihfield
Mentor
Mentor

Hi @mallorn.  Try changing this line:

iProperties.Material = oMaterial

...to this:

iProperties.Material(oDoc.DisplayName) = oMaterial

...otherwise, it does not know what document or assembly component to target other than the current/active one.

However, even that edit might not be enough, because it may not know how to find that Document by just its DisplayName.  It would usually look within the current/active document's AllReferencedDocuments collection for the document being specified, not within the collection of other 'parallel' opened documents.

But that is just the 'iLogic shortcut' way of doing it.

The Inventor API way would require you to get the actual Asset object representing that material from either each document's local materials (PartDocument.MaterialAssets), or from a global asset library, then specify that Asset as the value of the PartDocument.ActiveMaterial property.  The iLogic snippets often just ask us for Strings (names) of things, instead of the actual objects that the names point to, while the Inventor API methods usually want the actual objects, instead of just their names.

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 3 of 4

WCrihfield
Mentor
Mentor

Hi @mallorn.  Here is another way you could do a task like this...using the Inventor API way, instead of the iLogic API way.  The code still exists in an iLogic rule, but obviously a lot more code is involved this way.  We can also see what all is going on in the process this way.  We also trade out specifying which document we want to set the material of from 'document name' (which is vague, no direct property for), to specifying the actual Document object itself, which eliminates all guess work.  This code example below could have been expanded further, to include searching through additional 'global' material libraries, and optionally to create the material, if it can not be found anywhere, but there are lots of specifications involved in materials, so that one optional step could potentially involve a whole extra code routine with a lot of inputs being requested.

Here is the Inventor API example code for an iLogic rule:

Sub Main
	For Each oDoc As Inventor.Document In ThisApplication.Documents.VisibleDocuments
		SetMaterialByName(oDoc, "Generic")
	Next
End Sub

Sub SetMaterialByName(doc As Inventor.Document, MaterialName As String)
	If (Not TypeOf doc Is PartDocument) Then Return
	If Not doc.IsModifiable Then Return
	Dim oPDoc As PartDocument = doc
	Dim oMatAsset, oNeededMatAsset As MaterialAsset
	For Each oMatAsset In oPDoc.MaterialAssets
		If oMatAsset.DisplayName = MaterialName Then
			oNeededMatAsset = oMatAsset
			Exit For
		End If
	Next
	If oNeededMatAsset Is Nothing Then
		For Each oMatAsset In ThisApplication.ActiveMaterialLibrary.MaterialAssets
			If oMatAsset.DisplayName = MaterialName Then
				Try
					oNeededMatAsset = oMatAsset.CopyTo(oPDoc)
				Catch ex As Exception
					Logger.Error(vbCrLf & ex.ToString)
				End Try
				Exit For
			End If
		Next
	End If
	If oNeededMatAsset Is Nothing Then
		Logger.Warn("Could not find existing 'material' named '" & MaterialName & "'!")
		Return
		'or, try to create the material within the part, then set it as the active one
		'Dim oNewAsset As Inventor.Asset = oPDoc.Assets.Add(AssetTypeEnum.kAssetTypeMaterial, , , "Generic")
		'oNeededMatAsset = CType(oNewAsset, Inventor.MaterialAsset)
	End If
	Try
		oPDoc.ActiveMaterial = oNeededMatAsset
		oPDoc.Update2(True)
		oPDoc.Save()
	Catch ex As Exception
		Logger.Error(vbCrLf & ex.ToString)
	End Try
End Sub

If this solved your problem, or answered your question, please click ACCEPT SOLUTION .
Or, if this helped you, please click (LIKE or KUDOS) 👍.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 4 of 4

mallorn
Advocate
Advocate

Hello, your solution looks nicer, I was just simplifying mine.

I went through my program and found the solution: the reason was quite simple:

doc As Inventor.Document

should be changed to 

doc As Inventor.PartDocument

Then, after correcting the calls for function, it works properly by doing changes in all the opened files, not only the one I was calling iLogic rule from.

-------------------------
Tomasz Malinowski
0 Likes