Skip block of code if working through a suboccurance.

Skip block of code if working through a suboccurance.

jzcrouse
Enthusiast Enthusiast
734 Views
6 Replies
Message 1 of 7

Skip block of code if working through a suboccurance.

jzcrouse
Enthusiast
Enthusiast

I am trying to write this code to check if parts in an assembly have a drawing associated with them. 

It does a pretty good job of identifying parts that do not have drawings. 

Currently the code runs and will end with no message boxes if there are no parts missing drawings, however I would like the code to have a "Finished" message once it has run completely through. 

 

My problem is that when there is a subassembly any messagebox will be displayed multiple times if I just put the show messagebox at the end, which can be confusing. Is there a way to work through the parts in the suboccurance and still have a messagebox show saying when the code is done running through the main assembly?

 

Additionally, The current set up displays a separate messagebox with missing drawings for each subassembly. Is there a way i can group all the missing drawings from each sub and the main assembly into one messagebox at the end? 

 

Thanks

 

 

 

 

 

 

Private Sub Main()
    Dim asmDoc As AssemblyDocument
    asmDoc = ThisDoc.Document


    ' Call the function that traverses the assembly

    Call Iterate(asmDoc.ComponentDefinition.Occurrences,1)
    
    ' Update the view.
    ThisApplication.ActiveView.Update
End Sub



Sub Iterate(Occurrences As ComponentOccurrences, Level As Integer)
Dim oAsmCompDef As AssemblyComponentDefinition
oAsmCompDef = ThisDoc.Document.ComponentDefinition

Dim oPart As ComponentOccurrence
Dim oPartpath As String
Dim needsdwg As New ArrayList	
Dim FNamePos As Long
Dim Part_Name As String



'''Iterate through part occurrences in assembly

 
	For Each oPart In Occurrences

		Dim oFileName As String = oPart.Definition.Document.FullFileName
'Check to see if occurance is a Part
Dim partnumber As String = iProperties.Value(oPart.Name, "Project", "Part Number")
		If oPart.DefinitionDocumentType = DocumentTypeEnum.kPartDocumentObject Then


				Dim oDoc As PartDocument = oPart.Definition.Document
	
				If iProperties.Value(oPart.Name, "Custom", "ITS_DTL") = "Y" Then
				FNamePos = InStrRev(oFileName, "\", -1)
				Part_Name = Right(oFileName, Len(oFileName) -FNamePos)
				oPartpath = Left(oFileName, Len(oFileName) -Len(Part_Name))
				
				
					
'sets full file name to search for, drawing must be in same folder as part. 

				Dim Dwgname As String = oPartpath & "\" & partnumber & ".idw"


			
'check to see if drawing file exists 
				If System.IO.File.Exists(Dwgname) = True Then

					
					Else
						'Adds part names without a detail to list
						needsdwg.Add(partnumber)
						
					End If
								
				Else
					
				End If
	

		
	'ignore bolted assemblies.
	
	ElseIf partnumber.Contains("Bolted")=True Then 
	GoTo line1 
	
	'recursively call sub to traverse through occurance if it is a subassembly
	ElseIf oPart.DefinitionDocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
		
			Call Iterate(oPart.SubOccurrences, Level)
        
		
		End If
	line1 :
	
	Next

	
Dim i As Integer
Dim a As Integer

i = needsdwg.Count - 1
Dim partlist(i) As String

For a=0 To i
'moves all items in arraylist to string array.

partlist(a) = needsdwg.Item(CStr(a))
Next
If i = -1 Then
		
		Else
'displays all parts that are missing drawings. 

MessageBox.Show("Drawings needed for " & Join (partlist, ", "))
End If



		
End Sub  

 

0 Likes
Accepted solutions (3)
735 Views
6 Replies
Replies (6)
Message 2 of 7

yan.gauthier
Advocate
Advocate
Accepted solution

Declare a collection in the main assembly and pass it in your Iterate procedure as ref

 

 

sub Iterate(ByRef Occurrences as ComponentOccurrences, ByVal Level As Integer, ByRef MyCollection as Collection)

 

Passing a parameter ByRef means you are sending the actual parameter, not a copy, to your procedure. You can then append value to it and it will retain data when you are back at the main procedure so you can display your message.

 

N.B.: I prefer to use collections since it support both the for each loop and the add method. No need to reDim arrays or to use Ubound, etc...

 

 

0 Likes
Message 3 of 7

WCrihfield
Mentor
Mentor
Accepted solution

@jzcrouse 

You can use a simple If...Then statement to check if the currently processing "Item" within the parent collection = Collection.Count, then a GoTo statement.

You can also, when it doesn't find a drawing, you can simply "Add" the document's FullFileName to a "List(Of String)", then at the end (when count = count) use an InputListBox() to display the list of documents (or just write them to a temporary TXT file).

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 4 of 7

jzcrouse
Enthusiast
Enthusiast

These are good suggestions. However, I am having trouble adding things to a collection. I've tried multiple things mostly looking at this

https://docs.microsoft.com/en-us/dotnet/visual-basic/programming-guide/concepts/collections

 

Sub Iterate(ByRef Occurrences As ComponentOccurrences, ByVal Level As Integer, ByRef needsdwg As List(Of String)) 
needsdwg.Add(partnumber)

 I keep getting "Object reference not set to an instance of an object." So my guess is I have the wrong variable type somewhere. The partnumber variable is a string. 

 My vb.net capabilities are limited as I am used to working within the ilogic bubble. I have not found any guides from inventor on using collections.

 

 

0 Likes
Message 5 of 7

yan.gauthier
Advocate
Advocate
Accepted solution

in your main, declare and initialize your list

 

I am not sure how exactly in VB.Net, but it should be something like

 

Dim needsdwg as New List(Of String)

 

0 Likes
Message 6 of 7

jzcrouse
Enthusiast
Enthusiast

That worked 

Thanks

Here is the final code for anyone interested. This will go through an assembly and its sub-assemblies and display which parts do not have idw's associated with them

 

Private Sub Main()
    Dim asmDoc As AssemblyDocument
    asmDoc = ThisDoc.Document
	'initiate list to be used in sub
Dim needsdwg As New List(Of String)

    ' Call the function that traverses the assembly

    Call Iterate( asmDoc.ComponentDefinition.Occurrences, 1,  needsdwg)
	
	

  ' Update the view.
    ThisApplication.ActiveView.Update
End Sub

'passes a list of parameters and retains info between sub assemblies; byref passes actual parameter

Sub Iterate(ByRef Occurrences As ComponentOccurrences, ByVal Level As Integer, ByRef needsdwg As List(Of String)) 

Dim oAsmCompDef As AssemblyComponentDefinition
oAsmCompDef = ThisDoc.Document.ComponentDefinition
Dim Parentasm As String = ThisAssembly.Document.DisplayName
Dim currentasm As String
Dim oPart As ComponentOccurrence
Dim oPartpath As String	
Dim FNamePos As Long
Dim Part_Name As String
'counts the number of occurances in assembly

Dim count As Integer
count = ThisAssembly.Components.Count


'''Iterate through part occurrences in assembly

 
	For Each oPart In Occurrences

		Dim oFileName As String = oPart.Definition.Document.FullFileName
