Add component attribute find number

The following journal is an extension of the code presented in the processing components tutorial.

This journal will recursively walk through the assembly structure and prompt for a "find number" to be added to each component as an attribute. Subsequent runs of the journal will ignore components that already have a unique find number attribute.

The journal does limited error checking, and due to the order of processing of subsequent runs, it may prompt for a find number for a component that already has one. In short, the code needs some improvements before it is put into a 'production environment'.

The code is offered 'as-is', the user is responsible for testing and any necessary edits for their environment.

'Journal to recursively walk through the assembly structure
' will run on assemblies or piece parts
' will step through all components of the displayed part
' and prompt for/add a "callout" attribute to each component
'NX 7.5, native
'February 29, 2012

'edit April 9, 2013: error handling more robust
' instead of using the generic ApplicationException, use NXException with associated error code
' to check for "attribute not found" error (NX error code: 512008)

Option Strict Off

Imports System
Imports System.Collections.Generic
Imports NXOpen
Imports NXOpen.UF
Imports NXOpen.Assemblies

Module NXJournal

Public theSession As Session = Session.GetSession()
Public ufs As UFSession = UFSession.GetUFSession()
Public lw As ListingWindow = theSession.ListingWindow
Dim componentList As New Dictionary(Of String, String)
Dim blnCancel As Boolean = False

'***** change the value of the following constant to your desired attribute title
Const attributeTitle As String = "MYCALLOUT"
'*******************************************

Sub Main()
Dim workPart As Part = theSession.Parts.Work
Dim dispPart As Part = theSession.Parts.Display
Dim blnGatheringInfo As Boolean = True
Dim i As Integer

Dim markId1 As Session.UndoMarkId
markId1 = theSession.SetUndoMark(Session.MarkVisibility.Invisible, "Start")

lw.Open()
For i = 0 To 1
Try
Dim c As ComponentAssembly = dispPart.ComponentAssembly
If Not IsNothing(c.RootComponent) Then
reportComponentChildren(c.RootComponent)
End If
Catch e As Exception
theSession.ListingWindow.WriteLine("Failed: " & e.ToString)
End Try
blnGatheringInfo = False
Next
'lw.WriteLine("Done processing")
lw.Close()

theSession.SetUndoMarkName(markId1, "Add callout attributes")
theSession.SetUndoMarkVisibility(markId1, Nothing, Session.MarkVisibility.Visible)

End Sub
'**********************************************************
Sub reportComponentChildren(ByVal comp As Component)

For Each child As Component In comp.GetChildren()
'*** insert code to process component or subassembly
If blnCancel Then
Exit Sub
Else
processComponent(child)
reportComponentChildren(child)
End If
Next
End Sub
'**********************************************************
Sub processComponent(ByRef myComp As Component)
Dim previousValue As String = ""
Dim currentValue As String = ""

If blnCancel Then
Exit Sub
End If

If componentList.ContainsKey(myComp.DisplayName) Then
'component is in list
previousValue = componentList.Item(myComp.DisplayName)
'add code to validate attribute value here
Try
'is the attribute set on this component, and does it match the value in the list?
currentValue = myComp.GetStringAttribute(attributeTitle)
If currentValue <> previousValue Then
myComp.SetAttribute(attributeTitle, previousValue)
End If
Catch ex As NXException
'512008 = attribute not found
If ex.ErrorCode = 512008 Then
'component is in list but does not have the attribute, create attribute and set to value in list
myComp.SetAttribute(attributeTitle, previousValue)
Else
'some other error occurred
lw.WriteLine("## Error: " & ex.ErrorCode & " : " & ex.ToString)
End If
End Try
Else
'component is not yet in list
Try
'it is possible the component has the attribute assigned from a previous run
'or manual entry, but the component has not been processed yet by this run
currentValue = myComp.GetStringAttribute(attributeTitle)
If ValueExists(currentValue) Then
'attribute has been assigned, but the value is already in use by a different component
AssignAttribute(myComp)
Else
'attribute has been assigned and is unique among components processed so far
componentList.Add(myComp.DisplayName, currentValue)
End If

Catch ex As NXException
If ex.ErrorCode = 512008 Then
'component does not have attribute
AssignAttribute(myComp)
Else
'some other error occurred
lw.WriteLine("## Error: " & ex.ErrorCode & " : " & ex.ToString)
End If
End Try

