Hello, I'm in need of some assistance in attempting to change the reference set of some components. However I keep on getting errors on the "replaceReferenceSet" calls when attempting to switch the reference set to a true body.
For example:
Sub Main()
Lw.Open()
Dim cvInsertComponent As Component = searchAssembly(displayComponent, "component name string")
Dim cvInsertPart As Part = cvInsertComponent.Prototype.OwningPart
workPart.ComponentAssembly.ReplaceReferenceSet(cvInsertComponent, "TRUE")
Dim ejInsertComponent As Component = searchAssembly(displayComponent, "component name string")
Dim ejInsertPart As Part = ejInsertComponent.Prototype.OwningPart
workPart.ComponentAssembly.ReplaceReferenceSet(ejInsertComponent, "TRUE")
processBodies(cvInsertPart)
processBodies(ejInsertPart)
Lw.Close()
End Sub
Produces the error: NXOpen.NXException: First parameter is invalid...method stub
Sub Main()
Lw.Open()
Dim cvInsertComponent As Component = searchAssembly(displayComponent, "component name string")
Dim ejInsertComponent As Component = searchAssembly(displayComponent, "component name string")
Dim refSetToTrue(2) As Component
refSetToTrue(0) = cvInsertComponent
refSetToTrue(1) = ejInsertComponent
workPart.ComponentAssembly.ReplaceReferenceSetInOwners("TRUE", refSetToTrue)
Dim cvInsertPart As Part = cvInsertComponent.Prototype.OwningPart
Dim ejInsertPart As Part = ejInsertComponent.Prototype.OwningPart
processBodies(cvInsertPart)
processBodies(ejInsertPart)
Lw.Close()
End Sub
Produces the error: NXOpen.NXException: Incorrect object for this operation... method stub
Other possibly useful code:
Module NXJournal
Public NxSession As Session = Session.GetSession()
Public workPart As Part = NxSession.Parts.Work
Public ReadOnly displayComponent As Component = NxSession.Parts.Display.ComponentAssembly.RootComponent
Public Lw As ListingWindow = NxSession.ListingWindow
Sub Main()
re: change reference set
Double check your "searchAssembly" sub/function to make sure that it is:
Re: correct component
Here is the searchAssembly code:
Function searchAssembly(ByVal parentComponent As Component, ByVal searchString As String) As Component
If parentComponent.Name.Equals(searchString) Then
Lw.WriteFullline("Found: " & parentComponent.Name)
Return parentComponent
End If
For Each childComponent As Component In parentComponent.GetChildren
Dim returnComponent As Component = searchAssembly(childComponent, searchString)
If returnComponent IsNot Nothing Then
Return returnComponent
End If
Next
Return Nothing
End Function
The Found: parentComponent.name is returning the correct component name. I additionally added another check in sub main:
Sub Main()
Lw.Open()
Dim cvInsertComponent As Component = searchAssembly(displayComponent, "component name")
Dim cvInsertPart As Part = cvInsertComponent.Prototype.OwningPart
Lw.WriteFullline(cvInsertComponent.Name)
workPart.ComponentAssembly.ReplaceReferenceSet(cvInsertComponent, "TRUE")
This also returns the correct component name. This component name (AFAIK) is and should be unique to the assembly. The code returns the same error as before right after printing out the correct name.
NX 8.5
NX 9.0
re: change ref set
According to the help file, the .ReplaceReferenceSet method only works on top level components. In your case, that means components directly owned by the work part. Your "searchAssembly" routine searches the entire assembly, not just the top level. If you want to change the reference set regardless of the direct owner, you would be better off using the .ReplaceReferenceSetInOwners method. You have indicated that that method is also throwing errors, you can examine the error list to get a better idea of what is going wrong and what actions to take.
Something like:
Dim myErrList As ErrorList
myErrList = workPart.ComponentAssembly.ReplaceReferenceSetInOwners("TRUE", refSetToTrue)
For i As Integer = 0 To myErrList.Length - 1
lw.WriteLine("Error number: " & i.ToString)
lw.WriteLine(" " & myErrList.GetErrorInfo(i).ErrorCode & ": " & myErrList.GetErrorInfo(i).Description)
lw.WriteLine("")
Next
re: errorlist
So here's the problem, my code keeps crashing before I can look at the error list.
And when I do a try-catch to prevent it from crashing, the error list never gets filled up from the replaceReferenceSetInOwners call. This results in a null reference exception when trying to access the error list.
Code
Dim refSetToTrue(2) As Component
refSetToTrue(0) = cvInsertComponent
refSetToTrue(1) = ejInsertComponent
Dim errorList As ErrorList = Nothing
Try
'Code will crash here, never allowing the errorList to be created
errorList = workPart.ComponentAssembly.ReplaceReferenceSetInOwners("TRUE", refSetToTrue)
For i As Integer = 0 To errorList.Length - 1
Lw.WriteLine("Error number: " & i.ToString)
Lw.WriteLine(" " & errorList.GetErrorInfo(i).ErrorCode & ": " & errorList.GetErrorInfo(i).Description)
Lw.WriteLine("")
Next
Catch nxe As NXException
Lw.WriteFullline(nxe.ToString)
End Try
NX 8.5
NX 9.0
re: catch error
In the catch block, list the error code and description.
Catch nxe As NXException
Lw.WriteFullline(nxe.ErrorCode & ": " & nxe.Message)
End Try
catch error output
NXOpen.NXException: Incorrect object for this operation.
at NXOpen.Assemblies.ComponentAssembly.ReplaceReferenceSetInOwners(String newReferenceSet, Component[] components)
at NXJournal.Main() in C:\line 34
NX 8.5
NX 9.0
error code
650004: Incorrect object for this operation.
NX 8.5
NX 9.0
re: changing reference set
Rather than:
workPart.ComponentAssembly.ReplaceReferenceSet(cvInsertComponent, "TRUE")
Try:
cvInsertComponent.DirectOwner.ReplaceReferenceSet(cvInsertComponent, "TRUE")
re: DirectOwner call
Worked like a charm. Any ideas on why?
NX 8.5
NX 9.0
re: direct owner
As I mentioned in an earlier post, .ReplaceReferenceSet only works on top level components, this means it must be called from the component's direct parent assembly. My best guess is the component you are interested in is 2 or more levels deep in the assembly structure. When you execute the line:
workPart.ComponentAssembly.ReplaceReferenceSet(cvInsertComponent, "TRUE")
you get an error because the component is not directly owned by the work part (i.e. it is not a "top level" component in the work part assembly structure). The line of code I gave you will call the .ReplaceReferenceSet method from the direct owner of the component.
Re direct owner
Ah yes. Thank you.
Do you have any ideas on why the .ReplaceReferenceSetInOwners was returning errors? I'm wondering because I've used this method call successfully in the past.
NX 8.5
NX 9.0
Hello,
Hello,
I am trying to realise just the same sort of thing: Change the RefSets for all components that are the children of the current work part component.
Unfortunately I can't find the clue how to do that in journalling. So I hoped to find some working code that I could adapt to my needs. Now I see that I am not able to make things work using these sniplets only. There seems to exist some context that I don't know.
Would you mind to post your solution code here to help me understand how the whole job can be done? That would be a great help.
/UdoMM
re: change ref set
The code below will loop through the displayed part and attempt to change each top level's component reference set to the one named "SOLID". If the component does not have a reference set with that name it will be skipped. Change the refSetName constant to your desired value before running.
Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.UF
Imports NXOpen.Assemblies
Module Module19
Dim theSession As Session = Session.GetSession()
Dim ufs As UFSession = UFSession.GetUFSession()
Dim lw As ListingWindow = theSession.ListingWindow
Const refSetName As String = "SOLID"
Sub Main()
Dim workPart As Part = theSession.Parts.Work
Dim dispPart As Part = theSession.Parts.Display
lw.Open()
Dim c As ComponentAssembly = dispPart.ComponentAssembly
'to process the work part rather than the display part,
' comment the previous line and uncomment the following line
'Dim c As ComponentAssembly = workPart.ComponentAssembly
If IsNothing(c.RootComponent) Then
'no components to process, exit journal
Return
End If
For Each child As Component In c.RootComponent.GetChildren()
Try
child.DirectOwner.ReplaceReferenceSet(child, refSetName)
Catch ex As NXException
'add code to handle error condition
End Try
Next
lw.Close()
End Sub
'**********************************************************
Public Function GetUnloadOption(ByVal dummy As String) As Integer
Return Session.LibraryUnloadOption.Immediately
End Function
'**********************************************************
End Module
re: change ref set
That's much more straightforward than my result - Thank you!
/UdoMM
Make this work recursively
Can we make this work recursively for all levels instead of the first level?
re: make this work recursively
Fortunately for us, there is a method in the NXOpen API called ReplaceReferenceSetInOwners that will do all the work for us. The code below will create a reference set with the specified name in each component part (edit the value of "myRefSetName" to the name of the reference set you want to create before running the code). The journal does not save any of the parts, they will need to be saved if you wish to keep the changes.
Also of note, once the reference set is created in the parts, you can make use the the NX assembly load options (reference sets option) to set each component in the assembly to use a specified reference set when the assembly is opened.
'NXJournaling.com
'June 1, 2022
'Process an assembly:
'create a reference set in each part, add all solid bodies from the part to the new ref set
'change the value of Const myRefSetName to your desired reference set name
'update June 7, 2022
'update components to use the newly created reference set.
Option Strict Off
Imports System
Imports System.Collections.Generic
Imports System.Windows.Forms
Imports NXOpen
Imports NXOpen.UF
Imports NXOpen.Assemblies
Module Module2
Dim theSession As Session = Session.GetSession()
Sub Main()
If IsNothing(theSession.Parts.Display) Then
MessageBox.Show("Active Part Required", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
End If
Dim lw As ListingWindow = theSession.ListingWindow
lw.Open()
'change the following line to the reference set name you want to update/create
Const myRefSetName As String = "TEST"
Dim myAsmInfo As New NXJ_Assembly_info
myAsmInfo.Part = theSession.Parts.Display
For Each tempPart As Part In myAsmInfo.AllUniqueParts
lw.WriteLine(tempPart.Leaf)
'get MODEL reference set
Dim myRefSet As ReferenceSet = Nothing
myRefSet = GetRefSet(tempPart, myRefSetName)
'get all solid bodies in part
Dim partSolidBodies As New List(Of Body)
For Each tempBody As Body In tempPart.Bodies
If tempBody.IsSolidBody Then
partSolidBodies.Add(tempBody)
End If
Next
'add solid bodies to MODEL reference set
myRefSet.AddObjectsToReferenceSet(partSolidBodies.ToArray)
lw.WriteLine(partSolidBodies.Count.ToString & " bodies added to refset: " & myRefSetName)
lw.WriteLine("")
Next
'lw.WriteLine("")
'lw.WriteLine("Parts that could not be loaded")
'lw.WriteLine("------------------------------")
'For Each temp As String In myAsmInfo.NotLoaded
' lw.WriteLine(temp)
'Next
Dim errorList As ErrorList = Nothing
Try
errorList = myAsmInfo.Part.ComponentAssembly.ReplaceReferenceSetInOwners(myRefSetName, myAsmInfo.AllComponents.ToArray)
For i As Integer = 0 To errorList.Length - 1
lw.WriteLine("Error number: " & i.ToString)
lw.WriteLine(" " & errorList.GetErrorInfo(i).ErrorCode & ": " & errorList.GetErrorInfo(i).Description)
lw.WriteLine("")
Next
Catch nxe As NXException
lw.WriteFullline("error: " & nxe.Message)
End Try
End Sub
Function GetRefSet(ByVal thePart As Part, ByVal refSetName As String) As ReferenceSet
Dim theReferenceSet As ReferenceSet = Nothing
For Each myRefSet As ReferenceSet In thePart.GetAllReferenceSets()
If myRefSet.Name.ToUpper() = refSetName.ToUpper Then
theReferenceSet = myRefSet
End If
Next
If IsNothing(theReferenceSet) Then
'the specified reference set does not exist, create it
Dim markId1 As NXOpen.Session.UndoMarkId = Nothing
markId1 = theSession.SetUndoMark(NXOpen.Session.MarkVisibility.Invisible, "Reference Sets")
theReferenceSet = thePart.CreateReferenceSet()
theReferenceSet.SetName(refSetName)
Dim nErrs1 As Integer = Nothing
nErrs1 = theSession.UpdateManager.DoUpdate(markId1)
End If
Return theReferenceSet
End Function
Public Function GetUnloadOption(ByVal dummy As String) As Integer
'Unloads the image immediately after execution within NX
GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately
End Function
End Module
'To process "non-geometric" components, set the environment variable: UGII_ALLOW_NGC_IN_UGOPEN {YES|NO}
Public Class NXJ_Assembly_info
#Region "Private Variables"
Private Const Version As String = "0.2.0"
Private _theSession As Session = Session.GetSession()
Private _theUfSession As UFSession = UFSession.GetUFSession
Private _components As New List(Of Assemblies.Component)
Private _uniqueParts As New List(Of Part)
Private _allComponents As New List(Of Assemblies.Component)
Private _allUniqueParts As New List(Of Part)
Private _notLoaded As New List(Of String)
Private lg As LogFile = _theSession.LogFile
#End Region
#Region "Properties"
Private _isTCRunning As Boolean
Public ReadOnly Property IsTCRunning() As Boolean
Get
Return _isTCRunning
End Get
End Property
Private _thePart As Part = Nothing
Public Property Part() As Part
Get
Return _thePart
End Get
Set(ByVal value As Part)
_thePart = value
'Me.GetInfo()
_allUniqueParts.Add(_thePart)
Me.GetAllInfo()
End Set
End Property
Public ReadOnly Property AllComponents() As List(Of Component)
Get
Return _allComponents
End Get
End Property
Public ReadOnly Property AllUniqueParts() As List(Of Part)
Get
Return _allUniqueParts
End Get
End Property
Public ReadOnly Property Components As List(Of Component)
Get
Return _components
End Get
End Property
Public ReadOnly Property UniqueParts As List(Of Part)
Get
Return _uniqueParts
End Get
End Property
Public ReadOnly Property NotLoaded As List(Of String)
Get
Return _notLoaded
End Get
End Property
'Private _loadParts As Boolean = True
'Public Property LoadParts() As Boolean
' Get
' Return _loadParts
' End Get
' Set(ByVal value As Boolean)
' _loadParts = value
' End Set
'End Property
#End Region
Public Sub New()
lg.WriteLine("")
lg.WriteLine("~ NXJournaling.com: NXJ_Assembly_info object created ~")
lg.WriteLine(" ~~ Version: " & Version & " ~~")
lg.WriteLine(" ~~ Timestamp of run: " & DateTime.Now.ToString & " ~~")
lg.WriteLine("NXJ_Assembly_info Sub New()")
'determine if we are running under TC or native
_theUfSession.UF.IsUgmanagerActive(_isTCRunning)
lg.WriteLine("IsTcRunning: " & _isTCRunning.ToString)
lg.WriteLine("exiting Sub New")
lg.WriteLine("")
End Sub
Private Sub GetAllInfo()
'get all component info from assembly (all levels)
lg.WriteLine("Sub GetAllInfo()")
Try
Dim c As ComponentAssembly = Part.ComponentAssembly
If Not IsNothing(c.RootComponent) Then
'*** insert code to process 'root component' (assembly file)
lg.WriteLine(" part has components")
'*** end of code to process root component
lg.WriteLine(" calling GetAllComponentChildren")
GetAllComponentChildren(c.RootComponent)
Else
'*** insert code to process piece part, part has no components
lg.WriteLine(" part has no components")
End If
Catch ex As NXException
lg.WriteLine("Sub GetAllInfo error: " & ex.ErrorCode)
lg.WriteLine(" " & ex.Message)
End Try
lg.WriteLine("exiting Sub GetAllInfo()")
End Sub
Private Sub GetAllComponentChildren(ByVal comp As Component)
For Each child As Component In comp.GetChildren()
lg.WriteLine(child.DisplayName)
'*** insert code to process component or subassembly
If Me.LoadComponent(child) Then
_allComponents.Add(child)
Dim tempPart As Part = child.Prototype.OwningPart
If Not _allUniqueParts.Contains(tempPart) Then
_allUniqueParts.Add(tempPart)
End If
Else
'component could not be loaded
End If
'*** end of code to process component or subassembly
If child.GetChildren.Length <> 0 Then
'*** this is a subassembly, add code specific to subassemblies
'*** end of code to process subassembly
Else
'this component has no children (it is a leaf node)
'add any code specific to bottom level components
End If
Me.GetAllComponentChildren(child)
Next
End Sub
Private Sub GetInfo()
'get top level component info from assembly (no recursion)
lg.WriteLine("Sub GetInfo()")
Try
Dim c As ComponentAssembly = Part.ComponentAssembly
If Not IsNothing(c.RootComponent) Then
'*** insert code to process 'root component' (assembly file)
lg.WriteLine(" part has components")
'*** end of code to process root component
lg.WriteLine(" calling GetComponentChildren")
Me.GetComponentChildren(c.RootComponent)
Else
'*** insert code to process piece part, part has no components
lg.WriteLine(" part has no components")
End If
Catch ex As NXException
lg.WriteLine("Sub GetInfo error: " & ex.ErrorCode)
lg.WriteLine(" " & ex.Message)
End Try
lg.WriteLine("exiting GetInfo()")
End Sub
Private Sub GetComponentChildren(ByVal comp As Component)
For Each child As Component In comp.GetChildren()
'*** insert code to process component or subassembly
_components.Add(child)
Dim tempPart As Part = child.Prototype.OwningPart
If Not _uniqueParts.Contains(tempPart) Then
_uniqueParts.Add(tempPart)
End If
'*** end of code to process component or subassembly
If child.GetChildren.Length <> 0 Then
'*** this is a subassembly, add code specific to subassemblies
'*** end of code to process subassembly
Else
'this component has no children (it is a leaf node)
'add any code specific to bottom level components
End If
Next
End Sub
Private Function LoadComponent(ByVal theComponent As Component) As Boolean
lg.WriteLine("Sub LoadComponent()")
Dim thePart As Part = theComponent.Prototype.OwningPart
Dim partName As String = ""
Dim refsetName As String = ""
Dim instanceName As String = ""
Dim origin(2) As Double
Dim csysMatrix(8) As Double
Dim transform(3, 3) As Double
'save the current assembly load options
Dim curLoadOptions As UFAssem.Options
_theUfSession.Assem.AskAssemOptions(curLoadOptions)
'When loading a component, the current load options are used.
'If the current load option is set to "from folder" or "search folders" and the component
'is not in one of those folders, it will not be found.
'Change the load options to "as-saved" to look for the component in the last known location.
'To Do:
'If the component is not found using the "as-saved" option, try changing to the user's
'"from folder" or "search folders" option to see if it can be found.
'change the load options to "as-saved"
Dim newLoadOptions As UFAssem.Options
_theUfSession.Assem.AskAssemOptions(newLoadOptions)
newLoadOptions.load_options = UFConstants.UF_ASSEM_load_as_saved
_theUfSession.Assem.SetAssemOptions(newLoadOptions)
Try
If thePart.IsFullyLoaded Then
'component is fully loaded
Else
'component is partially loaded
End If
lg.WriteLine(" component: " & theComponent.DisplayName & " is already partially or fully loaded")
lg.WriteLine(" return: True")
lg.WriteLine("exiting Sub LoadComponent()")
lg.WriteLine("")
Return True
Catch ex As NullReferenceException
'component is not loaded
Try
lg.WriteLine(" component not loaded, retrieving part information")
_theUfSession.Assem.AskComponentData(theComponent.Tag, partName, refsetName, instanceName, origin, csysMatrix, transform)
lg.WriteLine(" component part file: " & partName)
Dim theLoadStatus As PartLoadStatus
_theSession.Parts.Open(partName, theLoadStatus)
'_theUfSession.Assem.SetAssemOptions(curLoadOptions)
If theLoadStatus.NumberUnloadedParts > 0 Then
If theLoadStatus.NumberUnloadedParts > 1 Then
lg.WriteLine(" problem loading " & theLoadStatus.NumberUnloadedParts.ToString & " components")
Else
lg.WriteLine(" problem loading 1 component")
End If
Dim allReadOnly As Boolean = True
For i As Integer = 0 To theLoadStatus.NumberUnloadedParts - 1
lg.WriteLine("part name: " & theLoadStatus.GetPartName(i))
lg.WriteLine("part status: " & theLoadStatus.GetStatus(i))
If theLoadStatus.GetStatus(i) = 641058 Then
'read-only warning, file loaded ok
Else
'641044: file not found
allReadOnly = False
If Not _notLoaded.Contains(partName) Then
_notLoaded.Add(partName)
End If
End If
lg.WriteLine("status description: " & theLoadStatus.GetStatusDescription(i))
lg.WriteLine("")
Next
If allReadOnly Then
lg.WriteLine(" 'read-only' warnings only")
lg.WriteLine(" return: True")
Return True
Else
'warnings other than read-only...
lg.WriteLine(" return: False")
lg.WriteLine("exiting Sub LoadComponent()")
lg.WriteLine("")
Return False
End If
Else
lg.WriteLine(" component(s) loaded successfully")
lg.WriteLine(" return: True")
lg.WriteLine("exiting Sub LoadComponent()")
lg.WriteLine("")
Return True
End If
Catch ex2 As NXException
lg.WriteLine(" Load error: " & ex2.Message)
lg.WriteLine(" error code: " & ex2.ErrorCode)
lg.WriteLine(" return: False")
lg.WriteLine("exiting Sub LoadComponent()")
lg.WriteLine("")
If ex2.Message.ToLower = "file not found" Then
If Not _notLoaded.Contains(partName) Then
_notLoaded.Add(partName)
End If
End If
Return False
End Try
Catch ex As NXException
'unexpected error
lg.WriteLine(" Error in Sub LoadComponent: " & ex.Message)
lg.WriteLine(" return: False")
lg.WriteLine("exiting Sub LoadComponent()")
lg.WriteLine("")
Return False
Finally
'Reset assembly load option to the user's preference.
_theUfSession.Assem.SetAssemOptions(curLoadOptions)
End Try
End Function
End Class
Make this work recursively
Thanks, NXJournaling. This is of huge help, I am trying to make another journal that will only change the reference set for all loaded components to "MODEL" if there is no such reference set skip to the next component. The reason is, that it might be useful on assemblies that do not need a "MODEL" referenceset created but only set it for all components.
HI can i get macro which will
HI can i get macro which will consider the STD component,solids and surface while setting the "Reference Set" so that I can avoid the default UG NX steps for the same.
re: reference set
You want to create a new reference set and add all the solid and sheet bodies to it?
I'm not sure what "consider the STD component" means.
Can you list the steps you currently take in NX to do what it is that you need to accomplish?
STD component means the item
STD component means the item I take from library and those file will be read only cannot be changed.
Ex: Sankyo Elements,Misumi etc
re: reference set
Do you have write access to the part in which you want to create the reference set?
Can you list the steps you currently take in NX to do what it is that you need to accomplish?
Like "xxxxxxx-main" in this
Like "xxxxxxx-main" in this the sub files will come
xxxxxxx-main
--xxxxxxxx-lower assy
- xxxxxxx-lower shoe
-- xxxxxxx-upper assy
- xxxxxxx-upper shoe
in all sub file respective standard item will come.so without opening a sub file in a new window i want make a reference set for all main and sub files.
re: create reference set in each component
The code in the following link shows how to process each component in an assembly:
http://nxjournaling.com/content/creating-subroutine-process-all-componen...
Combine that with the function to create reference sets found here:
http://nxjournaling.com/comment/1359#comment-1359
And you can quickly create a reference set in every component.