Get BOM instance property value

Get BOM instance property value

marco_bonacina5834P
Enthusiast Enthusiast
431 Views
10 Replies
Message 1 of 11

Get BOM instance property value

marco_bonacina5834P
Enthusiast
Enthusiast

Hi everyone,
I'm trying to export the instance properties extracted from the BOM to an excel file, I tried with this rule

Private Sub FillBomRowsList(oBomRows As BOMRowsEnumerator, myBomRows As List(Of MyBomRow))
For Each oRow As BOMRow In oBomRows
		Dim oCompDef As ComponentDefinition
		oCompDef = oRow.ComponentDefinitions.Item(1)
		Dim oPropSets As PropertySets
		oPropSets = oCompDef.Document.PropertySets
		Dim oCustomPropertySet = oPropSets.Item("Inventor User Defined Properties")
	Dim myBomRow = New MyBomRow()
		If oRow.ComponentOccurrences(1).OccurrencePropertySetsEnabled
			Try
		myBomRow.Spare = oRow.OccurrencePropertySets(1)("Spare").Value
		Catch
		End Try
		Else
			Try
			myBomRow.Spare = oCustomPropertySet.Item("Spare").Value
			Catch
			End Try
		End If
Next
End Sub

in ilogic and it works only if the assemblies are composed of only parts, in my case there are additional subassemblies inside the assemblies. I tried to follow this post https://forums.autodesk.com/t5/inventor-programming-ilogic/instance-properties-and-bomrows/td-p/1099... but Visual studio generates an error.
Has anyone already faced this type of problem?

Thanks.

0 Likes
432 Views
10 Replies
Replies (10)
Message 2 of 11

C_Haines_ENG
Collaborator
Collaborator

It seems your issue lies in this line.

oCompDef = oRow.ComponentDefinitions.Item(1)

You are only grabbing the component definition of the first item in that BOM row. Also if you're just grabbing an iProperty from each item item in an assembly (including subassemblies) you can just cycle through the parts in the assembly instead of going through the BOM. The example code below is in VB.Net formatting but you should be able to adjust it for VBA.

Sub Main

	Dim oAsm As AssemblyDocument = ThisDoc.Document
	Dim oDesignation As [Property]

	Dim oBOM As BOM = oAsm.ComponentDefinition.BOM
	Dim oBOMRows As BOMRowsEnumerator = oBOM.BOMViews(1).BOMRows
	
	Dim oProps As List(Of String)
	
	For Each oBOMRow As BOMRow In oBOMRows
		
		For Each oCompDef As ComponentDefinition In oBOMRow.ComponentDefinitions
			
			oProps.Add(oCompDef.Document.PropertySets("Inventor User Defined Properties")("Spare").Value)
		
		Next
			
	Next

End Sub

 

0 Likes
Message 3 of 11

marco_bonacina5834P
Enthusiast
Enthusiast

Hi,
thanks for the reply, then, analyzing the link in the previous message better I understood that there are some points to pay attention to.
I corrected the rule in this way and so I can have access to the instance properties but I still receive an error from visual studio when I take the value in this line:

 

ESBomRow.iSpare = componentProxy.NativeObject.OccurrencePropertySets(1).Item("Spare").Value 

 


At the moment it seems excluding the error the data is taken correctly but I have a bit of trouble understanding where the problem could be.

I attach the portion of code fixed:

	Private Sub FillBomRowsList(oBomRows As BOMRowsEnumerator, ESBomRows As List(Of EdilSiderBomRow))
		For Each oRow As BOMRow In oBomRows

			Dim oCompDef As ComponentDefinition
			oCompDef = oRow.ComponentDefinitions.Item(1)
Dim oPropSets As PropertySets
oPropSets = oCompDef.Document.PropertySets

