Problem accessing Part Only View with BOMViews in iLogic Assembly

Problem accessing Part Only View with BOMViews in iLogic Assembly

Anonymous
Not applicable
2,599 Views
6 Replies
Message 1 of 7

Problem accessing Part Only View with BOMViews in iLogic Assembly

Anonymous
Not applicable

Hi, when I tried to access the Part Only View of the assembly BOM with this code in VBA: (with the Part Only View enabled in BOM Editor beforehand)

 

Public Sub test()
Debug.Print (ThisApplication.ActiveDocument.ComponentDefinition.BOM.BOMViews("Parts Only").Name)
End Sub

I got this error message: "Run-time error '5':Invalid procedure call or argument".

 

Here comes the funny part, this only happens to the assembly files with iLogic rule and iLogic linked LOD (aka iLogic assembly), the code works perfectly with normal assembly without iLogic rule and iLogic linked LOD (output "Part Only" to the immediate window).

 

Later, I found out in the VBA debugger that this code

ThisApplication.ActiveDocument.ComponentDefinition.BOM.BOMViews.count

shows "1" (which is "unnamed") for iLogic assembly and "3" (namely "unnamed", "Structured" and "Parts Only") for normal assembly, when both of them had the Part Only and Structured View enabled in the BOM Editor. 

 

Am I missing something?

 

Thanks 

Lanette

0 Likes
Accepted solutions (1)
2,600 Views
6 Replies
Replies (6)
Message 2 of 7

fulvio81
Contributor
Contributor
Accepted solution

Hi Lanette,

 

here's a VBA sample to get Part Only View

 

Sub GetPartOnlyView()

Dim oDoc As AssemblyDocument
Set oDoc = ThisApplication.ActiveDocument
Dim odef As AssemblyComponentDefinition
Set odef = oDoc.ComponentDefinition

'Get the ActiveLevelOfDetailRepresentation Name
Dim MyLOD_Name As String
MyLOD_Name = odef.RepresentationsManager.ActiveLevelOfDetailRepresentation.Name

If Not MyLOD_Name = "Master" Then
'activate master because only it can do the trick
    Call odef.RepresentationsManager.LevelOfDetailRepresentations.Item(1).Activate
End If

' Set a reference to the BOM
Dim oBOM As BOM
Set oBOM = oDoc.ComponentDefinition.BOM

' Make sure that the PartOnly view is enabled.
oBOM.PartsOnlyViewEnabled = True

'Set a reference to the "Part Only" BOMView
Dim oBOMView As BOMView
Set oBOMView = oBOM.BOMViews.Item("Parts Only")

'do what you want here

MsgBox oBOMView.Name

'set your LOD back
odef.RepresentationsManager.LevelOfDetailRepresentations.Item(MyLOD_Name).Activate

End Sub

Fulvio

 

 

Message 3 of 7

Anonymous
Not applicable

Hi Fulvio, 

 

Thank you for your reply. I can't believe I missed setting the LOD to Master before accessing the Part Only View. Smiley Very Happy

0 Likes
Message 4 of 7

fulvio81
Contributor
Contributor
Ok. Happy that it helps you
0 Likes
Message 5 of 7

chrisw01a
Collaborator
Collaborator

So this is great, however what if you don't want the quantity of ALL parts in the master LOD?

 

If we are using a certain LOD with suppressed parts, how can we get only the quantity of unsuppressed parts?

 

I have some code that I have been using to get total part qty for any given project.  Now we have some assemblies using LOD and this code will not handle it.  Does anyone know how to fix this?

 

The example in this post works, but it gives you the total of all parts in the master...

 

Here is the code I am talking about:

 

'iterate through an assembly and assign a part qty to all parts and sub assemblies

Sub Main
'Rebuild all
ThisDoc.Document.Rebuild()
'Get current document
doc = ThisDoc.Document
Dim oAssyDef As AssemblyComponentDefinition = doc.ComponentDefinition
'Get the BOM object
Dim oBOM As BOM = oAssyDef.BOM
'enable the Parts Only View
oBOM.PartsOnlyViewEnabled = True
'Get the Parts Only view of the BOM
Dim oBOMViewPO As BOMView = oBOM.BOMViews.Item("Parts Only")
'declare variable for each BOM row.
Dim oBOMRowPO As BOMRow
'Set the name of the custom iProperty
'Dim oIPropertyName As String = "TotalPartQty"
'MessageBox.Show("debug")

