To RETRIEVE BOM STRUCTURE DATA (for OCCURRENCES) in to a notepad document

To RETRIEVE BOM STRUCTURE DATA (for OCCURRENCES) in to a notepad document

RoyWickrama_RWEI
Advisor Advisor
802 Views
8 Replies
Message 1 of 9

To RETRIEVE BOM STRUCTURE DATA (for OCCURRENCES) in to a notepad document

RoyWickrama_RWEI
Advisor
Advisor

I am trying to retrieve BOM Structure data in to a notepad document where I will process data further with an Excel document.

With reference to the sample model I am working with, I find that when an item is made referenced within the assembly (please see IMAGE-2), the rule did not capture BOMStructure data - please see IMAGE-1. I revised the code (please see IMAGE-2). Despite I spent a lot of time, I am not getting it: I request someone help me to get around this issue.

 

IMAGE-1.png

IMAGE-2.png

IMAGE-3.png

0 Likes
Accepted solutions (2)
803 Views
8 Replies
Replies (8)
Message 2 of 9

JamieVJohnson2
Collaborator
Collaborator

Read through your code file.  In the function oReference_at_Assembly, you are returning BOM_Structure.  This object was never defined, populated without definition (bad mojo, and your doing it a lot), or passed in.  It will return nothing every time (or throw an error at that point).

 

Jamie Johnson : Owner / Sisu Lissom, LLC https://sisulissom.com/
Message 3 of 9

RoyWickrama_RWEI
Advisor
Advisor

Thanks for the reply. It is not correct. I did with some different codes as well - finally I left with what I has last and posted in the forum. Could you help me to get around this.

Thanks.

0 Likes
Message 4 of 9

JamieVJohnson2
Collaborator
Collaborator

Give me a bit of time, I'm cleaning up the code.

Jamie Johnson : Owner / Sisu Lissom, LLC https://sisulissom.com/
0 Likes
Message 5 of 9

JamieVJohnson2
Collaborator
Collaborator
Accepted solution
Imports System.Windows.Forms
Sub Main()
	Try
		'This will create the class BOMCrawler, and run its Public Sub New all in one line of code.
		Dim oBOMCrawler As New BOMCrawler
		'this will add the active document, because a class can not use the values This... without them being passed in
		oBOMCrawler.oAssy_ThisDoc = ThisApplication.ActiveDocument
		oBOMCrawler.CrawlBOM
	Catch ex As Exception
		MsgBox ("Sub Main" & vbCrLf & ex.ToString)
	End Try
End Sub
	
'use a class here when you want to define public variables that all other routines (subs and function) can read or modify.	
Public Class BOMCrawler
		
	Public Property oTextSave As String 
	Public Property iLNO As String 
	Public Property oName_Sub As String 'used for error reporting
	Public Property oIndex As Integer 'used for error reporting
	Public Property oTitle As String 'used for error reporting
	Public Property oAssy_ThisDoc As AssemblyDocument 
	Public Property oAssy_CompDef As AssemblyComponentDefinition 
	Public Property BOM_Structure_SourceDoc As String 
	
''' <summary>
''' Initialize public variables
''' </summary>	
	Public Sub New
		Try
			oTextSave  = "C:\Users\Public\Documents\iLogicBuffer.txt"
			iLNO  = "0003-BOM"
			oName_Sub = "New BOM Crawler"
			oIndex = 1
			oTitle = iLNO & "-" & oIndex & " @ SUB: " & oName_Sub
		Catch ex As Exception
			MsgBox(oName_Sub & vbCrLf & oTitle & vbCrLf & ex.ToString)
		End Try
	End Sub
	
	''' <summary>
	''' Process the export of the BOM data to the specified text file
	''' </summary>
	Public Sub CrawlBOM
		oName_Sub = "CrawlBOM"
		Try
			'Get assembly component definition
			Me.oAssy_CompDef = oAssy_ThisDoc.ComponentDefinition 
			MainDoc 'for main document BOM structure
			'crawl through the component occurrences
			For i As Integer = 1 To oAssy_CompDef.Occurrences.Count
				Dim occ As ComponentOccurrence = oAssy_CompDef.Occurrences(i)
				MsgBox(occ.Name & " - " & GetBOMType(occ.BOMStructure))
				RecurReferencing(occ, 0)
			Next
			'open Notepad to the new text file
			Process.Start("Notepad.exe", oTextSave)	
		Catch ex As Exception
			MsgBox(oName_Sub & vbCrLf & oTitle & vbCrLf & ex.ToString)
		End Try
	End Sub
	
	Sub RecurReferencing(oCompOcc As ComponentOccurrence, Level As Integer)
		Try
			'error header
			oName_Sub = "RecurReferencing"
			oIndex = 1
			oTitle = iLNO & "-" & oIndex  & " @ Sub: " & oName_Sub

			'get bom type
			Dim oFFN_cw_EXT As String = oCompOcc.ReferencedDocumentDescriptor.ReferencedDocument.FullFileName	'cw file extension
			Dim oStr As String = oDoc_LocalName_WExt(oFFN_cw_EXT)
			Dim BOM_Structure_Return As String = Func_BOM_Structure(oCompOcc)

			'specify word splitting characters "space" and "dash"
			Dim Separators() As Char = {"*"c} 
			Dim Sentence As String = BOM_Structure_Return
			Dim Words() As String = Sentence.Split(Separators)
			Dim BOM_Structure As String = Words(0)
			Dim oOccurrence_FFN As String = Words(1)

			If Level = 0	 			
				BOM_Structure = oOccurrence_FFN & " <- " & "BOM Structure: " & BOM_Structure
				'error header
				oIndex = 2
				oTitle = iLNO & "-" & oIndex & " @ Sub: " & oName_Sub
				oExtension = Right(oOccurrence_FFN, 3)
			Else
				MessageBox.Show("@ ELSE", "Title")
				If oCompOcc.BOMStructure = BOMStructureEnum.kDefaultBOMStructure Then
					BOM_Structure = oOccurrence_FFN & " <- " & BOM_Structure & "(BOM STATUS: Default)"
				ElseIf oCompOcc.BOMStructure = BOMStructureEnum.kInseparableBOMStructure Then
					BOM_Structure = oOccurrence_FFN & " <- " & BOM_Structure & "(BOM STATUS: Inseparable)"
				ElseIf oCompOcc.BOMStructure = BOMStructureEnum.kNormalBOMStructure Then
					BOM_Structure = oOccurrence_FFN & " <- " & BOM_Structure & "(BOM STATUS: Normal)"
				ElseIf oCompOcc.BOMStructure = BOMStructureEnum.kPhantomBOMStructure Then
					BOM_Structure = oOccurrence_FFN & " <- " & BOM_Structure & "(BOM STATUS: Phantom)"				
				ElseIf oCompOcc.BOMStructure = BOMStructureEnum.kPurchasedBOMStructure Then
					BOM_Structure = oOccurrence_FFN & " <- " & BOM_Structure & "(BOM STATUS: Purchased)"
				ElseIf oCompOcc.BOMStructure = BOMStructureEnum.kVariesBOMStructure Then
					BOM_Structure = oOccurrence_FFN & " <- " & BOM_Structure & "(BOM STATUS: Varies)"
				End If
			End If

			If Level = 0	 			
			'		MessageBox.Show("oStr @ Level = 0: " & BOM_Str_Return, oTitle)
				BOM_Str_Return =  oOcc_FFN_X_Return & "(BOM STATUS: " & BOM_Str_Return & ")"
			Else
				MessageBox.Show("oStr @ Level: " & Level _
				& vbLf & "oStr: " & oStr, oTitle)
				BOM_Str_Return = oOcc_FFN_X_Return & BOM_Str_Return & ")"
			End If

			If oCompOcc.SubOccurrences.Count = 0
				Using oWrite = System.IO.File.AppendText(oTextSave)
					oWrite.WriteLine(BOM_Structure)	
					oWrite.Flush()
				End Using
			Else
				For Each oSubocc In oCompOcc.Definition.Occurrences
					RecurReferencing(oSubocc, Level + 1)
				Next
			End If
		Catch ex As Exception
			MsgBox(oName_Sub & vbCrLf & oTitle & vbCrLf & ex.ToString)
		End Try
	End Sub
	
	''' <summary>
	''' Get and format sub path of file including file name and extension
	''' </summary>
	''' <param name="oFFN_cw_EXT">Full file path</param>
	Function oDoc_LocalName_WExt(oFFN_cw_EXT As String)
		'error header
		oName_Sub = "oDoc_LocalName_WExt"
		oTitle = iLNO & " @ SUB: " & oName_Sub
		
		'get sub path of file including file name and extension
		oPos = Len(oFFN_cw_EXT) - InStrRev(oFFN_cw_EXT, "\", -1)
		oName_Local_cw_Ext = Right(oFFN_cw_EXT, oPos)
		Return oName_Local_cw_Ext 'Local file name complete with extension
	End Function
		
	''' <summary>
	''' Get BOM Structure Enum and combine with full file name
	''' </summary>
	''' <param name="oCompOcc"></param>
	Function Func_BOM_Structure(oCompOcc As ComponentOccurrence)
	    'error header
		oName_Sub = "BOM_Structure"
		oIndex = 1
		oTitle = iLNO & "=" & oIndex & " @ Sub: " & oName_Sub
		'get full file name
		oFFN_X = oCompOcc.ReferencedDocumentDescriptor.ReferencedDocument.FullFileName
		Dim BOM_Structure As String = GetBOMType(oCompOcc.BOMStructure)
		oDoc_LocalName_WExt(oFFN_X)
		Dim BOM_Structure_Return As String = BOM_Structure & "*" & oFFN_X
		Return BOM_Structure_Return
	End Function
	
	''' <summary>
	''' Process the top file of the BOM tree, then initialize and save data to file.  This method does not return a value.
	''' </summary>
	Sub MainDoc()
		'To retrieve BOM structure of current documrny
		oName_Sub = "MainDoc()"
		oIndex = 1
		oTitle = iLNO & "-" & oIndex & " @ SUB: " & oName_Sub
		Dim BOM_Structure_SourceDoc As String = GetBOMType(Me.oAssy_CompDef.BOMStructure)

		'Dim oModel_Occurence As ComponentOccurrence 
		Dim oFFN As String = oAssy_ThisDoc.FullFileName
		Dim oPos_FFN As Integer = InStrRev(oFFN, "\", - 1)
		Dim docFName As String = Right(oFFN, Len(oFFN) - oPos_FFN)
		Clipboard.SetText(docFName)
		Using oWrite As System.IO.StreamWriter = System.IO.File.CreateText(oTextSave)	
			oWrite.WriteLine("FILE REFERENCE TREE RAN FROM: " & oFFN)
			Dim docFName_cw_BOM As String = docFName & " <- " & "(BOM STATUS: " & BOM_Structure_SourceDoc & ")"
			oWrite.WriteLine(docFName_cw_BOM) 
			oWrite.WriteLine("---------------------------------------------------------------------------------------------------------------------")
		End Using
	End Sub
	
	''' <summary>
	''' Get the BOM type string from the BOMStructureEnum
	''' </summary>
	''' <param name="oBomStructure">BOMStructure(Enum) from component occurrence</param>
	''' <returns></returns>
	Public Function GetBOMType(oBomStructure As Inventor.BOMStructureEnum) As String
		Dim BOM_Structure_SourceDoc As String = "Unknown BOM Structure"
		'Select BOM Structure 
		Select Case oBomStructure
			Case = BOMStructureEnum.kDefaultBOMStructure
				BOM_Structure_SourceDoc = "Default"
			Case = BOMStructureEnum.kNormalBOMStructure
				BOM_Structure_SourceDoc = "Normal"
			Case = BOMStructureEnum.kPhantomBOMStructure
				BOM_Structure_SourceDoc = "Phantom"
			Case = BOMStructureEnum.kReferenceBOMStructure
				BOM_Structure_SourceDoc = "Reference"
			Case = BOMStructureEnum.kPurchasedBOMStructure
				BOM_Structure_SourceDoc = "Purchased"
			Case = BOMStructureEnum.kInseparableBOMStructure
				BOM_Structure_SourceDoc = "Inseparable"
			Case = BOMStructureEnum.kVariesBOMStructure
				BOM_Structure_SourceDoc = "Varies" 
		End Select
		Return BOM_Structure_SourceDoc
	End Function
				
End Class

So I really ripped your code structure a new one.  But fundamentally the error is in the call Func_BOM_Structure, when you call to the oCompOcc.Definition.BOMStructure instead of oCompOcc.BOMStructure.

 

 

Jamie Johnson : Owner / Sisu Lissom, LLC https://sisulissom.com/
Message 6 of 9

RoyWickrama_RWEI
Advisor
Advisor

Hi Jamie;

 

It looks too good. Also a great help to getting used to do with classes. I am not a programmer, but I keep learning.

 

It is a great help. I am eager to accept this as a solution, but just let me go through and run a sample test.

 

Again, THANKS.

0 Likes
Message 7 of 9

JamieVJohnson2
Collaborator
Collaborator
Accepted solution

Honestly, I took the time to change the code up as a method to teach some coding.

1:  Using select case statement instead of a bunch of if statements.

2:  Calling a function vs a sub, functions return values sub's don't.  So if you don't plan on returning anything, just make it a sub.

3:  Combining like processes, this you already get, but squeeze more commonality (normalizing) make for easier to read code (most of the time).

4:  Classes vs Modules.  Technically this is beyond the scope of iLogic and more into VB.Net's realm.  But when you were defining variables without definitions, and scattering them all over the place, and passing them around back and forth, you tend to loose sight of the 'scope' of that variable.  In a class, you can define variables up top (and in a module, but not an iLogic module for some reason), then reuse them without redefining or passing them all over the code structure.  But Classes have to be instantiated (hence the oClass = new Class) in order to be created when using.  Think of a class as a custom tool bucket that holds precisely the tools you want (form fitting foam snap in tool buckets).  When you want to use it, you must first put the tools into it.

5:  Defining variables, define them when they are being created, even if you don't have too (modern code editors and put up with it), because that helps you to find and read the variable's scope.  Scope is important, because it could be for the entire rule, just the method, or several times in the method.  If you place a new variable of the same name and the editor lets you, think to yourself, is it creating a new data bucket, or tying into the other one with the same name.  This creates problems where you think your editing a value, and your actually editing a different value, or you think your editing a different value and your actually overwriting a common value.  Scope is important.  Cleaning that up will keep you from getting confused.

6: Indentation.  Clean code makes for fast reading code.  For me to take the time to read your long bits of code is very rare on here, you just got lucky today.  For better help, make clean indentation, 'tight' separation, and notes...

7. Notes, if you type ''' by the third ' the iLogic editor will create the standard xml notation header for you properties and methods.  These allow you to hover over the name of the method elsewhere and read your notes describing the method and what it does.  You can also just put simple comments to separate logical sections of code (this you already know).  I like to 'comment my notes like an outline then write the code between the comments.

8:  New ideas vs old.  When you come up with a new idea, that makes an old one obsolete, rem out the code, until you prove out the new idea, then DELETE the old code to clean up your text.  Makes for faster reading.

 

I regret I couldn't use the Logging.Info method inside of the class (still figuring that one out), but if you create a class free rule, then you can use Logging.Info, and open the iLogic Log window (see the + button next to the model window).  This allows you to dump values into a text pane while the code is running.  Old school is the 1 million message box method.  I had to test to see if the value expected was the value being gotten.

 

Inventor clearly knew what the value expected was.  The issue was getting the BOM of the part definition (of the occurrence) and not the assembly's component occurrence (of the part).

Jamie Johnson : Owner / Sisu Lissom, LLC https://sisulissom.com/
Message 8 of 9

RoyWickrama_RWEI
Advisor
Advisor

Dear Jamie;

 

Morning, I was not feeling bad on myself for bothering you to fix my code. However, the help came with a wealth of learning support and guide lines. I will go through the code thoroughly and will grasp the concept.

I printed both code and the instructions that you posted (usually, I don't print) because I want to read/practice several times.

Thank you SIR, for the help.

Message 9 of 9

RoyWickrama_RWEI
Advisor
Advisor

To fix my message:

 

Should read as:  "... I was feeling bad on myself for bothering you to fix my ...."

 

(It was: "..  I was not feeling bad on myself for bothering you to fix my ..")

You did all well. I am progressing. Planning to use the class idea even for small rules: for getting use at it!

 

Thanks.

0 Likes