'Check to see if occurance is a Part
Dim partnumber As String = iProperties.Value(oPart.Name, "Project", "Part Number")
		If oPart.DefinitionDocumentType = DocumentTypeEnum.kPartDocumentObject Then


				Dim oDoc As PartDocument = oPart.Definition.Document
	
				If iProperties.Value(oPart.Name, "Custom", "ITS_DTL") = "Y" Then
				FNamePos = InStrRev(oFileName, "\", -1)
				Part_Name = Right(oFileName, Len(oFileName) -FNamePos)
				oPartpath = Left(oFileName, Len(oFileName) -Len(Part_Name))
				
				
					
'sets full file name to search for, drawing must be in same folder as part. 

				Dim Dwgname As String = oPartpath & "\" & partnumber & ".idw"


			
'check to see if drawing file exists 
				If System.IO.File.Exists(Dwgname) = True Then

					
					Else
						'Adds part names without a detail to list
						
'						needsdwg.add(New dwgs(partnumber), partnumber)
						
						If Not needsdwg.contains(partnumber) Then
							
						needsdwg.Add(partnumber)
					end if
						
					End If
								
				Else
					
				End If
	

		
	'ignore bolted assemblies.
	
	ElseIf partnumber.Contains("Bolted")=True Then 
	GoTo line1 
	
	'recursively call sub to traverse through occurance if it is a subassembly
	ElseIf oPart.DefinitionDocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
		
		
			Call Iterate( oPart.SubOccurrences, 1, needsdwg)
        
		
		End If
	line1 :
	
	Next
'finds if part being processes is in a sub or parent assembly
Try
currentasm = oPart.ParentOccurrence.Name
Catch
	currentasm = Parentasm
End Try


If currentasm = Parentasm Then
	
	Dim partlist As String()=needsdwg.ToArray
	MessageBox.Show("Drawings needed for " & Join (partlist, ", "))


End If



		
End Sub  

 

 

Message 7 of 7

WCrihfield
Mentor
Mentor

Good to hear. 

Here is a couple variations of a simple little external iLogic rule I did a year or two ago that checks if the current document has a drawing file.

It only works if you save your drawing files in the same directory and with the same file name (just different extension) as the Model file.  Doesn't matter if it's a Part or Assembly.

 

If IO.File.Exists(ThisDoc.PathAndFileName & ".idw") Then
	MsgBox("Yes. This model has a Drawing file.")
Else
	MsgBox("No. This model does not have a Drawing file.")
End If
Dim oFFN As String = ThisApplication.ActiveDocument.FullFileName
If IO.File.Exists(Left(oFFN,Len(oFFN)-4) & ".idw") Then
	MsgBox("Yes. This model has a Drawing file.")
Else
	MsgBox("No. This model does not have a Drawing file.")
End If

 

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes