Part Family test code

The code below was written a while back while learning about querying part families with the NXOpen API. When run, the code below will look at the current work part and take one of several possible actions. No matter what, the code will report the current part family save directory.

If the work part is a family template, it will report such and attempt to list the members. If a member part is open in the current session, the journal will check to see if it is up to date. If the member is not up to date, the journal will attempt to update it.

If the current work part is a family instance, the journal will report such and attempt to report the controlling part family template.

As you work with part families, I hope the code below helps to illustrate how to call the part family functions.

'NXJournaling.com
'December 4, 2014

'NX 8.5
'Test journal to learn about part family functions.
'This journal tests the work part to see if it is a family template.
'If so, it will generate and save any missing members.
'If the work part is a family member instance, the journal will report
'if the instance is current or not.

Option Strict Off
Imports System
Imports System.IO
Imports System.Collections.Generic
Imports System.Windows.Forms
Imports NXOpen
Imports NXOpen.UF

Module part_family

Dim theSession As Session = Session.GetSession
Dim theUfSession As UFSession = UFSession.GetUFSession
Dim workPart As Part = theSession.Parts.Work
Dim displayPart As Part = theSession.Parts.Display

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()

Dim famInstSaveDir As String
theUfSession.Part.AskFamInstSaveDir(famInstSaveDir)
lw.WriteLine("family instance save directory [session/customer default part file directory]: " & famInstSaveDir)

Dim numMembers As Integer = 0

If IsPartFamilyTemplate(workPart) Then
lw.WriteLine("the work part is a part family template")
lw.WriteLine("family save directory: " & PartFamilySaveDir(workPart))
Try
numMembers = workPart.GetPartFamilyManager.GetMemberCount()
Catch ex As NXException
If ex.ErrorCode = 3520027 Then
'not a part family
Else
MsgBox("error: " & ex.Message, MsgBoxStyle.OkOnly, ex.ErrorCode)
Return
End If
End Try

lw.WriteLine("member count: " & numMembers.ToString)

If numMembers = 0 Then
lw.WriteLine("family has no members")
Return
End If
lw.WriteLine("")

lw.WriteLine("members:")
Dim newMembers As New List(Of String)
Dim existingMembers As New List(Of String)

For i As Integer = 0 To numMembers - 1
Dim familyMember As String = ""
familyMember = workPart.GetPartFamilyManager.EstablishMember(i)
'if familyMember ends in ".prt", the part has been newly created
'otherwise it is an existing part
lw.WriteLine("familyMember: " & familyMember)

Dim memberIndex As Integer
memberIndex = workPart.GetPartFamilyManager.AskIndexOfMemberName(familyMember)
lw.WriteLine("memberIndex: " & memberIndex.ToString)

If IO.Path.GetExtension(familyMember).ToLower = ".prt" Then
'save the file
lw.WriteLine("new file")
newMembers.Add(familyMember)
Else
lw.WriteLine("existing file")
existingMembers.Add(familyMember & ".prt")
End If
lw.WriteLine("")

Next
lw.WriteLine("")

For Each myPart As Part In theSession.Parts
'lw.WriteLine(myPart.Leaf)
For Each newPart As String In newMembers
If myPart.FullPath.ToLower = newPart.ToLower Then
'
lw.WriteLine("part found in session")
'
'display part
ChangeDisplayPart(myPart)
SavePart(myPart)
Exit For
End If
Next

'display existing parts
For Each exPart As String In existingMembers
If myPart.FullPath.ToLower = exPart.ToLower Then
'
lw.WriteLine(exPart & ": found in session")
'
'display part
ChangeDisplayPart(myPart)

'check to see if it is current
If IsPartFamilyInstanceCurrent(displayPart) Then
lw.WriteLine(" the instance is current")
Else
lw.WriteLine(" the instance is NOT current")
If PartFamilyUpdateInstance(displayPart) Then
lw.WriteLine(" the instance was updated")
Else
lw.WriteLine(" the instance could not be updated")
End If
End If
lw.WriteLine("")

Exit For
End If
Next
Next

ElseIf IsPartFamilyInstance(workPart) Then
lw.WriteLine("the work part is a family member")
Dim parent As String = PartFamilyTemplateFilename(workPart)
lw.WriteLine(" this instance belongs to: " & parent)

'If IsPartFamilyInstanceCurrent(workPart) Then
' lw.WriteLine(" the instance is current")
'Else
' lw.WriteLine(" the instance is NOT current")
'End If
lw.WriteLine("")

End If

End Sub