'For each row in the Parts Only BOM, do the following
For Each oBOMRowPO In oBOMViewPO.BOMRows
	'Set a reference to the primary ComponentDefinition of the row
	Dim oCompDef As ComponentDefinition = oBOMRowPO.ComponentDefinitions.Item(1)
	
		'get the full filename associated to the component in the row. ex: c:\temp\part1.ipt
		Dim CompFullDocumentName As String = oCompDef.Document.FullDocumentName
		Dim CompFileNameOnly As String
		'get the location of the last backslash
		Dim index As Integer = CompFullDocumentName.lastindexof("\")
		'get the filename only from the full filename
		CompFileNameOnly = CompFullDocumentName.substring(index+1)
		'MessageBox.Show(CompFileNameOnly)
		'get the Qty value in the current row
		Dim Qty As String = oBOMRowPO.TotalQuantity
		'check to see if the component is a library part, cc part or read only.
		Dim IsLibCCReadonly As Boolean = LibCCReadonlyChecker(CompFullDocumentName)
		
			'if the file is NOT a library part, cc part or read only.
			If IsLibCCReadonly = False Then
			'set following custom iproperty to equal the QTY from the row
			iProperties.Value(CompFileNameOnly, "Custom", "TotalPartQty") = Qty
			'set built in iProperty
			'iProperties.Value(CompFileNameOnly, "Status", "Mfg. Approved By") = Qty + " RQD"
		
			End If
Next

'At this time, the qty value for all parts have been copied to the custom property.'next, the following code will cycle through only the subassemblies.

'if the Structured BOM view is enabled then...
If oBOM.StructuredViewEnabled Then
	'If show First Level is set then turn it off. This will set it to All Levels
	If oBOM.StructuredViewFirstLevelOnly Then
	oBOM.StructuredViewFirstLevelOnly = False
	End If
Else
	'enable the Structured BOM view
	oBOM.StructuredViewEnabled = True
	'set the FirstLevelOnly to false therefore make it All Levels
	oBOM.StructuredViewFirstLevelOnly = False
End If

'Get the Structured view of the BOM
Dim oBOMViewStruc As BOMView = oBOM.BOMViews.Item("Structured")
'declare variable for each BOM row.
Dim oBOMRowStruc As BOMRow
'Create a blank array(list). This will be used to store a list of all subassemblies for comparing if the subassembly already exist.
Dim arrSubAssemblyList As New ArrayList
'call a subroutine to cycle through the structured BOM. It will need the collection of rows, the subassembly list, and 1 is the initial parentqty.
Call QueryBOMRowProperties(oBOMViewStruc.BOMRows, arrSubAssemblyList, 1)

End Sub


Private Sub QueryBOMRowProperties(oBOMRows As BOMRowsEnumerator, arrSubAssembly As ArrayList, oParentQty As Integer)
'declare a incrementer variable
Dim i As Long
	'for each row in the structured BOM
	For i = 1 To oBOMRows.count
	'get the row based on the incrementer
	Dim oBOMRowStruc As BOMRow = oBOMRows.item(i)
	'get the component definition assocated with the row
	Dim oCompDef As ComponentDefinition = oBOMRowStruc.ComponentDefinitions.item(1)
	Dim oQty As Integer
		'If the component is an assembly and it's bom structure is Normal then do the following. else do nothing
		If TypeOf oCompDef Is AssemblyComponentDefinition And oCompDef.BOMStructure = BOMStructureEnum.kNormalBOMStructure Then
		'get the full filename associated to the component in the row. ex: c:\temp\subassembly.iam
		Dim CompFullDocumentName As String = oCompDef.Document.FullDocumentName
		Dim CompFileNameOnly As String
		'get the location of the last backslash
		Dim index As Integer = CompFullDocumentName.lastindexof("\")
		'get the filename only from the full filename
		CompFileNameOnly = CompFullDocumentName.substring(index+1)
		'MessageBox.Show(CompFileNameOnly)
		'get the qty of the row and multiply by the parent qty.
		oQty = oBOMRowStruc.ItemQuantity * oParentQty
		'create a variable that will be used to get the qty of the subassembly if it was used elsewhere
		Dim additionalQty As Integer = 0
		'if the subassembly list is not empty then...
			If arrSubAssembly.Count <> 0 Then
			'create a counter. this will be used to determine which item in the subassembly array (list) when it finds a match.
			'this counter will be used to edit that item with the new qty.
			Dim counter As Integer = 0
			'for each item in the subassembly array (list) starting at 0 (first item) to last item
				For j As Integer = 0 To arrSubAssembly.Count-1
				'get the location of the colon
				Dim commaindex As Integer = arrSubAssembly(j).indexof(":")
				'get just the file name
				Dim CompName As String = arrSubAssembly(j).substring(0,commaindex)
				'if the file name of the current row matches the current item in the subassembly array (list) then...
					If CompName = CompFileNameOnly Then
					'set the additional qty to the qty found in the subassembly array (list)
					additionalQty = arrSubAssembly(j).substring(commaindex+1)
					'set the counter equal to the item in the subassembly array (list)
					counter = j
					'since a match is found, we need to exit the for loop so that counter no longer increments.
					'so Set j To the number of items in the subassembly array. this will exit out the for loop.
					j = arrSubAssembly.Count
					Else
					'increase the counter
					counter += 1
					End If
				Next
					'if additional qty was not changed then there was no match. It will be a new item in the subassembly array (list)
					If additionalQty = 0 Then
					'add the subassambly to the subassembly array (list)
					arrSubAssembly.add(CompFileNameOnly & ":" & oQty)
					Else
					'if it did find a match, then update the qty for that item in the subassembly array (list)
					arrSubAssembly(counter) = CompFileNameOnly & ":" & oQty + additionalQty
					End If
				Else
				'add the first subassembly to the list. It will add the filename and the qty separated by a colon. ex. subassembly.iam:2
				arrSubAssembly.add(CompFileNameOnly & ":" & oQty)
			End If
				'check to see if the component is a library part, cc part or read only.
				Dim IsLibCCReadonly As Boolean = LibCCReadonlyChecker(CompFullDocumentName)
					'if the file is NOT a library part, cc part or read only.
					If IsLibCCReadonly = False Then
					
					'(original code)
					'set following custom iproperty to equal the QTY from the row plus the additional qty value
					'iProperties.Value(CompFileNameOnly, "Custom", "PartQty") = oQty + additionalQty
					
					'add QTY from the row plus the additional qty value
					Dim qtyPlusAdd As String = oQty + additionalQty
					
					'set following iproperty to equal the QTY from the row plus the additional qty value
					iProperties.Value(CompFileNameOnly, "Custom", "TotalPartQty") = qtyPlusAdd
					'iProperties.Value(CompFileNameOnly, "Status", "Mfg. Approved By") = qtyPlusAdd + " RQD"
					
					'Recursively iterate child rows if present.
						If Not oBOMRowStruc.ChildRows Is Nothing Then
						'recall the subroutine, push the childrows of the sub, sub assembly array (list), and the qty of the subassembly
						Call QueryBOMRowProperties(oBOMRowStruc.ChildRows, arrSubAssembly, oQty)
						End If
				End If
		End If
	Next
End Sub


Private Function LibCCReadonlyChecker(filename As String) As Boolean
	' Get the active project
	Dim oProject As DesignProject = ThisApplication.DesignProjectManager.ActiveDesignProject
	' Get all the library paths
	Dim oLibraryPaths As ProjectPaths = oProject.LibraryPaths
	Dim oLibraryPath As ProjectPath
	'for each library path in the list of all library paths
	For Each oLibraryPath In oLibraryPaths
		'get the library path
		Dim oLibs As String = oLibraryPath.Path
		'if the file is in a library path then Return True
		If filename.Contains(oLibs) = True Then
			Return True
		End If
	Next
	'if the file is in the CC location then Return True
	If filename.Contains(oProject.ContentCenterPath) = True Then
		Return True
	End If
	'get read only status
	Dim File_Attr As Long = System.IO.File.GetAttributes(filename)
	'if the file is readonly or readonly and archieve then Return True
	If File_Attr = 1 Or File_Attr = 33 Then
		Return True
	End If
	'return False if it's not a library, CC or a Readonly part.
	Return False
End Function
0 Likes
Message 6 of 7

MechMachineMan
Advisor
Advisor

LOD's DO NOT and HAVE NEVER worked for adjusting BOM quantities for placing orders.

 

The best thing to do is use a view rep with the parts you dont want hidden, then place that model with that view rep activated in a drawing, and place an all-levels parts list. Export that parts list and voila.

 

It's been said 100+ times; it'll be said 100+ more. LOD is for memory management, and nothing more.


--------------------------------------
Did you find this reply helpful ? If so please use the 'Accept as Solution' or 'Like' button below.

Justin K
Inventor 2018.2.3, Build 227 | Excel 2013+ VBA
ERP/CAD Communication | Custom Scripting
Machine Design | Process Optimization


iLogic/Inventor API: Autodesk Online Help | API Shortcut In Google Chrome | iLogic API Documentation
Vb.Net/VBA Programming: MSDN | Stackoverflow | Excel Object Model
Inventor API/VBA/Vb.Net Learning Resources: Forum Thread

Sample Solutions:Debugging in iLogic ( and Batch PDF Export Sample ) | API HasSaveCopyAs Issues |
BOM Export & Column Reorder | Reorient Skewed Part | Add Internal Profile Dogbones |
Run iLogic From VBA | Batch File Renaming| Continuous Pick/Rename Objects

Local Help: %PUBLIC%\Documents\Autodesk\Inventor 2018\Local Help

Ideas: Dockable/Customizable Property Browser | Section Line API/Thread Feature in Assembly/PartsList API Static Cells | Fourth BOM Type
0 Likes
Message 7 of 7

chrisw01a
Collaborator
Collaborator
Sounds like we might need to change our workflow then...

Thank you for the information.