Dim oCustomPropertySet = oPropSets.Item("Inventor User Defined Properties")

			If Not TypeOf oRow.ComponentDefinitions.Item(1) Is VirtualComponentDefinition Then
				If oRow.ComponentOccurrences(1).Type = ObjectTypeEnum.kComponentOccurrenceObject Then

					Dim component As ComponentOccurrence = CType(oRow.ComponentOccurrences(1), ComponentOccurrence)
					If component.OccurrencePropertySetsEnabled Then
						'

						Try
							ESBomRow.iSpare = component.OccurrencePropertySets(1).Item("Spare").Value.ToString()
						Catch ex As Exception
						End Try
					Else
						Try
							ESBomRow.iSpare = oCustomPropertySet.Item("Spare").Value ' iProperties Spare
						Catch ex As Exception
						End Try

					End If

				ElseIf oRow.ComponentOccurrences(1).Type = ObjectTypeEnum.kComponentOccurrenceProxyObject Then

					Dim componentProxy As ComponentOccurrenceProxy = CType(oRow.ComponentOccurrences(1), ComponentOccurrenceProxy)

					If componentProxy.NativeObject.OccurrencePropertySetsEnabled Then
						

					End If
					Try
						ESBomRow.iSpare = componentProxy.NativeObject.OccurrencePropertySets(1).Item("Spare").Value ' Proprietà istanza Spare
					Catch ex As Exception
					End Try
				Else
					Try
						ESBomRow.iSpare = oCustomPropertySet.Item("Spare").Value ' iProperties Spare
					Catch ex As Exception
					End Try

				End If
			End If

		Next
	End Sub
0 Likes
Message 4 of 11

C_Haines_ENG
Collaborator
Collaborator

Could you attach the files you're working with?

 

Otherwise, it doesn't look like you adapted my code at all. You still are only taking the first occurrence. You don't need to cast a type, I haven't used "occurrence property sets" so I don't think that's the method you want to go with. Grabbing the "native object" of what you are defining as a proxy object is a recipe for disaster because 9 times out of 10 you already have the native object, and asking for a native objects, native object, will result in an E-FAIL error (If I remember correctly). You also aren't specifying "Inventor User Defined Properties" and writing a "1" instead, but I don't think inventor actually keeps the index position of those categories in the same place per document.

 

Try running my code on its own, and seeing if its pulling the correct data. When troubleshooting these kinds of issues its best to start as simple as possible and build from there. 

 

0 Likes
Message 5 of 11

marco_bonacina5834P
Enthusiast
Enthusiast

No, I didn't start from your code but I modified my previous one before you replied. In the next few days I'll do a test starting from your portion of code and I'll inform you of the result.
Thanks for the tip

0 Likes
Message 6 of 11

marco_bonacina5834P
Enthusiast
Enthusiast

Hi, I did a couple of tests but it doesn't work, with the custom property "spare" it doesn't return any value, then I tried with the part number but as a result it only gave the value of the upper assembly.
Maybe I explained myself badly, I'll post an image of what I would like to export to an excel sheet along with the other iProperties that I need.

marco_bonacina5834P_0-1737353562819.png

As you can see, in the third row the "Spare" property is set to instance.

Thanks.

0 Likes
Message 7 of 11

WCrihfield
Mentor
Mentor

Hi guys.  I'm just going to drop a few things into this conversation that may help some.

First of all, you are dealing with 'instance properties' here, which are different than 'custom iProperties', even though they may both seem to utilize the same system.  A single BOMRow can represent any number of 'instances' (BOMRow.ComponentOccurrences) that exist within an assembly (not always just one 'instance').  Therefore, if a single BOMRow represents 6 instances of a part (for example), and only one of those instances has this instance property applied to it, then you would have to iterate through each of the instances in the collection which that BOMRow represents to find what you are looking for.  Yes, a BOMRow object does have a property for instance properties (BOMRow.OccurrencePropertySets), but that is generally for 'applying' instance properties to all instances which that BOMRow represents, but not the greatest for retrieving existing instance properties when there are potentially different instances within that row's ComponentOccurrences collection that potentially have different properties, with potentially different values.  If every instance has the same instance property assigned to it, with the same value, then you might as well just use the custom iProperties of the referenced document, unless that referenced document is ReadOnly for some reason.  So, it may make more sense to simply iterate through all of the ComponentOccurrences, and use their ComponentOccurrence.OccurrencePropertySets property.  But that is just my 2 cents, so you can take it or leave it.

 

The ProxyObject.NativeObject property does not always lead to the 'original', non-proxy object either.  It can lead to a lower level proxy object, if that is what this proxy was based on.  An example of this is when you have a part occurrence that is within a sub assembly occurrence, and that sub assembly occurrence is in the main assembly.  A proxy object that exists within the main assembly for geometry of that part occurrence will be a proxy of a proxy (2 levels removed from the original), meaning that top level proxy object's 'NativeObject' will be the proxy of that geometry which exists within the context of the sub assembly, instead of within the context of the main assembly, but is still not the original geometry, which only exists within the context of the part document itself.  Then that second level proxy's NativeObject will finally be the original geometry that exists within the context of the part document.

 

