Assembly Load Function
Assembly Load Function
(OP)
I am trying to write a journal to load select components of an assembly based off user input. It has quickly gone over my head, any help would be greatly appreciated.
We generally have our "Assembly Load Options" set to "Structure Only". Once the main assembly is loaded the user loads only what is needed to complete the task.
My intent was to have the user enter a portion of the file name and the program would search for files in the assembly containing this string of text and load it.
I ignore the first five characters when searching file names because this is typically our job number.
The program below seemed to be working until it had to go 4-5 sub-assemblies deep, or at least that is what I think.
Thanks,
Kevin
NX8.0
VB.Net
Imports System
Imports NXOpen
Imports NXOpen.UF
Imports NXOpen.Utilities
Imports System.Collections
Imports System.Windows.Forms
Imports System.Collections.Generic
Imports NXOpenUI
Module NXJournal
Dim theSession As Session = Session.GetSession()
Dim theUFSession As UFSession = UFSession.GetUFSession()
Dim workPart As Part = theSession.Parts.Work
Dim UserInputNumber As String
Dim lw As ListingWindow = theSession.ListingWindow
Sub DoIt()
Dim allComps() As Assemblies.Component = Nothing
Dim CompCounts() As Integer = Nothing
getAllChildrenPacked(workPart, allComps, CompCounts)
For ii As Integer = 0 To allComps.Length - 1
Echo(allComps(ii).DisplayName & " X " & CompCounts(ii))
Next
End Sub
Sub getAllChildrenPacked(ByVal assy As BasePart, ByRef children() As Assemblies.Component, ByRef counts() As Integer)
Dim theChildren As Collections.ArrayList = New Collections.ArrayList
Dim theCounts As Collections.ArrayList = New Collections.ArrayList
Dim theChildNames As Collections.ArrayList = New Collections.ArrayList
For Each child As Assemblies.Component In getAllChildren(assy)
Dim thisChildName As String = child.DisplayName
If theChildNames.Contains(thisChildName) Then
theCounts.Item(theChildNames.IndexOf(thisChildName)) = theCounts.Item(theChildNames.IndexOf(thisChildName)) + 1
Else
theChildren.Add(child)
theChildNames.Add(thisChildName)
theCounts.Add(1)
End If
Next
children = theChildren.ToArray(GetType(Assemblies.Component))
counts = theCounts.ToArray(GetType(Integer))
End Sub
Function getAllChildren(ByVal assy As BasePart) As Assemblies.Component()
Dim theChildren As Collections.ArrayList = New Collections.ArrayList
Dim aChildTag As Tag = Tag.Null
Do
theUFSession.Obj.CycleObjsInPart(assy.Tag, UFConstants.UF_component_type, aChildTag)
If (aChildTag = Tag.Null) Then Exit Do
Dim aChild As Assemblies.Component = NXObjectManager.Get(aChildTag)
theChildren.Add(aChild)
Loop
Return theChildren.ToArray(GetType(Assemblies.Component))
End Function
Public Sub Main(ByVal args As String())
If workPart IsNot Nothing Then
DoIt()
UserInputNumber = NXInputBox.GetInputString("Enter Partial Text of Components To Load", "Text", "")
If UserInputNumber = "" Then
Exit Sub
Else
Dim allComps2() As Assemblies.Component = Nothing
Dim CompCounts2() As Integer = Nothing
Dim theFoundKids As Collections.ArrayList = New Collections.ArrayList
getAllChildrenPacked(workPart, allComps2, CompCounts2)
For Each allComps3 As Assemblies.Component In allComps2
Dim nameCount As Integer = allComps3.DisplayName.ToString.Length
Dim strippedName As String
If nameCount > 8 Then
strippedName = Right(allComps3.DisplayName.ToString, (nameCount-5))
End If
lw.Open()
If strippedName.Contains(UserInputNumber) Then
Dim componentsToOpen1(0) As Assemblies.Component
Dim component2 As Assemblies.Component = allComps3
componentsToOpen1(0) = component2
Dim option1 As Boolean
option1 = theSession.Parts.LoadOptions.UsePartialLoading
lw.Open()
lw.WriteLine(component2.DisplayName.ToString+" component2 Name")
Dim openStatus1() As Assemblies.ComponentAssembly.OpenComponentStatus
Dim partLoadStatus1 As PartLoadStatus
partLoadStatus1 = workPart.ComponentAssembly.OpenComponents(Assemblies.ComponentAssembly.OpenOption.WholeAssembly, componentsToOpen1, openStatus1)
theFoundKids.Add(allComps3)
lw.WriteLine(componentsToOpen1(0).DisplayName.ToString+" componentsToOpen1")
lw.WriteLine(openStatus1(0).ToString+” openStatus”)
partLoadStatus1.Dispose()
If openStatus1(0).ToString = "CouldNotOpen" Then
MessageBox.Show("Unable to load, please load manually")
End If
End If
Next
'-------------------------Error Message if None Found-------------------------------
If theFoundKids.Count < 1 Then
MessageBox.Show("Component Not Found!")
End If
'-------------------------Show Components Getting Loaded---------NOT DONE YET-------------------
lw.WriteLine(theFoundKids.Count.ToString+" theFoundKids")
lw.WriteLine(UserInputNumber.ToString+" UserInputNumber")
lw.Close()
End If
Return
End If
For ii As Integer = 0 To args.Length - 1
Echo("Processing: " & args(ii))
Try
Dim loadStatus As PartLoadStatus = Nothing
workPart = TryCast(theSession.Parts.OpenBaseDisplay(args(ii), loadStatus), Part)
reportPartLoadStatus(loadStatus)
DoIt()
workPart.Close(BasePart.CloseWholeTree.True, BasePart.CloseModified.CloseModified, Nothing)
Catch ex As NXException
Echo(" " & ex.Message)
End Try
Next
End Sub
Sub Echo(ByVal output As String)
'theSession.ListingWindow.Open()
'theSession.ListingWindow.WriteLine(output)
'theSession.LogFile.WriteLine(output)
End Sub
Sub reportPartLoadStatus(ByVal load_status As PartLoadStatus)
If load_status.NumberUnloadedParts = 0 Then
Return
End If
Echo(" Load notes:")
For ii As Integer = 0 To load_status.NumberUnloadedParts - 1
Echo(" " & load_status.GetPartName(ii) & " - " & load_status.GetStatusDescription(ii))
Next
End Sub
Public Function GetUnloadOption(ByVal arg As String) As Integer
Return Session.LibraryUnloadOption.Immediately
End Function
End Module
We generally have our "Assembly Load Options" set to "Structure Only". Once the main assembly is loaded the user loads only what is needed to complete the task.
My intent was to have the user enter a portion of the file name and the program would search for files in the assembly containing this string of text and load it.
I ignore the first five characters when searching file names because this is typically our job number.
The program below seemed to be working until it had to go 4-5 sub-assemblies deep, or at least that is what I think.
Thanks,
Kevin
NX8.0
VB.Net
Imports System
Imports NXOpen
Imports NXOpen.UF
Imports NXOpen.Utilities
Imports System.Collections
Imports System.Windows.Forms
Imports System.Collections.Generic
Imports NXOpenUI
Module NXJournal
Dim theSession As Session = Session.GetSession()
Dim theUFSession As UFSession = UFSession.GetUFSession()
Dim workPart As Part = theSession.Parts.Work
Dim UserInputNumber As String
Dim lw As ListingWindow = theSession.ListingWindow
Sub DoIt()
Dim allComps() As Assemblies.Component = Nothing
Dim CompCounts() As Integer = Nothing
getAllChildrenPacked(workPart, allComps, CompCounts)
For ii As Integer = 0 To allComps.Length - 1
Echo(allComps(ii).DisplayName & " X " & CompCounts(ii))
Next
End Sub
Sub getAllChildrenPacked(ByVal assy As BasePart, ByRef children() As Assemblies.Component, ByRef counts() As Integer)
Dim theChildren As Collections.ArrayList = New Collections.ArrayList
Dim theCounts As Collections.ArrayList = New Collections.ArrayList
Dim theChildNames As Collections.ArrayList = New Collections.ArrayList
For Each child As Assemblies.Component In getAllChildren(assy)
Dim thisChildName As String = child.DisplayName
If theChildNames.Contains(thisChildName) Then
theCounts.Item(theChildNames.IndexOf(thisChildName)) = theCounts.Item(theChildNames.IndexOf(thisChildName)) + 1
Else
theChildren.Add(child)
theChildNames.Add(thisChildName)
theCounts.Add(1)
End If
Next
children = theChildren.ToArray(GetType(Assemblies.Component))
counts = theCounts.ToArray(GetType(Integer))
End Sub
Function getAllChildren(ByVal assy As BasePart) As Assemblies.Component()
Dim theChildren As Collections.ArrayList = New Collections.ArrayList
Dim aChildTag As Tag = Tag.Null
Do
theUFSession.Obj.CycleObjsInPart(assy.Tag, UFConstants.UF_component_type, aChildTag)
If (aChildTag = Tag.Null) Then Exit Do
Dim aChild As Assemblies.Component = NXObjectManager.Get(aChildTag)
theChildren.Add(aChild)
Loop
Return theChildren.ToArray(GetType(Assemblies.Component))
End Function
Public Sub Main(ByVal args As String())
If workPart IsNot Nothing Then
DoIt()
UserInputNumber = NXInputBox.GetInputString("Enter Partial Text of Components To Load", "Text", "")
If UserInputNumber = "" Then
Exit Sub
Else
Dim allComps2() As Assemblies.Component = Nothing
Dim CompCounts2() As Integer = Nothing
Dim theFoundKids As Collections.ArrayList = New Collections.ArrayList
getAllChildrenPacked(workPart, allComps2, CompCounts2)
For Each allComps3 As Assemblies.Component In allComps2
Dim nameCount As Integer = allComps3.DisplayName.ToString.Length
Dim strippedName As String
If nameCount > 8 Then
strippedName = Right(allComps3.DisplayName.ToString, (nameCount-5))
End If
lw.Open()
If strippedName.Contains(UserInputNumber) Then
Dim componentsToOpen1(0) As Assemblies.Component
Dim component2 As Assemblies.Component = allComps3
componentsToOpen1(0) = component2
Dim option1 As Boolean
option1 = theSession.Parts.LoadOptions.UsePartialLoading
lw.Open()
lw.WriteLine(component2.DisplayName.ToString+" component2 Name")
Dim openStatus1() As Assemblies.ComponentAssembly.OpenComponentStatus
Dim partLoadStatus1 As PartLoadStatus
partLoadStatus1 = workPart.ComponentAssembly.OpenComponents(Assemblies.ComponentAssembly.OpenOption.WholeAssembly, componentsToOpen1, openStatus1)
theFoundKids.Add(allComps3)
lw.WriteLine(componentsToOpen1(0).DisplayName.ToString+" componentsToOpen1")
lw.WriteLine(openStatus1(0).ToString+” openStatus”)
partLoadStatus1.Dispose()
If openStatus1(0).ToString = "CouldNotOpen" Then
MessageBox.Show("Unable to load, please load manually")
End If
End If
Next
'-------------------------Error Message if None Found-------------------------------
If theFoundKids.Count < 1 Then
MessageBox.Show("Component Not Found!")
End If
'-------------------------Show Components Getting Loaded---------NOT DONE YET-------------------
lw.WriteLine(theFoundKids.Count.ToString+" theFoundKids")
lw.WriteLine(UserInputNumber.ToString+" UserInputNumber")
lw.Close()
End If
Return
End If
For ii As Integer = 0 To args.Length - 1
Echo("Processing: " & args(ii))
Try
Dim loadStatus As PartLoadStatus = Nothing
workPart = TryCast(theSession.Parts.OpenBaseDisplay(args(ii), loadStatus), Part)
reportPartLoadStatus(loadStatus)
DoIt()
workPart.Close(BasePart.CloseWholeTree.True, BasePart.CloseModified.CloseModified, Nothing)
Catch ex As NXException
Echo(" " & ex.Message)
End Try
Next
End Sub
Sub Echo(ByVal output As String)
'theSession.ListingWindow.Open()
'theSession.ListingWindow.WriteLine(output)
'theSession.LogFile.WriteLine(output)
End Sub
Sub reportPartLoadStatus(ByVal load_status As PartLoadStatus)
If load_status.NumberUnloadedParts = 0 Then
Return
End If
Echo(" Load notes:")
For ii As Integer = 0 To load_status.NumberUnloadedParts - 1
Echo(" " & load_status.GetPartName(ii) & " - " & load_status.GetStatusDescription(ii))
Next
End Sub
Public Function GetUnloadOption(ByVal arg As String) As Integer
Return Session.LibraryUnloadOption.Immediately
End Function
End Module





