Community
Inventor Programming - iLogic, Macros, AddIns & Apprentice
Inventor iLogic, Macros, AddIns & Apprentice Forum. Share your knowledge, ask questions, and explore popular Inventor topics related to programming, creating add-ins, macros, working with the API or creating iLogic tools.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Create an array list of Part Number iProperties from reference model

21 REPLIES 21
SOLVED
Reply
Message 1 of 22
mikejones
876 Views, 21 Replies

Create an array list of Part Number iProperties from reference model

Hi all.

 

I want to create an array that will store the iProperty Partnumber of each component in a reference model. The reference model is defined as the model used in a drawing view and the rule will be run from the drawing document.

Any help will be appreciated on this one.

 

Mike

Autodesk Certified Professional
21 REPLIES 21
Message 2 of 22
WCrihfield
in reply to: mikejones

Hi @mikejones.  I am not sure about the true scope of your task, or how you need to specify which view to process, so I wasn't sure how deep you wanted this to go.  For instance, do you only want the rule to process the view if it directly references an assembly?  Do you only want the part numbers of 'top level' assembly components in that assembly, or do you want it to go down into sub levels, and sub sub levels, etc?  Do you only want one part number listed for each 'unique' component (even if multiple components reference same model file), or one for every component, even if there are 10 components referencing the same model file?  Below is an example that lets you 'Pick' a view, then just processes the top level components that are not suppressed.

Sub Main
	Dim oView As DrawingView = PickDrawingView
	Dim oModel As Document = oView.ReferencedDocumentDescriptor.ReferencedDocument
	Dim oPNList As New List(Of String)
	If oModel.DocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then Exit Sub
	Dim oAModel As AssemblyDocument = oModel
	Dim oOccs As ComponentOccurrences = oAModel.ComponentDefinition.Occurrences
	If oOccs.Count = 0 Then Exit Sub 'no components to process
	For Each oOcc As ComponentOccurrence In oOccs
		If oOcc.Suppressed Then Continue For
		Dim oPN As String = iProperties.Value(oOcc.Name, "Project", "Part Number")
		oPNList.Add(oPN)
	Next
	oMyPN = InputListBox("", oPNList, "", "Part Numbers")
End Sub

Function PickDrawingView(Optional oPrompt As String = vbNullString) As DrawingView
	If oPrompt = "" Then oPrompt = "Select a Drawing View."
	oObj = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kDrawingViewFilter, oPrompt)
	If IsNothing(oObj) OrElse (TypeOf oObj Is DrawingView = False) Then Return Nothing
	Dim oView As DrawingView = oObj
	Return oView
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)

Message 3 of 22
mikejones
in reply to: WCrihfield

Thanks for the quick responce @WCrihfield .

 

This rule will only ever run on an assembly drawing and I want to get a complete list of all parts and sub assemblies referenced in it, however deep the tree goes. If a component occurs multiple times  then I only need to reference it once.

 

It is going to give me a list of all the part and sub assembly drawings required for manufacturing purposes 

 

Mike

Autodesk Certified Professional
Message 4 of 22
WCrihfield
in reply to: mikejones

OK.  I have modified the code to iterate through the assembly document's 'AllReferencedDocuments', which reaches every level of the assembly.  It is still possible though, that this does not include some documents, if every component, in every level that references that document has been suppressed.  I am using an iLogic shortcut within the loop that was only made available in the 2021 product year, so if you are using an earlier version, we may have to change that to using API route, to get the iProperty value.  Just let me know.  I am just using an InputListBox to show you the resulting list of part numbers, but you can modify to do whatever you need with that list.

Sub Main
	Dim oView As DrawingView = PickDrawingView
	Dim oModel As Document = oView.ReferencedDocumentDescriptor.ReferencedDocument
	Dim oPNList As New List(Of String)
	If oModel.DocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then Exit Sub
	Dim oAModel As AssemblyDocument = oModel
	Dim oRefDocs As DocumentsEnumerator = oAModel.AllReferencedDocuments
	If oRefDocs.Count = 0 Then Exit Sub
	For Each oRefDoc As Document In oRefDocs
		Dim SOP = StandardObjectFactory.Create(oRefDoc) 'Inventor 2021 or later only
		Dim oPN As String = SOP.iProperties.Value("Project", "Part Number")
		oPNList.Add(oPN)
	Next 'oRefDoc
	oMyPN = InputListBox("", oPNList, "", "Part Numbers")
End Sub