And yes, the first 4 PropertySet objects within every Inventor.Document will always be in the same Index order, because they will always pre-exist, and are standard.  So, referring to them by their Index number is a stable way to do it, but perhaps not the most readable/understandable way to do so.  For years I referred to them my their full Inventor API names myself, but have since (past couple of years) switched mostly to referring to them by their Index numbers, mainly because I now know it is safe to do so, is much faster/easier to do so, but often leave myself a 'comment' about which one it is accessing.  But I likely got into that habit more due to a lot of the code I wrote was for others, who may live in other countries, and may speak other languages, in which case using the Index numbers is language independent.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 8 of 11

eugen.gutol
Contributor
Contributor

Hi @WCrihfield

I have a case when I want to do a custom export of BOM to an excel file.

As a default setup, BOM's Merge Instance Rows is disabled, and the export is based on Parts Only view.

When I try to look up the instance row value of a position from BOM using VBA editor and navigating to ComponentOccurrences.Item(1) the properties governing said Instance Properties (OccurrencePropertySets & OccurrencePropertySetsEnabled)  are present but show following error <Application-defined or object-defined error>.

How can I find and read this Occurrence exactly to read the said property ?

 

0 Likes
Message 9 of 11

WCrihfield
Mentor
Mentor

Hi @eugen.gutol.  You mentioned having the one setting/option about merging 'instance rows' turned off, but what about the other similar option about merging rows based on Part Number match?  Is it possible in your Project space or CAD filing system for there to be two or more different model files with the same Part Number value, and both being somewhere in that assembly's overall structure at the same time?  I only ask because the BOMRow.OccurrencePropertySets property's online help documentation says "This only applies to non merged component rows with Instance Properties."  Also, is it possible for that BOMRow to have a quantity of zero, or all of its instances suppressed?  I ask that because there is another setting/option in the BOM called "Hide Suppressed Components in BOM".  I'm not sure if this would matter, but since I rarely use 'virtual' components, I am not sure if they support 'instance' properties, like regular occurrences do, so if you have any rows for virtual components, that may be something to check out also.

I am mostly just making educated guesses here, because I am honestly not sure what might be causing that error.  And, although I sometimes help others out with code examples for navigating BOM's, I don't really do much BOM manipulation by code where I work.  I just happen to understand a lot about accessing that data by code, and help others to understand it better when I can.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 10 of 11

eugen.gutol
Contributor
Contributor

Part Number merge is enabled, Hide Suppressed Components too.

The assembly I started to work is in "ideal" conditions: no suppressed parts, no virtual parts, few parts for faster testing.

I found something that needs more investigation: accessing ComponentOccurrences.Item(x).OccurrencePath and then cycling through them to find the Occ. with same name and then reading the instance property. They are displayed at that level. Seems like going several layers too deep.

0 Likes
Message 11 of 11

WCrihfield
Mentor
Mentor

Ah, yes.  That little detail can also be confusing.  Since these 'instance properties' became available at the same time ModelStates became available, I suspect that they may play an important detail in how they work, or how they get 'recorded'.  It has been my theory that when you are working within an assembly, and choosing component instances to set instance properties to, those instance properties will only exist at that same level of the assembly that you were 'actively editing' at the moment you created them, and likely only when that same ModelState is also active, unless you had the 'Member Edit Scope' set to edit all ModelState members at the same time, in which case all ModelStates of the assembly at that edit level would have recorded them.  So, for example, if you were in-place-editing a top level sub assembly component, then that sub assembly would be the 'active edit document' at that moment, and if you created any instance properties associated with any of of that sub assemblies components, those instance properties would only exist within that sub assembly, not within the 'main / top' assembly.  Same goes for if you created them directly within that sub assembly, while that sub assembly was the 'active' assembly on your screen, before you placed it into a higher level assembly, as a component.  That higher level assembly does not 'adopt' them into its 'scope' directly, so they stay in the 'scope' of that sub assembly document.  Again, just my theory so far.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes