Replace Component with NX Journal

Hello

I would like to have a Journal to replace, in an Assembly, a selected component by another one. I used the "record" function of NX but the Journal created by NX is incomplete because the Replace Component NX function is partially journaled. Can you help to write correctly this Journal

Thank you

What version of NX are you using? The code below was written and tested on NX 9.

Here is some code based on a recorded journal; I modified it so that the user can select which component to replace. The replacement part is hardcoded into the journal; in an actual application you would want some way to specify the replacement part either through code logic or allowing the user to specify a replacement part.

Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.UF

Module Module1

Dim theSession As Session = Session.GetSession()
Dim theUfSession As UFSession = UFSession.GetUFSession()

Dim theUI As UI = UI.GetUI()
Dim lw As ListingWindow = theSession.ListingWindow

Sub Main()

Dim markId1 As Session.UndoMarkId
markId1 = theSession.SetUndoMark(Session.MarkVisibility.Visible, "NXJ")

lw.Open()

Dim selComp As NXOpen.Assemblies.Component = Nothing
If SelectComponent(selComp) = Selection.Response.Cancel Then
'user pressed cancel
Exit Sub
End If

Dim replaceComponentBuilder1 As Assemblies.ReplaceComponentBuilder
replaceComponentBuilder1 = theSession.Parts.Work.AssemblyManager.CreateReplaceComponentBuilder()

replaceComponentBuilder1.ReplaceAllOccurrences = True

replaceComponentBuilder1.ComponentNameType = Assemblies.ReplaceComponentBuilder.ComponentNameOption.AsSpecified

Dim added1 As Boolean
added1 = replaceComponentBuilder1.ComponentsToReplace.Add(selComp)

'path to replacement part, edit as needed
replaceComponentBuilder1.ReplacementPart = "C:\parts\newpart.prt"

replaceComponentBuilder1.SetComponentReferenceSetType(Assemblies.ReplaceComponentBuilder.ComponentReferenceSet.Maintain, Nothing)

Dim partLoadStatus1 As PartLoadStatus
partLoadStatus1 = replaceComponentBuilder1.RegisterReplacePartLoadStatus()

Dim nXObject1 As NXObject
nXObject1 = replaceComponentBuilder1.Commit()

partLoadStatus1.Dispose()

replaceComponentBuilder1.Destroy()

lw.Close()

End Sub

Function SelectComponent(ByRef selObj As TaggedObject) As Selection.Response

Dim theUI As UI = UI.GetUI
Dim message As String = "Select component to replace"
Dim title As String = "Select a Component"
Dim includeFeatures As Boolean = False
Dim keepHighlighted As Boolean = False
Dim selAction As Selection.SelectionAction = Selection.SelectionAction.ClearAndEnableSpecific
Dim cursor As Point3d
Dim scope As Selection.SelectionScope = Selection.SelectionScope.AnyInAssembly
Dim selectionMask_array(0) As Selection.MaskTriple

With selectionMask_array(0)
.Type = UFConstants.UF_component_type
.Subtype = UFConstants.UF_all_subtype
End With

Dim resp As Selection.Response = theUI.SelectionManager.SelectTaggedObject(message,
title, scope, selAction,
includeFeatures, keepHighlighted, selectionMask_array,
selObj, cursor)
If resp = Selection.Response.ObjectSelected OrElse resp = Selection.Response.ObjectSelectedByName Then
Return Selection.Response.Ok
Else
Return Selection.Response.Cancel
End If

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

Thanks for your help
But I already tried this kind of NX Journal but it does not work. The part is not replaced
I have to add this extra line
"replaceComponentBuilder1.MaintainRelationships = False" to get the part replaced but doing that I lost all the Assembly Constrains and also the expressions InterPart Connection is not done automatically

When you perform the same replace operation in interactive NX are the expressions and constraints correctly updated?

Hello

When I replace the templates from my assembly by the custom parts, constrains and expressions interpart references are updated correctly

I'm not sure what you mean by "replacing the template with the custom part". Are the components (original and replacement) generated from a family of parts? Using family parts or named references are the only ways I know of to help maintain constraints when replacing components. Otherwise, it would seem that interactive NX is doing more work to replace the component than what gets recorded in the journal.

Our templates in our assembly are there just to create the final assembly (contrains and Interpart references). Templates are replaced by our designers by the Productions Part(for customer). Productions Part are the same as the templates part but customized (dimensions are different for each customer application). By replacing manually each Template Parts by Production Parts, mating conditions and interpart references are updated with the Production Part by UG (it's normal).
Yes, the Interactive NX is doing more work to replace than the Recorded Journal. BTW, UG shows that the Replace Component function is partially recorded. The Recorded Journal does not update constrains and interpart references. Because of the constrains, the recorded journal does not work (no error messages, but original parts are not replaced).
So I created a Journal, in this Journal, I replace original parts without keeping the 'Relionships' (Maintain Relationships is false). By doing that, all constrains are gone and I recreate (with the journal) all the original constrains and I also recreate (with the journal) the interpart references between the main assembly and the components

Find below my final code. My assembly contains only one template to replace. Journal replaces the template by my production part (I have to enter an existing part number), recreates 3 constrains because relationships are not maintained (I have to select manually 2 Datum Planes and 1 Datum Axis from the production part because I did not find out how to do it automatically by using the journal) and I recreate the Interpart References

Option Strict Off
Imports System
Imports NXOpen
Imports NXOpenUI

Module ThreadReplacePart
Sub Main
Dim theSession As Session
Dim workPart As Part
Dim CheckPart as Boolean

theSession = Session.GetSession()
workPart = theSession.Parts.Work

' ----------------------------------------------
' Check Part
' ----------------------------------------------
if CheckPartIsPreform (theSession,workPart) = false then return

Dim component1() As Assemblies.Component = workPart.ComponentAssembly.RootComponent.getchildren()
Dim openStatus1() As Assemblies.ComponentAssembly.OpenComponentStatus
Dim NewPartName as string
Dim Dummy_Thread_Name as String

workPart.ComponentAssembly.OpenComponents(Assemblies.ComponentAssembly.OpenOption.ComponentOnly, component1, openStatus1)
Dummy_Thread_Name = component1(0).DisplayName
NewPartName=NXInputBox.GetInputString("Enter Part Number (xxxxxxx/x) :","New Production Part")
if NewPartName="" then return

' ----------------------------------------------
' Replace Dummy Thread
' ----------------------------------------------

ReplaceDummyThread(theSession,workPart,component1(0),NewPartName)

' ----------------------------------------------
' Create 3 Constrains
' ----------------------------------------------

Dim componentPositioner1 As Positioning.ComponentPositioner
Dim arrangement1 As Assemblies.Arrangement
Dim network1 As Positioning.Network
Dim componentNetwork1 As Positioning.ComponentNetwork
Dim allowInterpartPositioning1 As Boolean
Dim nullAssemblies_Component As Assemblies.Component
Dim nullAssemblies_Arrangement As Assemblies.Arrangement
Dim component2() As Assemblies.Component = workPart.ComponentAssembly.RootComponent.getchildren()

workPart.ComponentAssembly.ReplaceReferenceSetInOwners("BODY_MATE", component2)

componentPositioner1 = workPart.ComponentAssembly.Positioner
componentPositioner1.ClearNetwork()
arrangement1 = CType(workPart.ComponentAssembly.Arrangements.FindObject("Arrangement 1"), Assemblies.Arrangement)
componentPositioner1.PrimaryArrangement = arrangement1
componentPositioner1.BeginAssemblyConstraints()
allowInterpartPositioning1 = theSession.Preferences.Assemblies.InterpartPositioning
network1 = componentPositioner1.EstablishNetwork()
componentNetwork1 = CType(network1, Positioning.ComponentNetwork)
componentNetwork1.MoveObjectsState = True
nullAssemblies_Component = Nothing
componentNetwork1.DisplayComponent = nullAssemblies_Component
componentNetwork1.NetworkArrangementsMode = Positioning.ComponentNetwork.ArrangementsMode.Existing
componentNetwork1.MoveObjectsState = True
componentNetwork1.NetworkArrangementsMode = Positioning.ComponentNetwork.ArrangementsMode.Existing

CreateCenterAxisConstrain(workPart,componentPositioner1,component2)
CreatePlaneConstrain("Select Thread TOF PLANE (Yellow)","DATUM_PLANE(3)",workPart,componentPositioner1,component2)
'CreatePlaneConstrain("Select Thread SPLITLINE PLANE (Yellow)","FIXED_DATUM_PLANE(0)",workPart,componentPositioner1,component2)
CreateAngularConstrain(workPart,componentPositioner1,component2)

workPart.ComponentAssembly.ReplaceReferenceSetInOwners("BODY", component2)

componentNetwork1.Solve()
componentPositioner1.ClearNetwork()
theSession.UpdateManager.AddToDeleteList(componentNetwork1)
componentPositioner1.DeleteNonPersistentConstraints()
nullAssemblies_Arrangement = Nothing
componentPositioner1.PrimaryArrangement = nullAssemblies_Arrangement
componentPositioner1.EndAssemblyConstraints()

' ----------------------------------------------
' Create Interpart Connection (if needed)
' ----------------------------------------------

workPart.Expressions.ChangeInterpartReferences(Dummy_Thread_Name, NewPartName, False, True)

' ----------------------------------------------
' Fix Link Body
' ----------------------------------------------

End Sub

Function CheckPartIsPreform(ByVal s as Session, ByVal w as Part) as Boolean
Dim ex As NXException
Dim myExp1 as Expression

If IsNothing(s.Parts.BaseWork) Then
msgbox("Active Part required; THREAD REPLACEMENT AUTOMATION aborted !!!",,"THREAD REPLACEMENT")
Return false
End If

Try
myExp1 = w.Expressions.FindObject("ENGRAVING_FONT")
Catch ex
If ex.ErrorCode = 3520016 Then
MsgBox("Not a PREFORM PART; THREAD REPLACEMENT AUTOMATION aborted !!!",,"THREAD REPLACEMENT")
Return false
End If
End Try
Try
myExp1 = w.Expressions.FindObject("SHRINKAGE_New_Design")
Catch ex
If ex.ErrorCode = 3520016 Then
MsgBox("Not NEW PREFORM VERSION PART (>=V10.00); THREAD REPLACEMENT AUTOMATION aborted !!!",,"THREAD REPLACEMENT")
Return false
End If
End Try
CheckPartIsPreform=true
End Function

Sub ReplaceDummyThread(ByVal s as Session, ByVal w as Part, ByVal c as Assemblies.Component, ByVal partname as String)
Dim replaceComponentBuilder1 As Assemblies.ReplaceComponentBuilder
Dim partLoadStatus1 As PartLoadStatus
Dim nXObject1 As NXObject

replaceComponentBuilder1 = w.AssemblyManager.CreateReplaceComponentBuilder()
replaceComponentBuilder1.ReplaceAllOccurrences = True
replaceComponentBuilder1.ComponentNameType = Assemblies.ReplaceComponentBuilder.ComponentNameOption.AsSpecified
replaceComponentBuilder1.ComponentsToReplace.Add(c)
replaceComponentBuilder1.ComponentName = "DUMMY_THREAD"
s.Parts.SetNonmasterSeedPartData("@DB/" & partname)
replaceComponentBuilder1.ComponentName = left(partname,InStr(partname, "/") - 1)
replaceComponentBuilder1.MaintainRelationships = False
replaceComponentBuilder1.ReplaceAllOccurrences = False
replaceComponentBuilder1.ReplacementPart = "@DB/" & partname
replaceComponentBuilder1.SetComponentReferenceSetType(Assemblies.ReplaceComponentBuilder.ComponentReferenceSet.Maintain, Nothing)
partLoadStatus1 = replaceComponentBuilder1.RegisterReplacePartLoadStatus()
nXObject1 = replaceComponentBuilder1.Commit()
partLoadStatus1.Dispose()
replaceComponentBuilder1.Destroy()
End Sub

Sub CreateCenterAxisConstrain(ByVal w as Part, ByVal compPositioner As Positioning.ComponentPositioner, ByVal comp() As Assemblies.Component)
Dim constraint1 As Positioning.Constraint
Dim componentConstraint1 As Positioning.ComponentConstraint
Dim datumAxis1 As DatumAxis
Dim datumAxis2 As DatumAxis
Dim constraintReference1 As Positioning.ConstraintReference
Dim constraintReference2 As Positioning.ConstraintReference
Dim nullAssemblies_Arrangement As Assemblies.Arrangement
Dim theUI As UI = UI.GetUI
Dim mySelectedObject As NXObject
Dim cursor As Point3d

constraint1 = compPositioner.CreateConstraint()
componentConstraint1 = CType(constraint1, Positioning.ComponentConstraint)
componentConstraint1.ConstraintAlignment = Positioning.Constraint.Alignment.ContraAlign
componentConstraint1.ConstraintType = Positioning.Constraint.Type.Touch

theUI.SelectionManager.SelectObject("SELECTION THREAD AXIS","Select Thread CENTER AXIS (Yellow)", Selection.SelectionScope.AnyInAssembly,False, Selection.SelectionType.All, mySelectedObject, cursor)
datumAxis1 = mySelectedObject
datumAxis2 = CType(w.Datums.FindObject("DATUM_AXIS(6)"), DatumAxis)
constraintReference1 = componentConstraint1.CreateConstraintReference(comp(0), datumAxis1, False, False, False)
constraintReference2 = componentConstraint1.CreateConstraintReference(w.ComponentAssembly, datumAxis2, False, False, False)

componentConstraint1.FlipAlignment()

constraintReference1.SetFixHint(True)
constraintReference1.SetFixHintforUpdate(True)
constraintReference2.SetFixHint(True)
constraintReference2.SetFixHintforUpdate(True)
End Sub

Sub CreatePlaneConstrain(ByVal prompt as String,ByVal planeName as String , ByVal w as Part, ByVal compPositioner As Positioning.ComponentPositioner, ByVal comp() As Assemblies.Component)
Dim constraint1 As Positioning.Constraint
Dim componentConstraint1 As Positioning.ComponentConstraint
Dim datumPlane1 As DatumPlane
Dim datumPlane2 As DatumPlane
Dim constraintReference1 As Positioning.ConstraintReference
Dim constraintReference2 As Positioning.ConstraintReference
Dim nullAssemblies_Arrangement As Assemblies.Arrangement
Dim theUI As UI = UI.GetUI
Dim mySelectedObject As NXObject
Dim cursor As Point3d

constraint1 = compPositioner.CreateConstraint()
componentConstraint1 = CType(constraint1, Positioning.ComponentConstraint)
componentConstraint1.ConstraintAlignment = Positioning.Constraint.Alignment.CoAlign
componentConstraint1.ConstraintType = Positioning.Constraint.Type.Touch

theUI.SelectionManager.SelectObject("SELECTION THREAD PLANE", prompt, Selection.SelectionScope.AnyInAssembly,False, Selection.SelectionType.All, mySelectedObject, cursor)
datumPlane1 = mySelectedObject
datumPlane2 = CType(w.Datums.FindObject(planeName), DatumPlane)
constraintReference1 = componentConstraint1.CreateConstraintReference(comp(0), datumPlane1, False, False, False)
constraintReference2 = componentConstraint1.CreateConstraintReference(w.ComponentAssembly, datumPlane2, False, False, False)

constraintReference1.SetFixHint(True)
constraintReference1.SetFixHintforUpdate(True)
constraintReference2.SetFixHint(True)
constraintReference2.SetFixHintforUpdate(True)
End Sub

Sub CreateAngularConstrain(ByVal w as Part, ByVal compPositioner As Positioning.ComponentPositioner, ByVal comp() As Assemblies.Component)
Dim constraint1 As Positioning.Constraint
Dim componentConstraint1 As Positioning.ComponentConstraint
Dim datumPlane1 As DatumPlane
Dim datumPlane2 As DatumPlane
Dim constraintReference1 As Positioning.ConstraintReference
Dim constraintReference2 As Positioning.ConstraintReference
Dim nullAssemblies_Arrangement As Assemblies.Arrangement
Dim theUI As UI = UI.GetUI
Dim mySelectedObject As NXObject
Dim cursor As Point3d
Dim expression1 As Expression

constraint1 = compPositioner.CreateConstraint()
componentConstraint1 = CType(constraint1, Positioning.ComponentConstraint)
componentConstraint1.ConstraintAlignment = Positioning.Constraint.Alignment.ContraAlign
componentConstraint1.ConstraintType = Positioning.Constraint.Type.Angle
componentConstraint1.SetExpression("180")

theUI.SelectionManager.SelectObject("SELECTION THREAD PLANE", "Select Thread SPLITLINE PLANE (Yellow)", Selection.SelectionScope.AnyInAssembly,False, Selection.SelectionType.All, mySelectedObject, cursor)
datumPlane1 = mySelectedObject
datumPlane2 = CType(w.Datums.FindObject("DATUM_PLANE(236)"), DatumPlane)
constraintReference1 = componentConstraint1.CreateConstraintReference(comp(0), datumPlane1, False, False, False)
constraintReference2 = componentConstraint1.CreateConstraintReference(w.ComponentAssembly, datumPlane2, False, False, False)

constraintReference1.SetFixHint(True)
constraintReference1.SetFixHintforUpdate(True)
constraintReference2.SetFixHint(True)
constraintReference2.SetFixHintforUpdate(True)
End Sub

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

Hi

This code is great. It's really helped me understand a little more about how to reference assemblies. I was wondering if you knew how you would change the codes object input to allow you to simply type in the part number of the component you want replaced rather then pick it? I have written a (pretty simple and crude) subroutine which identifies certain parts which need replacing but it's output is string based.

Thanks in advance

Hi

This code is great. It's really helped me understand a little more about how to reference assemblies. I was wondering if anybody knows how you would change the 09/06/2016 codes object input to allow you to type in the part number of the component you want replaced rather then pick it? I have written a (pretty simple and crude) subroutine which identifies certain parts which need replacing but it's output is string based.

Thanks in advance