Retrieve/Change attributes within an assembly

In the "add component attribute find number" journal the following reply was made about applying the attribute to the part level instead of the component level:

"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."

Does this mean you replace:

theComponent.SetAttribute(attributeTitle, newValue)
with
theComponent.Prototype.SetAttribute(attributeTitle, newValue)

????

Untested, but I believe the syntax for that would be (NX 7.5):

theComponent.Prototype.OwningPart.SetAttribute(...)

There were some major changes done to the attribute system in NX 8; if you are using NX 8 or newer, there is a better way to do it (use the AttributePropertiesBuilder object).

That makes a lot of sense then. I've used the single line of code in the past, but it doesn't "refresh" so it ends up not really applying until someone manually goes in and makes an attribute change. The attributePropertiesBuilder object is what I have been using, but it's on the work part only.

What would the code be to with your reportComponentChildren for each child... to set the child component as the work part so that I can call the attribute properties builder on the found component set as the work part?

Dim prototype As Part

For Each child As Component In comp.GetChildren()
prototype = CType(c.Prototype, Part)

Dim prototype As Part
For Each child As Component In comp.GetChildren()
prototype = CType(c.Prototype, Part)
'''Run sub that applies properties to part
Next

Would something like this work?

I don't have access to NX at the moment, I'd suggest opening an assembly and recording a journal while assigning an attribute to a component (as a part attribute). Use the resulting code as a guide.

I recorded a journal today and cut out the fluff. The following code will assign a string attribute to the selected component as a part attribute. Notice the .ObjectPicker option used. This journal was recorded in NX 8 to illustrate the use of the attributePropertiesBuilder, it probably won't run successfully in your assembly unless you have a component named "model3".





Option Strict Off
Imports System
Imports NXOpen

Module NXJournal
Sub Main

Dim theSession As Session = Session.GetSession()
Dim workPart As Part = theSession.Parts.Work

Dim displayPart As Part = theSession.Parts.Display

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

Dim objects1(0) As NXObject
Dim component1 As Assemblies.Component = CType(workPart.ComponentAssembly.RootComponent.FindObject("COMPONENT model3 1"), Assemblies.Component)

objects1(0) = component1

Dim attributePropertiesBuilder1 As AttributePropertiesBuilder
attributePropertiesBuilder1 = workPart.PropertiesManager.CreateAttributePropertiesBuilder(objects1)

attributePropertiesBuilder1.IsArray = False

attributePropertiesBuilder1.DataType = AttributePropertiesBaseBuilder.DataTypeOptions.String

attributePropertiesBuilder1.ObjectPicker = AttributePropertiesBaseBuilder.ObjectOptions.ComponentAsPartAttribute

attributePropertiesBuilder1.Title = "test"

attributePropertiesBuilder1.StringValue = "this is a test"

Dim nXObject2 As NXObject
nXObject2 = attributePropertiesBuilder1.Commit()

attributePropertiesBuilder1.Destroy()

End Sub
End Module

@nxjornaling

What would be the best way to define selected assembly components (by using 'SelectComponents' Function) into 'objects' array for changing those selected components attributes in the assembly ?

Regards,
MFJ

If you are using the SelectTaggedObjects function, it will return an array of 'TaggedObjects'. You can then cast these objects to the 'Component' object type as needed.

I am already using the 'selectComponents' Function as below which is using the Selecttaggedobjects function. But I cannot connect them as my recorded journal below is defined automatically a fixed 3 object array. How can I change that to cast to a variable array instead?


Dim objects2(2) As NXOpen.NXObject
objects2(0) = component2
objects2(1) = component3
objects2(2) = component4
Dim attributePropertiesBuilder1 As NXOpen.AttributePropertiesBuilder = Nothing
attributePropertiesBuilder1 = theSession.AttributeManager.CreateAttributePropertiesBuilder(workPart, objects2, NXOpen.AttributePropertiesBuilder.OperationType.None)

Regards,
MFJ

Let's assume that your array of components is called "myComps". In the code above, you could just use "myComps" in place of "objects2" in the call to the CreateAttributePropertiesBuilder. You could then remove the lines of code that define and fill the "objects2" array.

I tried as you mentioned with following code inside the sub main:

Dim selCompObj As NXOpen.NXObject

If SelectComponents("Select components", selCompObj) = Selection.Response.Cancel Then
Return
End If

Dim attributePropertiesBuilder1 As NXOpen.AttributePropertiesBuilder = Nothing
attributePropertiesBuilder1 = theSession.AttributeManager.CreateAttributePropertiesBuilder(workPart, selCompObj, NXOpen.AttributePropertiesBuilder.OperationType.None)

My selection Function name was 'SelectComponents' Using above code gives me error which summarizes like - 'NXObject' cannot be converted to a ' 1 -dimensional array of Taggedobject

Also tried replacing object2 with 'SelectComponents' as you mentioned above, but doesn't work either, which look like below:


attributePropertiesBuilder1 = theSession.AttributeManager.CreateAttributePropertiesBuilder(workPart, SelectComponents, NXOpen.AttributePropertiesBuilder.OperationType.None)

Regards,
MFJ

It appears that you are starting with a single component object and not an array. The CreateAttributePropertiesBuilder must be passed an array of objects, it will not work on a single object. There are a few ways to convert your object to an array. The easy way is to wrap it in curly braces; this will tell the compiler to treat your variable as an array with a single object.

attributePropertiesBuilder1 = theSession.AttributeManager.CreateAttributePropertiesBuilder(workPart, {selCompObj}, NXOpen.AttributePropertiesBuilder.OperationType.None)

Option 2 would be to create your own array and assign your variable as the only object in the array and pass the resulting array to the builder.

dim myArray(0) as NXObject = selCompObj
attributePropertiesBuilder1 = theSession.AttributeManager.CreateAttributePropertiesBuilder(workPart, myArray, NXOpen.AttributePropertiesBuilder.OperationType.None)

Option 3 would be to modify your selection function to return an array of objects. You would then be able to use that array directly in the builder.

Followed as you said. I guess I am almost there, but getting errors shown in commented line with respective lines below:

Dim selCompObj As TaggedObject
If SelectComponents("Select Components", selCompObj) = Selection.Response.Cancel Then 'Value of type 'TaggedObject' cannot be converted to '1-diemntional array of TaggedObjects
Return
End If

Dim myObjects(0) As NXObject = selCompObj 'Explicit initialization is not permitted for arrays declared with explicit bounds

Dim attributePropertiesBuilder1 As NXOpen.AttributePropertiesBuilder = Nothing
attributePropertiesBuilder1 = theSession.AttributeManager.CreateAttributePropertiesBuilder(workPart, myObjects, NXOpen.AttributePropertiesBuilder.OperationType.None)

attributePropertiesBuilder1.SetAttributeObjects(myObjects)

Regards,
MFJ

Dim myObjects(0) As NXObject = selCompObj 'Explicit initialization is not permitted for arrays declared with explicit bounds

The error above is just saying that you cannot declare the array with explicit bounds and give it a value at the same time (sorry, I should have double checked this first).

Dim myObjects(0) As NXObject
myObjects(0) = selCompObj

'Value of type 'TaggedObject' cannot be converted to '1-diemntional array of TaggedObjects

For the above error, I'd guess that you changed something in the "SelectComponents" function. We'd really need to see that function code to make any recommendations. Please try the first solution above and see if that works out for you.

Below are my codes now with comments showing the error on that line

Dim selCompObj() As TaggedObject
If SelectComponents("Select Components", selCompObj) = Selection.Response.Cancel Then
Return
End If

Dim myObjects() As NXObject = selCompObj 'Error: Unable to cast object of type 'TaggedObject to type 'NXObject'

Dim attributePropertiesBuilder1 As NXOpen.AttributePropertiesBuilder = Nothing
attributePropertiesBuilder1 = theSession.AttributeManager.CreateAttributePropertiesBuilder(workPart, myObjects, NXOpen.AttributePropertiesBuilder.OperationType.None)

Also the selection Function is below:


Function SelectComponents(ByVal prompt As String, ByRef selObj() As TaggedObject) As Selection.Response

Dim theUI As UI = UI.GetUI
Dim title As String = "Select components"
Dim includeFeatures As Boolean = False
Dim keepHighlighted As Boolean = False
Dim selAction As Selection.SelectionAction = Selection.SelectionAction.ClearAndEnableSpecific
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.SelectTaggedObjects(prompt,
title, scope, selAction,
includeFeatures, keepHighlighted, selectionMask_array,
selObj)
If resp = Selection.Response.Ok Then
Return Selection.Response.Ok
Else
Return Selection.Response.Cancel
End If

End Function

Regards,
MFJ

I looked around my code library and found a version of the SelectComponents function that I think will help you.

Option Strict Off
Imports System
Imports System.Collections.Generic
Imports NXOpen
Imports NXOpen.UF
Imports NXOpen.Assemblies

Module Module179

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

Dim lw As ListingWindow = theSession.ListingWindow

Sub Main()

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

lw.Open()

Dim myComps As New List(Of Component)
If SelectComponents("Select Components", myComps) = Selection.Response.Cancel Then
Return
End If

lw.WriteLine(myComps.Count.ToString & " components selected")
For Each temp As Component In myComps
lw.WriteLine(" " & temp.DisplayName)
Next

Dim attributePropertiesBuilder1 As NXOpen.AttributePropertiesBuilder = Nothing
attributePropertiesBuilder1 = theSession.AttributeManager.CreateAttributePropertiesBuilder(theSession.Parts.Work, myComps.ToArray, NXOpen.AttributePropertiesBuilder.OperationType.None)
'other code to use the attribute properties builder
attributePropertiesBuilder1.Destroy()

lw.Close()

End Sub

Function SelectComponents(ByVal prompt As String, ByRef selComponents As List(Of Component)) As Selection.Response

Dim selObj() As TaggedObject
Dim theUI As UI = UI.GetUI
Dim title As String = "Select Components"
Dim includeFeatures As Boolean = False
Dim keepHighlighted As Boolean = False
Dim selAction As Selection.SelectionAction = Selection.SelectionAction.ClearAndEnableSpecific
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_component_subtype
End With

Dim resp As Selection.Response = theUI.SelectionManager.SelectTaggedObjects(prompt,
title, scope, selAction, includeFeatures, keepHighlighted, selectionMask_array, selObj)
If resp = Selection.Response.Ok Then

For Each temp As Component In selObj
selComponents.Add(temp)
Next

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

Worked really nicely with some changes in other attributepropertiesbuilder changes. Thanks!

Regards,
MFJ

If I use only parentheses as below, NX selection dialog shows up which lets me select the components, but gives me an error with execution saying ' Unable to cast object of type 'TaggedObject to type 'NXObject'


Dim selCompObj() As TaggedObject
If SelectComponents("Select Components", selCompObj) = Selection.Response.Cancel Then 'Value of type 'TaggedObject' cannot be converted to '1-diemntional array of TaggedObjects
Return
End If

Dim myObjects() As NXObject = selCompObj 'Explicit initialization is not permitted for arrays declared with explicit bounds

Dim attributePropertiesBuilder1 As NXOpen.AttributePropertiesBuilder = Nothing
attributePropertiesBuilder1 = theSession.AttributeManager.CreateAttributePropertiesBuilder(workPart, myObjects, NXOpen.AttributePropertiesBuilder.OperationType.None)
attributePropertiesBuilder1.SetAttributeObjects(myObjects)

Regards,
MFJ

To be more precise 'CreateAttributePropertiesBuilder' uses an objects array, while I am trying to select assembly 'Components'. How should I call the selected components with the objects array?


Dim objects2(2) As NXOpen.NXObject
objects2(0) = component2
objects2(1) = component3
objects2(2) = component4
Dim attributePropertiesBuilder1 As NXOpen.AttributePropertiesBuilder = Nothing
attributePropertiesBuilder1 = theSession.AttributeManager.CreateAttributePropertiesBuilder(workPart, objects2, NXOpen.AttributePropertiesBuilder.OperationType.None)

Regards,
MFJ