RE: Assembly Load Function
As an alternative, if you have an Advanced Assemblies license you might consider using Assembly Groups (what we used to call 'filters') to help organize an Assembly so that it's easier to only load those Components which are relevant for what it it that you're attempting to do. Some examples are loading Comoponents by attributes, by size, and even by name where entering the first few letters will filter the list. One defined, these groups can be used to then load only those components defined by a group once you've opend an Assembly using the 'Structure Only' option.
John R. Baker, P.E.
Product 'Evangelist'
Product Engineering Software
Siemens PLM Software Inc.
Industry Sector
Cypress, CA
Siemens PLM:
UG/NX Museum:
To an Engineer, the glass is twice as big as it needs to be.
RE: Assembly Load Function
I am sure a PDM system would be very beneficial but that is a decision I am not part of nor have much influence on.
As far as the Assembly Groups, we do not have enough licenses for all users. However this is something I am still researching.
Thanks for the info!
Kevin
RE: Assembly Load Function
Any ideas, please let me know.
Thanks,
Kevin
Imports System
Imports NXOpen
Imports NXOpen.UF
Imports NXOpen.Utilities
Imports System.Collections
Imports System.Windows.Forms
Imports System.Collections.Generic
Imports NXOpenUI
Module NXJournal
Dim theSession As Session = Session.GetSession()
Dim theUFSession As UFSession = UFSession.GetUFSession()
Dim workPart As Part = theSession.Parts.Work
Dim lw As ListingWindow = theSession.ListingWindow
Dim assy As BasePart = workPart
Dim UserInputNumber As String
Sub Main()
Dim theChildren As Collections.ArrayList = New Collections.ArrayList
Dim aChildTag As Tag = Tag.Null
Do
theUFSession.Obj.CycleObjsInPart(assy.Tag, UFConstants.UF_component_type, aChildTag)
If (aChildTag = Tag.Null) Then Exit Do
Dim aChild As Assemblies.Component = NXObjectManager.Get(aChildTag)
theChildren.Add(aChild)
Loop
theChildren.ToArray(GetType(Assemblies.Component))
If workPart IsNot Nothing Then
UserInputNumber = NXInputBox.GetInputString("Enter Partial Text of Components To Load", "Text", "")
If UserInputNumber = "" Then
Exit Sub
Else
Dim allComps2() As Assemblies.Component = Nothing
Dim CompCounts2() As Integer = Nothing
Dim theFoundKids As Collections.ArrayList = New Collections.ArrayList
For Each allComps3 As Assemblies.Component In theChildren
Dim nameCount As Integer = allComps3.DisplayName.ToString.Length
Dim strippedName As String
If nameCount > 8 Then
strippedName = Right(allComps3.DisplayName.ToString, (nameCount-5))
End If
lw.Open()
If strippedName.Contains(UserInputNumber) Then
Dim componentsToOpen1(0) As Assemblies.Component
Dim component2 As Assemblies.Component = allComps3
componentsToOpen1(0) = component2
Dim option1 As Boolean
option1 = theSession.Parts.LoadOptions.UsePartialLoading
lw.Open()
lw.WriteLine(component2.DisplayName.ToString+" component2 Name")
Dim openStatus1() As Assemblies.ComponentAssembly.OpenComponentStatus
Dim partLoadStatus1 As PartLoadStatus
partLoadStatus1 = workPart.ComponentAssembly.OpenComponents(Assemblies.ComponentAssembly.OpenOption.WholeAssembly, componentsToOpen1, openStatus1)
theFoundKids.Add(allComps3)
lw.WriteLine(componentsToOpen1(0).DisplayName.ToString+" componentsToOpen1")
lw.WriteLine(openStatus1(0).ToString+” openStatus”)
partLoadStatus1.Dispose()
If openStatus1(0).ToString = "CouldNotOpen" Then
MessageBox.Show("Unable to load, please load manually")
End If
End If
Next
End If
End If
End Sub
End Module
RE: Assembly Load Function
Do you get any specific error messages (if so, what are they)? or does the code just not work as you expect?
www.nxjournaling.com
RE: Assembly Load Function
With the first program I posted, it says it cannot load it(message I build in). OpenStatus is CouldNotOpen even though my componentsToOpen1 name and count are correct. I can manually load it with no issues.
The second program I posted is loading the component now but I have to "ok" a bunch of messages boxes for "Could Not Load". Hopefully later today I can do some more testing with this one, when I was testing it last week it was acting the same as the first.