'For loop' to exclude 'base component'

'For loop' to exclude 'base component'

Mike_Y2
Advocate Advocate
420 Views
10 Replies
Message 1 of 11

'For loop' to exclude 'base component'

Mike_Y2
Advocate
Advocate

We create a multi body part file and then use "Make components" to create parts (1 part per body) and an Assembly.

 

When use an iLogic rule to loop through the Parts in the assembly using "AllReferencedDocuments" it includes looping through the original multibody part. How do I identify the multibody part and skip past it???

 

Note that we manually add sub assemblies and other Parts into the Assembly (created by "Make components") so any change to "AllReferencedDocuments" needs to continue to loop through the sub assembly and it's part files

 

For Each oDoc In oAsmDoc.AllReferencedDocuments

 

Thanks for your help

0 Likes
Accepted solutions (2)
421 Views
10 Replies
Replies (10)
Message 2 of 11

WCrihfield
Mentor
Mentor

Hi @Mike_Y2.  There are a few different possible ways to determine which referenced document is the 'original' one that the others are 'derived' from.  One way would be to simply know that file's name, then check each document's file name to filter it out while iterating through them.  If you used the Document.ReferencedDocuments collection instead of the Document.AllReferencedDocuments collection, that would only include 'directly' referenced documents, and not deeper referenced documents, but then you would have to use a 'recursive' routine for stepping down into the components within sub assemblies.  If you do not want to have to include a hard-coded file name in your code anywhere, then we will have to dig deeper into some more complex stuff.

When we dig down into the properties of a part's PartComponentDefinition, we have the PartComponentDefinition.ReferenceComponents property, which returns a ReferenceComponents collection object.  Since the 'make components' tool pretty much just derives parts of one part into another part, then at this point we would need to use the ReferenceComponents.DerivedPartComponents property to get its DerivedPartComponents collection object.  This is where we could define & create new derived part components, if we wanted to, but will only need to iterate through its members.  Each DerivedPartComponent object has the DerivedPartComponent.ReferencedDocumentDescriptor property, which returns a DocumentDescriptor.  That object has the FullDocumentName property, but that does not always have the same value as the Document.FullFileName.  The FullDocumentName will 'start' with the FullFileName value, but can then also include the 'member' name (for example, the iPart member name or ModelState member name) within "<" & ">" brackets.  So, if you want to get a clean FullFileName, you may want to step further down into the DocumentDescriptor.ReferencedFileDescriptor property, which returns a FileDescriptor object.  Then use its FileDescriptor.FullFileName property.  Finally, you can store that value in a String type variable, or in a List(Of String) type variable, if there are multiple files like that which you have to keep in mind and avoid.  Then when iterating through all referenced documents, you can check if the current referenced document's FullFileName equals the FullFileName of the derived parts' source file(s).

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 3 of 11

Mike_Y2
Advocate
Advocate

@WCrihfield 

Thankyou for your detailed reply and 3 possible answers. It is really appreciated 👍

 

Answer 1

The multibody part doesn't have a static filename... it will be different on each occasion so hardcoding the filename isn't an option for my use case

 

Answer 2

I need to loop through all sub assemblies (if there are any). There will be a varying number of sub assembly levels each time so using Document.ReferencedDocuments doesn't seam like the way to go for my use case

 

Answer 3

I have since found the post linked below. This would appear to put a version of your answer into actual code (all be it i would need to extract the relevant part). If at all possible would you be able to look to see if there are any issue / oversights?... as your info above is very detailed and you clearly have a lot of knowledge on the subject. I would really value your expertise / input / guidance 👍

 

https://forums.autodesk.com/t5/inventor-programming-forum/ilogic-exclude-derived-parts-in-export-loo... 

 

0 Likes
Message 4 of 11

JhoelForshav
Mentor
Mentor
Accepted solution

Hi @Mike_Y2 
My recommendation is to loop through AllReferencedDocuments where the document is represented as an occurrence in the Assembly.
Example:

Dim oAsmDoc As AssemblyDocument = ThisDoc.Document
Dim oAsmDef As AssemblyComponentDefinition = oAsmDoc.ComponentDefinition
For Each oDoc As Document In oAsmDoc.AllReferencedDocuments.OfType(Of Document).Where(Function(x As Document) oAsmDef.Occurrences.AllReferencedOccurrences(x).Count > 0)
	MsgBox(oDoc.FullDisplayName)
Next





0 Likes
Message 5 of 11

WCrihfield
Mentor
Mentor

Here is one example code you can review and try out.  I tried to include lots of 'comments' right within the code to explain what each line of code is attempting to do.  I hope this helps some.  I created a separate Function just for extracting the FullFileName(s) of any/all 'derived in' source files from any given Inventor Document.  So, it iterates though all referenced documents one time just to collect those source file's FullFileNames to a collection, then you can iterate through them again to do what you want with each of them, while avoiding those source files.

Sub Main
	Dim oDoc As Inventor.Document = ThisDoc.Document
	'initialize the global variable for the collection of Strings
	oDerivedInSourceFiles = New HashSet(Of String)
	'get the collection of all referenced documents to a variable
	Dim oRefDocs As Inventor.DocumentsEnumerator = oDoc.AllReferencedDocuments
	'iterate through all referenced documents once to find all 'derived in source files'
	For Each oRefDoc As Inventor.Document In oRefDocs
		'this joins the ones returned from the custom Function into our main collection
		oDerivedInSourceFiles.UnionWith(ExtractDerivedInPartSourceFiles(oRefDoc, oDerivedInSourceFiles))
	Next 'oRefDoc
	'now iterate through all referenced documents again, and do what you want
	For Each oRefDoc As Inventor.Document In oRefDocs
		'if this referenced document's FullFileName is in our collection,
		'then it is a 'derived in source file', so skip over it
		If oDerivedInSourceFiles.Contains(oRefDoc.FullFileName) Then Continue For
			
		'<<< YOUR CODE HERE FOR WHAT YOU WANT TO DO WITH EACH REF DOC >>>
		
	Next 'oRefDoc
	
End Sub

'variables declared between routines are 'global' (can be accessed by all routines)
'create a new collection of Strings, which does not maintain order, and does not allow duplicates
Dim oDerivedInSourceFiles As HashSet(Of String)

'this will try to extract any/all 'derived in' part component source file(s) FullFileName
'the Optional input/output HashSet can be used to add to an already existing HashSet
Function ExtractDerivedInPartSourceFiles(doc As Inventor.Document, _
	Optional ByRef existingSet As HashSet(Of String) = Nothing) As HashSet(Of String)
	'if this is not a 'Part', then this method is not intersted in it, so exit, and return Nothing
	If Not TypeOf doc Is Inventor.PartDocument Then Return Nothing
	'create a PartDocument type variable, and set this document as its value (enables recognition)
	Dim oPDoc As Inventor.PartDocument = CType(doc, Inventor.PartDocument)
	'get all of this part's 'derived in' part components
	Dim oDPCs As DerivedPartComponents = oPDoc.ComponentDefinition.ReferenceComponents.DerivedPartComponents
	'if there are none, then we are done here, exit routine, and return Nothing
	If oDPCs.Count = 0 Then Return Nothing
	'create a new collection of Strings, which does not maintain order, and does not allow duplicates
	If existingSet Is Nothing Then existingSet = New HashSet(Of String)
	For Each oDPC As DerivedPartComponent In oDPDc
		'if it is no longer 'Linked' to the source file, then no useful info here
		If Not oDPC.LinkedToFile Then Continue For
		'if 'Link' is suppressed, then may not be able to access useful info here
		If oDPC.SuppressLinkToFile Then Continue For
		'get the DocumentDescriptor (describes native document reference)
		Dim oDocDesc As DocumentDescriptor = oDPC.ReferencedDocumentDescriptor
		'if missing, unresolved, suppressed, or disabled, then skip this one
		If oDocDesc.ReferenceMissing OrElse oDocDesc.ReferenceSuppressed OrElse oDocDesc.ReferenceDisabled Then Continue For
		'get the FileDescriptor (describes reference to a file)
		Dim oFD As FileDescriptor = oDocDesc.ReferencedFileDescriptor
		'if missing or disabled, then skip this one
		If oFD.ReferenceMissing OrElse oFD.ReferenceDisabled Then Continue For
		'add this File's FullFileName to our collection
		existingSet.Add(oFD.FullFileName)
	Next 'oDPC
	'return that collection to the method that called this method to run
	Return existingSet
End Function

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 6 of 11

Mike_Y2
Advocate
Advocate

@JhoelForshav Thankyou for your reply.

I have tested this in some basic assemblies and it works without error.

 

Your approach to the code is simpler to @WCrihfield approach... I am just wandering if the will both achieve the same end result or if there are things the @WCrihfield approach copes with that your approach doesn't?

 

I am not being critical of your approach, it's just that this level of code is a step above my (current) understanding so i am very interested to hear your opinion and understand any differences in the end result!

0 Likes
Message 7 of 11

Mike_Y2
Advocate
Advocate

@WCrihfield  thanks for you reply.

 

I am getting an error relating to line...

For Each oDPC As DerivedPartComponent In oDPDc


Is oDPDc a typo? I can't see a definition for it but you code is a level above my understand so it maybe my lack of understanding!

 

As above... your approach to the code is more complicated than @JhoelForshav approach... I am just wandering if both achieve the same end result or if there are things the @JhoelForshav  approach copes with that your approach doesn't or vise versa???

0 Likes
Message 8 of 11

WCrihfield
Mentor
Mentor