End If

End Sub
'**********************************************************
Function ValueExists(ByVal value As String) As Boolean

For Each key As String In componentList.Keys
If value = componentList.Item(key) Then
Return True
Exit Function
End If
Next
Return False

End Function
'**********************************************************
Sub AssignAttribute(ByRef theComponent As Component)

Dim newValue As String = ""
Dim temp As String = ""
Dim i As Integer = 1

Do While ValueExists(i.ToString)
i += 1
Loop
Do
temp = newValue
newValue = InputBox("Enter value of " & attributeTitle & " for component: " & theComponent.DisplayName, theComponent.DisplayName, i.ToString)
If newValue = "" Then
'user pressed cancel
blnCancel = True
Exit Sub
End If
If ValueExists(newValue) Then
MsgBox("Value: " & newValue & " is already in use, please enter a new value", MsgBoxStyle.Exclamation + MsgBoxStyle.OkOnly, "Error")
End If
'add code to validate entered value
Loop While ValueExists(newValue)
componentList.Add(theComponent.DisplayName, newValue)
theComponent.SetAttribute(attributeTitle, newValue)

End Sub
'**********************************************************
Public Function GetUnloadOption(ByVal dummy As String) As Integer
Return Session.LibraryUnloadOption.Immediately
End Function
'**********************************************************

End Module

Comments

So I see that when I have an assembly open and execute the script it will add the attribute to the components. With the assembly displayed, when I examine the properties of the components the MYCALLOUT attribute is set with the assigned value. However, when I open the part in a new window I cannot find the attribute. How would I set the attribute so that it is assigned AT THE PART LEVEL and NOT FOR THE PART AT THE ASSEMBLY LEVEL. What I am trying to do is do a bulk assignment of attributes to all the components in a design (ie, Job Number, Designer, Date) that are the same so that when the drawing is created the the appropriate fields are automatically populated with these values.

Rather than adding the attributes to the component, you will want to add them to the part which defines the component geometry. You can get at this part by using the component.Prototype property.

As soon as work lets up and I'm not so busy designing I'll have to take the time to figure this out. Isn't it the way it seems to go, when you're busy you want to try and make things go quicker but don't have enough time to do it.

Thanks for all the examples you've posted. I hope that once I can, I'll have some useful journals to contribute as well.

Hi,

allready if I am having a attribute with the same name it is not updating the existing value. Can you please change the code to change the value of existing attribute.

Stay Hungry
Stay Foolish

How do you get the aal the attributes of the parent File onto a txt file or listing window?
Thanks

Carlo Tony Daristotile

By "parent file" do you mean you have a component and you want to report all the part attributes of the file where the geometry is defined (the prototype part)?

Also, what version of NX are you using? Part attributes changed some starting at NX 8.

by Parent I mean the Master Assembly.
NX 8.0.3.4

Carlo Tony Daristotile

How do I look at these, the attributes seem hidden.

Dan Gaigalas

Right click the component and choose Properties -> Attributes to view them. They are meant to be used in a note or parts list callout.

I what Origin tool Where i can Associate the Parent and child

I what Origin tool Where i can Associate the Parent and child

I don't understand the question, can you add more detail about what you are trying to do? What type of association are you trying to create and what type of objects are the parent and child?

In Drawing, in order to associate two entities(text, balloons,note,etc) with one another we would be using origin tool (which is available under settings of that particular entity).
So instead of providing manual values. Thought of making macro to provided Automatic association.

HI guys.
I've been testing this code, works fine except for the order to start placing number in a sequence that was confused to me.
Is there a way to set this code to start from the very fisrt one component in the work part and afterwards going to the next bellow? (Including assemblies and parts)

Fernando Alves
Mechanical Designer / NX11 - TeamCenter

The journal code works through the components as they are stored internally in NX; I think this matches the creation order (but I'm not 100% certain on that). If you need a different numbering order, I'd suggest adding the components to a list (or other data structure of your choosing), then sorting the list as desired, and processing the components based on the resulting order.

Do we get any online courses for the customization from your end.

I do not have, nor do I plan to offer, any sort of interactive online courses. The tutorial articles and other source code on the site are all that I have right now. I'm always looking for article topic ideas; if you have an interest in a particular topic, please let me know.