Owning Component of Workpart

Hello,

is there a nice and easy way to get the owning component of a workpart? I have a big assembly as the displayed part and made a component of a sub-assembly the workpart. Now I need to find out to which sub-assembly this part belongs. I tried workPart.OwningComponent but this function does not return anything at all.

Thanks in advance.

An individual part (where the geometry is created and stored) is known as a "prototype" object. When you add this part as a component to an assembly, the component is known as an "occurrence" object. The occurrences (components) link back to the prototype (part file) so that when the part is modified, the components update accordingly. The prototype (part file) has no knowledge of what assemblies use it as a component. As such, you will need to query the assembly to see where the part is used as a component.

However, if you have a reference to a component, it is fairly easy to get the owning assembly part. A component object has a .Parent property that will return a component object that owns this component (it will return null if no part owns it).

This link shows one way of processing all of the components of a given assembly:
http://nxjournaling.com/content/creating-subroutine-process-all-componen...
This code could be modified to test each component to see if the prototype is the same as the work part. Something like:

if child.Prototype.OwningPart.Equals(workPart) then
'this component is an occurrence of the work part
'query its parent
end if

I tried this code. It works but it may return the wrong parent component if the workpart-prototype is used in more than one subassembly. Any ideas how to get it right?

Public Function getWorkPartParent() As Component

Dim c As ComponentAssembly = displayPart.ComponentAssembly
reportComponentChildren(c.RootComponent, 0)
Return publicWorkComp

End Function

Sub reportComponentChildren(ByVal comp As Component, ByVal indent As Integer)

For Each child As Component In comp.GetChildren()

If child.Prototype.OwningPart.Equals(workPart) Then

publicWorkComp = child.Parent
Exit Sub

End If

reportComponentChildren(child, indent + 1)

Next
End Sub

To find the parent assembly, you will need to start with a component reference. Assemblies own component occurrences, they do not own parts. You'll need to get a reference to the component of interest and go from there.

The code above can tell you all of the parts that own a component occurrence of a given part; that's about the best you can do if your starting point is a part reference.

What workflow are you trying to automate? There may be a fairly easy way to get there. For instance, if the user selects a body occurrence in the assembly, you can query it to see what component it belongs to and what parent assembly owns that component reference.

Thanks for your advice. I was afraid there was no "easy" way to get the owning assembly since NX does not know the exact component occurrence I am searching for when I made it a work part.

I made a journal that allows you to perform various "Save As"-Actions for example saving a part with a higher revision or saving a part with a different name. There are options to save (or copy) the drawing, too (in native NX) and not replace or replace the old part in the displayed assembly. I created a WinForm and a user-defined Button to run this journal and it works great. I could post the code if you're interested...

The problem however is when the user wants to save the work part with a different name and NOT replace every instance in the session but only in the assembly it is directly subordinated to. To use ReplaceComponentBuilder I have to know the exact component occurrence and the assembly it belongs to.

Is your code running when the user changes the work part? If so, you should be able to get a reference to the chosen component.

If the work part is changed before your code is called, perhaps the form could show all the assemblies that use that part as a component and prompt the user to select which one(s) to replace the component.

There is a "change work part" user exit that you should be able to take advantage of if you have a development license. Once you register your code properly with NX, it will execute the code whenever that event happens in NX. Perhaps your code could take advantage of this directly, or perhaps there would be a "helper" program that somehow records or saves a reference to the component chosen in the change work part event. Your main program could then query the last component chosen to be the work part for its operations. According the the NX help, the "change work part" exit should fire "before a Component is chosen or when the work part is about to be changed from any other explicit user interface entry point ".

User code submissions are always welcome!
If you email it to me (info@nxjournaling.com) along with a short explanation of its intended use, I'll post it as an article on the site. There will be a link to it on the front page (until newer articles eventually bump it down).

The code is called after changing the work part and unfortunately we don't have a development license.

I decided to let the user choose a new option called "save selected part as and replace in assembly" when a component is selected. Once NX knows the selected component it is fairly easy to trace the assembly.