Hi @Mike_Y2.  If your primary intent is simply to skip over any/all referenced documents that there are not represented as components anywhere in your assembly, then yes, Jhoel Forshav's code seems very sufficient for that.  My code is simply far more specific, and only looks for referenced documents that are the source parts that were derived into other parts in your assembly.  If part of your goal was to isolate just those referenced documents or those files, to do something special with them, then my code example might have been a better choice.  But it seems like your main intent here was simply to skip over them when iterating through all other referenced documents, which my code example could be seen as 'overkill' for that task.  And yes, the error you mentioned was due to a typing mistake.  "oDPDc" should have been "oDPCs", as defined the few lines of code above where that loop starts.  I have used several different strategies over the years for skipping over referenced documents, referenced files, and assembly component occurrences, for one reason or another.  Sometimes I get a bit overzealous 😁.  But at least now you have both a working 'skip' method, and a 'code roadmap' of sorts, to where you can find those derived part source files.  Good luck in your future Inventor automation endeavors.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 9 of 11

Mike_Y2
Advocate
Advocate

@WCrihfield Thanks for explaining the difference in the code. It really helps👍

 

I corrected the typo but now get the error below... sorry I am unable to fix this myself.

 

Error on line 12 in rule: Rule3_Copy, in document: (U1) Pre-Mill TESTS.iam

Value cannot be null.
Parameter name: other

0 Likes
Message 10 of 11

WCrihfield
Mentor
Mentor
Accepted solution

That one is slightly more complicated to explain, but essentially it is possible that the custom method does not find any 'derived in' source part file FullFileNames, which may mean that that Function did not return anything.  So, when it attempts to do the 'UnionWith' method to join that returned collection with the main collection, it does not allow that variable to represent 'Nothing' or an empty collection, therefore it throws an error.  I obviously did not test this code before I posted it, because I had no use for it myself, and was apparently typing through it too fast, not paying attention to some of those types of details which would only show themselves when tested.  So, since there were a couple of errors needing repairs so far, I decided it might be best if I simply posted an updated version of the code I posted above, even though it is not necessarily a 'solution' in this case, just for reference.  I simplified the large custom Function by utilizing a Try...Catch...End Try statement.  Since we are not yet providing any 'feedback' about when or why any of the 'checks' may have failed, and no one really cares in this case, it is sufficient to just skip over all that internal detail here, and still achieve usable functionality.  I also included an extra check in the first loop of the 'Sub Main' area, to avoid the last error...at least that is what I assume caused it.

Sub Main
	Dim oDoc As Inventor.Document = ThisDoc.Document
	'create collection of Strings (duplicates not possible - does not maintain order)
	Dim oDerivedInSourceFiles As HashSet(Of String) = New HashSet(Of String)
	'get the collection of all referenced documents to a variable
	Dim oRefDocs As Inventor.DocumentsEnumerator = oDoc.AllReferencedDocuments
	'iterate through all referenced documents once to find all 'derived in source files'
	For Each oRefDoc As Inventor.Document In oRefDocs
		'if this is a part, which has any other parts derived into it,
		'then get those source part files' FullFileNames
		Dim oHS As HashSet(Of String) = ExtractDerivedInPartSourceFiles(oRefDoc)
		'if any were found/returned, then add them to our main collection for use later
		If (oHS IsNot Nothing) AndAlso (oHS.Count > 0) Then
			'join this HashSet with the main HashSet
			oDerivedInSourceFiles.UnionWith(oHS)
		End If
	Next 'oRefDoc
	'now iterate through all referenced documents again, and do what you want
	For Each oRefDoc As Inventor.Document In oRefDocs
		'if this referenced document's FullFileName is in our collection,
		'then it is a 'derived in source file', so skip over it
		If oDerivedInSourceFiles.Contains(oRefDoc.FullFileName) Then Continue For
			
		'<<< YOUR CODE HERE FOR WHAT YOU WANT TO DO WITH EACH REF DOC >>>
		
	Next 'oRefDoc
	
End Sub

'this will try to extract any/all 'derived in' part component source file(s) FullFileName
Function ExtractDerivedInPartSourceFiles(doc As Inventor.Document) As HashSet(Of String)
	'if this is not a 'Part', then this method is not intersted in it, so exit, and return Nothing
	If Not TypeOf doc Is Inventor.PartDocument Then Return Nothing
	'create a PartDocument type variable, and set this document as its value (enables recognition)
	Dim oPDoc As Inventor.PartDocument = CType(doc, Inventor.PartDocument)
	'create a new collection of Strings, which does not maintain order, and does not allow duplicates
	Dim oHS As HashSet(Of String) = New HashSet(Of String)
	'iterate through all 'derived in' part components (if any)
	For Each oDPC As DerivedPartComponent In oPDoc.ComponentDefinition.ReferenceComponents.DerivedPartComponents
		Try
			'try to add its FullFileName into our collection of Strings
			oHS.Add(oDPC.ReferencedDocumentDescriptor.ReferencedFileDescriptor.FullFileName)
		Catch
		End Try
	Next 'oDPC
	'return that collection to the method that called this method to run
	Return oHS
End Function

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 11 of 11

Mike_Y2
Advocate
Advocate

@WCrihfield Thank you for your detailed reply.

 

I have tested the latest version in some basic assemblies and it works without error. 👍

0 Likes