Sub ChangeDisplayPart(ByVal thePart As Part)

Dim partLoadStatus1 As PartLoadStatus
Dim status1 As PartCollection.SdpsStatus
status1 = theSession.Parts.SetDisplay(thePart, False, False, partLoadStatus1)

workPart = theSession.Parts.Work
displayPart = theSession.Parts.Display
partLoadStatus1.Dispose()

End Sub

Sub SavePart(ByVal thePart As Part)

Dim partSaveStatus1 As PartSaveStatus
partSaveStatus1 = thePart.Save(BasePart.SaveComponents.False, BasePart.CloseAfterSave.False)

partSaveStatus1.Dispose()

End Sub

Function IsPartFamilyTemplate(ByVal thePart As Part) As Boolean

Dim isFamilyTemplate As Boolean = False
theUfSession.Part.IsFamilyTemplate(thePart.Tag, isFamilyTemplate)
Return isFamilyTemplate

End Function

Function IsPartFamilyInstance(ByVal thePart As Part) As Boolean

Dim isFamilyInstance As Boolean = False
theUfSession.Part.IsFamilyInstance(thePart.Tag, isFamilyInstance)
Return isFamilyInstance

End Function

Function IsPartFamilyInstanceCurrent(ByVal thePart As Part) As Boolean

'load part family template, error will occur if .IsFamilyInstCurrent is called
'and the template part is not loaded

Dim isInstanceCurrent As Boolean = False
theUfSession.Part.IsFamilyInstCurrent(thePart.Tag, isInstanceCurrent)
Return isInstanceCurrent

End Function

Function PartFamilyTemplateFilename(ByVal thePart As Part) As String

Dim familyTemplate As String = ""
theUfSession.Part.AskTemplateFilename(thePart.Tag, familyTemplate)
Return familyTemplate

End Function

Function PartFamilyInstanceSaveDir() As String

Dim familyInstDir As String = ""
theUfSession.Part.AskFamInstSaveDir(familyInstDir)
'lw.WriteLine("Family Instance Save Dir = " & familyInstDir)
'lw.WriteLine("")
Return familyInstDir

End Function

Function PartFamilySaveDir(ByVal templatePart As Part) As String

'ref: nx_api3895

Dim family_count As Integer
Dim families() As Tag = Nothing
theUfSession.Part.AskFamilies(templatePart.Tag, family_count, families)

Dim familyDir As String = ""
theUfSession.Part.AskFamilySaveDir(families(0), familyDir)

Return familyDir

End Function

Function GetPartFamilyInstanceTag(ByVal familyPart As Part) As Tag

'"familyPart" can be a template part or an instance of a family
'returns the instance tag of a part family instance
'returns the family tag of a part family template

Dim instanceTag As Tag
theUfSession.Part.AskFamilyInstance(familyPart.Tag, instanceTag)
'lw.WriteLine("family instance tag: " & instanceTag.ToString)
Return instanceTag

End Function

Function PartFamilyUpdateInstance(ByVal instancePart As Part) As Boolean

'UF_PART_update_family_instance

If Not IsPartFamilyInstance(instancePart) Then
Return False
End If

'to do: get member index, call UF_PART_update_family_instance

Dim familyTag As Tag
Dim memberIndex As Integer

theUfSession.Fam.AskInstanceData(GetPartFamilyInstanceTag(instancePart), familyTag, memberIndex)

Dim updatedPartTag As Tag
Dim wasSaved As Boolean
Dim numErrors As Integer
Dim errorPartList() As Tag
Dim errorList() As Integer
Dim info As String

theUfSession.Part.UpdateFamilyInstance(familyTag, memberIndex, False, updatedPartTag, wasSaved, numErrors, errorPartList, errorList, info)

Dim updatedPart As Part = CType(Utilities.NXObjectManager.Get(updatedPartTag), Part)

If wasSaved Then
ChangeDisplayPart(updatedPart)
Return True
Else
Return False
End If

End Function

'nx_api4394
'nx_api3895

'UF_PART_apply_family_instance
'UF_PART_ask_fam_inst_save_dir
'UF_PART_ask_families
'UF_PART_ask_family_instance
'UF_PART_ask_family_save_dir
'UF_PART_ask_template_filename
'UF_PART_create_family_instance
'UF_PART_find_family_instance
'UF_PART_is_family_inst_current
'UF_PART_is_family_instance
'UF_PART_is_family_template
'UF_PART_set_fam_inst_save_dir
'UF_PART_set_family_save_dir
'UF_PART_update_family_instance

End Module