I'll send you an e-mail once I finished debugging. Thanks for your help! Here's the code to get the selected components assembly:

Public Function getCompParent(ByVal comp As Component) As Component

Return comp.OwningComponent

End Function

Public Function getSelectedComp() As Component

' Abfrage ob ein Teil selektiert ist
Dim intNumSelected As Integer = theUI.SelectionManager.GetNumSelectedObjects()

If intNumSelected = 0 Then Exit Function

Dim SelectedList As New List(Of Component)
For i As Integer = 0 To intNumSelected - 1

Dim intType As Integer
Dim intSubType As Integer

Dim objSelected As NXObject = theUI.SelectionManager.GetSelectedObject(i)
theUFS.Obj.AskTypeAndSubtype(objSelected.Tag, intType, intSubType)

If intType = UFConstants.UF_component_type Then

Dim theComp As Component = DirectCast(objSelected, Component)
If inList(theComp, SelectedList) = False Then SelectedList.Add(theComp)

End If

Next

If SelectedList.Count = 1 Then

Return SelectedList.Item(0)

Else

theUISession.NXMessageBox.Show("Fehler", NXOpen.NXMessageBox.DialogType.Error, "Mehr als eine oder keine Komponente ausgewählt!")

End If

End Function

Public Function inList(ByVal comp As Component, ByVal l As List(Of Component)) As Boolean

For x As Integer = 0 To l.Count - 1

If l.Item(x).DisplayName = comp.DisplayName Then

Return True
Exit For

End If

Next

End Function

The inList function should return False if the component is not found. Also, you can use the .Contains method of the list object to simplify the code a bit.

Public Function inList(ByVal comp As Component, ByVal l As List(Of Component)) As Boolean

If l.Contains(comp) then
Return True
Else
Return False
End if

End Function

If you use a HashSet rather than a List, you don't need the InList function. Each item in a HashSet occurs exactly once. When you add an item, the Add function checks to see if that item is already present.

I am not sure if I am following this post correctly but it seems like you need to start with the assembly or sub assembly as the displayed part and the component file as the work part. I am trying to start with a single component part as the displayed part and the owning assembly or assemblies are loaded in the current session. Would it be possible to search all of the parts in the current session and get a list of the owning assemblies of the currently displayed component? This would be the same list as shown when the part is right clicked and "Display Parent" is selected.

"Would it be possible to search all of the parts in the current session and get a list of the owning assemblies of the currently displayed component?"

Yes this is possible.

There is some code posted on the eng-tips website by user CNSZU that may be of interest to you.

http://www.eng-tips.com/viewthread.cfm?qid=351100

http://www.eng-tips.com/viewthread.cfm?qid=351988

How about
Session.GetSession().Parts.WorkComponent
The API reference says
"This is the component in the displayed part's NXOpen.Assemblies.ComponentAssembly which represents the current work part. "

Hello,

What is the line code that recognizes if the component of the assembly (children no assemblies or subassemblies) is empty with no object or body or displayableobject for example

Public Sub AddComponentsToList(ByRef Father As Component, ByRef compList As ArrayList)

For Each Newchild As Component In Father.GetChildren()
If Newchild.GetChildren.Length = 0
compList.Add(Newchild)
End If
AddComponentsToList(Newchild, compList)
Next

End Sub

What I am looking for is the children only which has no object or no body or no displayableobject.In Other word, empty component.

I found this UF_ASSEM_count_objs_in_comp in NXOPEN user Function and I am not sure if this will help too.
https://docs.plm.automation.siemens.com/data_services/resources/nx/11/nx...
The current example in C language.
https://docs.plm.automation.siemens.com/data_services/resources/nx/11/nx...

Your help is really appreciated.Thank You

Raeed Kena
{Mechanical / Civil Engineer}

I've not used the UF_ASSEM_count_objs_in_comp function, but it looks promising for what you are trying to do. The UF_ASSEM_cycle_objs_in_comp might be a viable alternative. I'm not sure if either of those functions will report components. Some assemblies will have components but no other geometry in the file; don't forget to check for this condition.