Function PickDrawingView(Optional oPrompt As String = vbNullString) As DrawingView
	If oPrompt = "" Then oPrompt = "Select a Drawing View."
	oObj = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kDrawingViewFilter, oPrompt)
	If IsNothing(oObj) OrElse (TypeOf oObj Is DrawingView = False) Then Return Nothing
	Dim oView As DrawingView = oObj
	Return oView
End Function

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 5 of 22
mikejones
in reply to: WCrihfield

That certainly gave me a complete list of all the files but now I want to filter out and ignore ones that have their BOM structure set to reference or phantom. So I need some code that does what is in red below.

 

	For Each oRefDoc As Document In oRefDocs
		Dim SOP = StandardObjectFactory.Create(oRefDoc) 'Inventor 2021 or later only
		If the BOM type is normal or inseperable then
		Dim oPN As String = SOP.iProperties.Value("Project", "Part Number")
		oPNList.Add(oPN)
End If Next 'oRefDoc

 

Thanks for your help so far.

 

Mike

Autodesk Certified Professional
Message 6 of 22
WCrihfield
in reply to: mikejones

OK.  Here you go.  I think this should do the trick.

Sub Main
	Dim oView As DrawingView = PickDrawingView
	Dim oModel As Document = oView.ReferencedDocumentDescriptor.ReferencedDocument
	Dim oPNList As New List(Of String)
	If oModel.DocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then Exit Sub
	Dim oAModel As AssemblyDocument = oModel
	Dim oRefDocs As DocumentsEnumerator = oAModel.AllReferencedDocuments
	If oRefDocs.Count = 0 Then Exit Sub
	For Each oRefDoc As Document In oRefDocs
		Dim oBOMSt As BOMStructureEnum = oRefDoc.ComponentDefinition.BOMStructure
		If oBOMSt = BOMStructureEnum.kReferenceBOMStructure Or _
			oBOMSt = BOMStructureEnum.kPhantomBOMStructure Then
			Continue For 'skip to next oRefDoc in loop, if any
		End If
		Dim SOP = StandardObjectFactory.Create(oRefDoc) 'Inventor 2021 or later only
		Dim oPN As String = SOP.iProperties.Value("Project", "Part Number")
		oPNList.Add(oPN)
	Next 'oRefDoc
	oMyPN = InputListBox("", oPNList, "", "Part Numbers")
End Sub

Function PickDrawingView(Optional oPrompt As String = vbNullString) As DrawingView
	If oPrompt = "" Then oPrompt = "Select a Drawing View."
	oObj = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kDrawingViewFilter, oPrompt)
	If IsNothing(oObj) OrElse (TypeOf oObj Is DrawingView = False) Then Return Nothing
	Dim oView As DrawingView = oObj
	Return oView
End Function

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 7 of 22
mikejones
in reply to: WCrihfield

@WCrihfield you are a genius, that has done everything I needed it to do. Thank you so much

 

Mike

Autodesk Certified Professional
Message 8 of 22
chris
in reply to: mikejones

can you show an example of what this rule is doing?

Message 9 of 22
mikejones
in reply to: chris

Hi Chris

 

This is part of a rule I'm developing for one of my manufacturing clients. It is basically a further development of an existing rule that creates a pdf and dxf file of a released drawing, and adds the drawing revision number as a suffix to the file names. Before creating the new files the rule also checks whether a previous version of the files exist and if so moves them into an archive folder. At the same time it will update the clients drawing register, which is an excel spreadsheet, with the relevant drawing information.

The new bit of code now determines whether the drawing is part of a manufacturing package and if it is then it will get all drawings required  for manufacturing and put them into a folder that can be sent out for supply, hence the need for the list of normal and inseparable files. When manufacturing drawings are updated the code will also check all manufacturing packages for the same drawing and replace them with the new one.

 

Currently this is being done manually by my client through windows explorer and is very prone to errors; I'm personally against copies of files in multiple places but if the client is insisting on doing it this way who am I to argue? They have no cad software in house and no MRP or ERP systems in place so it very much a manual process that I'm trying to automate for them.

 

Hopefully that makes sense.

 

Mike

Autodesk Certified Professional
Message 10 of 22
mikejones
in reply to: mikejones

This message goes to @WCrihfield or anyone else that can help. 


The solution offered by @WCrihfield worked great but I've recently realized it doesn't do what I want in all situations and that the 'AllReferencedDocuments' won't work if there are sub-assemblies in the file that are in as reference only; i.e. all of the parts in the reference sub-assembly are listed when they shouldn't be. Would it be possible to use the Parts Only BOM as the driver and ignore Purchased Parts from the list?
I've attached a Pack&Go sample file; 2023 version, and drawing that hopefully explains the situation better.

 

Any and all help really appreciated.

 

Mike

Autodesk Certified Professional
Message 11 of 22
WCrihfield
in reply to: mikejones

Hi @mikejones.  I'm still using 2022.3.2, so I wouldn't be able to open your files, but using Parts only BOMView certainly sounds doable.  To you want to keep the 'Pick View' functionality, or would you prefer to just have it work with the first view on the active sheet of the drawing?  And is the 'InputListBox' thing working OK for you, or would you prefer to have the bulk of the code set-up as a separate Function which will return the List(Of String) object, since this is just part of a larger automation project?

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 12 of 22
mikejones
in reply to: WCrihfield

Hi again @WCrihfield and thanks for replying.

 

Working from the first Base view on the sheet will work better for me if that's not too much trouble; just speeds up the whole process for me.

 

The Dim oPNList As New List(Of Stringmethod is working for me currently, just some additional incorrect items being picked up in it. It would be good to get parts from a weldment assembly as well but they won't show up in the Parts Only BOM unless I change the weldment BOM structure from Inseperable to Normal which I'd rather not do. Is there a way around that problem?

 

The only parts I don't want in the list will be parts that are inside an assembly that has a BOM Structure of Reference and Parts that have a BOM Structure of anything other than Normal i.e. no Purchased, Phantom etc.

 

Mike

 

Autodesk Certified Professional
Message 13 of 22
WCrihfield
in reply to: mikejones

To avoid the weldment BOMStructure issue, we could just try doing the iteration of the assembly components directly, instead of using the Parts Only BOMView, and instead of using the AllReferendedDocuments routes.  It's slightly less efficient, but certainly doable that way, I would just have to incorporate an extra List type variable for keeping track of component referenced documents that I've already processed, so I don't process the same ones multiple times.  I have done that before several times in other solutions, so its not too bit a deal.  I might also have to incorporate a separate recursive Sub routine, for digging down through all the levels, but I've done that before many times too, so no big deal there either.  Getting the first base view on the active sheet shouldn't be a problem either.  I would just have to start the code a bit more traditionally.  No promises on timing, because I've got a few things going on at the same time, but I'll see what I can do.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 14 of 22
mikejones
in reply to: WCrihfield

Thank you. 

 

I thought I'd help someone else out on the Inventor Forum as you were helping me out, what goes around comes around as they say.

 

I'm off skiing tomorrow for a week so I'm not in any rush for this, whenever you have time.

 

Mike

Autodesk Certified Professional
Message 15 of 22
WCrihfield
in reply to: mikejones

Hi @mikejones.  I've got something for you to try out.  It may look a bit intimidating, but I think it might work for you.  I only put a few comments in there, because its already a fairly lengthy code, but if you need to ask about anything, please do.  I'm not 100% sure if the Document object filter will work as planned now that ModelStates have complicated those references, but if not, we can try something else, like maybe FullFileName or FullDocumentName or something else unique about each one.  Let me know how this works out for you.

 

Class ThisRule
	Dim oDocs As List(Of Document) 'shared with all routines
	Dim oPNList As List(Of String) 'shared with all routines
	Sub Main
		If ThisDoc.Document.DocumentType <> DocumentTypeEnum.kDrawingDocumentObject Then
			MsgBox("A Drawing document must be active for this code to work. Exiting.", vbCritical, "")
			Exit Sub
		End If
		Dim oDDoc As DrawingDocument = ThisDoc.Document
		Dim oViews As DrawingViews = oDDoc.ActiveSheet.DrawingViews
		If oViews.Count = 0 Then Exit Sub 'may want a feedback message or Log entry here.
		Dim oBV As DrawingView
		For Each oView As DrawingView In oViews
			If oView.ViewType = DrawingViewTypeEnum.kStandardDrawingViewType Then
				oBV = oView : Exit For
			End If
		Next 'oView
		If IsNothing(oBV) Then Exit Sub 'may want a feedback message or Log entry here.
		Dim oADoc As AssemblyDocument = oBV.ReferencedDocumentDescriptor.ReferencedDocument
		Dim oOccs As ComponentOccurrences = oADoc.ComponentDefinition.Occurrences
		oDocs = New List(Of Document) 'to initiate it
		oPNList = New List(Of String) 'to initiate it
		RecursivelyProcessComponents(oOccs)
		oMyPN = InputListBox("", oPNList, "", "Part Numbers")
	End Sub

	Sub RecursivelyProcessComponents(oComps As ComponentOccurrences)
		If IsNothing(oComps) OrElse oComps.Count = 0 Then Exit Sub
		For Each oComp As ComponentOccurrence In oComps
			Dim ProcessFurther As Boolean = ProcessComponent(oComp) 'run our other routine
			If ProcessFurther = False Then Exit Sub
			If oComp.SubOccurrences.Count > 0 Then
				RecursivelyProcessComponents(oComp.SubOccurrences)
			End If
		Next
	End Sub
	
	Function ProcessComponent(oComp As ComponentOccurrence) As Boolean
		If IsNothing(oComp) OrElse oComp.Suppressed Then Return False
		'filter by BOMStructure values
		'Note:  BOMStructure of component can be different than its referenced document
		If oComp.BOMStructure <> BOMStructureEnum.kNormalBOMStructure And _
			oComp.BOMStructure <> BOMStructureEnum.kInseparableBOMStructure Then
			Return False
		End If
		If oComp.DefinitionDocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
			If oComp.Definition.BOMStructure = BOMStructureEnum.kReferenceBOMStructure Then Return False
		ElseIf oComp.DefinitionDocumentType = DocumentTypeEnum.kPartDocumentObject Then
			If oComp.Definition.BOMStructure <> BOMStructureEnum.kNormalBOMStructure Then Return False
		End If
		Dim oDoc As Document = oComp.Definition.Document
		If oDocs.Contains(oDoc) Then Return False 'do not process the same document again
		Dim SOP = StandardObjectFactory.Create(oDoc) 'Inventor 2021 or later only
		Dim oPN As String = SOP.iProperties.Value("Project", "Part Number")
		oPNList.Add(oPN)
		oDocs.Add(oDoc)
		Return True 'return True, so it will process any sub occurrances of this component
	End Function
End Class

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 16 of 22
mikejones
in reply to: WCrihfield

Hi @WCrihfield 

Thanks for taking the time to generate the code for me. 

No that I'm back from my holiday; great to get awayagain, I've run the code this morning but I get the following error on line 14

Object reference not set to an instance of an object.

This is  referring to the line 

If oBV.ViewType = DrawingViewTypeEnum.kStandardDrawingViewType Then

Do you have any idea why this is failing? I've tried changing the view type to projected aswell but that also fails with the same error.

 

Mike

Autodesk Certified Professional
Message 17 of 22
WCrihfield
in reply to: mikejones

Good morning @mikejones.  I see my mistake.  I should have used the 'oView' variable in that line, instead of the 'oBV' variable.  The loop definition line is using the oView variable, so it will always have a value, while the oBV variable will not have a value until after that line, if the oView passes the test.  So that line should have been:

 

If oView.ViewType = DrawingViewTypeEnum.kStandardDrawingViewType Then

I will fix that line in my code, so others can copy/paste it without the error being in there.

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 18 of 22
mikejones
in reply to: WCrihfield

Thanks.

That makes sense now I think about it. I'll give it another try.

 

Mike

Autodesk Certified Professional
Message 19 of 22
mikejones
in reply to: WCrihfield

Hi again.

 

So the code now gets a base view ok and displays the InputListBox from the code below

oMyPN = InputListBox("", oPNList, "", "Part Numbers")

but, what I find is that if the base view is an assembly with just components it is fine but if it is an assembly file with sub assembly (BOM Normal) then it return an empty list i.e. it only returns a list if the Base View file reference is an assembly with part files only.

 

Any ideas?

 

Mike

Autodesk Certified Professional
Message 20 of 22
mikejones
in reply to: WCrihfield

I think the issue is with the code highlighted red below. I think as soon as a reference that has a BOM Structure that is not NORMAL or INSEPARABLE is found then the code exits if I've understood it correctly. I don't know how to fix it though if that is the issue.

 

Sub RecursivelyProcessComponents(oComps As ComponentOccurrences)
		If IsNothing(oComps) OrElse oComps.Count = 0 Then Exit Sub
		For Each oComp As ComponentOccurrence In oComps
			Dim ProcessFurther As Boolean = ProcessComponent(oComp) 'run our other routine
			If ProcessFurther = False Then Exit Sub'........This needs to process the next oComp rather than exit
			If oComp.SubOccurrences.Count > 0 Then
				RecursivelyProcessComponents(oComp.SubOccurrences)
			End If
		Next
	End Sub
	
	Function ProcessComponent(oComp As ComponentOccurrence) As Boolean
		If IsNothing(oComp) OrElse oComp.Suppressed Then Return False
		'filter by BOMStructure values
		'Note:  BOMStructure of component can be different than its referenced document
		If oComp.BOMStructure <> BOMStructureEnum.kNormalBOMStructure And _
			oComp.BOMStructure <> BOMStructureEnum.kInseparableBOMStructure Then
			Return False
		End If

 

Autodesk Certified Professional

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report