Reading / Writing attributes into a parts without having it opened?

Hi,

I am trying to impove a program that is working fine but who need some more controls to prevent some end user input errors.
To do so, I am thinking on how I can do that. I have some ideas if it is possible, else I guess it'll be more difficult to set up, and above all slower.

Let's say I have 2 parts: Part A and Part B
Part B is a component of Part A.

Now suppose I have Part A as displayed part. I would like to know if it is possible to read and write part's attributes from Part B without having Part B as displayed part. Of course, I do not want to write "forced attributes" (as I used to call it). I mean, writing the attribute in a level assembly, not in the part itself.

Else I would be as displayed in Part A, read and store the needed attributes. Make Part B as displayed part (it's something I don't know how to do actually), read the attributes, compare them, write or overwrite attributes if needed, then go back to Part A.

Any ideas / clues about this?

What version of NX are you using?

I am using NX 7.5.5.4
Sadly, at the moment there are no plans to upgrade soon.

If you have a reference to the component, you can use the following code to set a part attribute.

For the sake of illustration, let's assume the component variable is named "myComponent":


myComponent.Prototype.OwningPart.SetAttribute("title", "attribute value")

If/when you upgrade to NX 8 or later, this code will need to be re-written. NX 8 made some changes to how attributes are handled.

Thanks for your help. It seems that it will be very usefull !
I guess that myComponent.Prototype.OwningPart.FindAttribute and myComponent.Prototype.OwningPart.AskPartAttribute will work as well. Isn't it?

To be able to write this, i'll have to look in depth in the tutorials provided on this great site to understand how to work with component.

I used to modify some recorded journals to suits my needs wich is pretty simple because I don't have to identify a specific component:
Dim theSession As Session = Session.GetSession()
Dim workPart As Part = theSession.Parts.Work

Dim displayPart As Part = theSession.Parts.Display

' ----------------------------------------------
' Définition et création de l'attribut DWG_REV
' ----------------------------------------------

Rev = ucase(right(thesession.Parts.Work.leaf, 1))

workPart.SetAttribute("DWG_REV", Rev)

End Sub

Thanks again !

I have built a new journal based on one of the online journals that make the component of the assembly as the display part. The function of the journal is to change the attribute of the specific components in the assembly (recognize by name) and make the component display part then will change the attribute. My concern is I don't want the journal to make the component work part or display part, I need the journal to get access to the attribute of the part (the component) without the need to make the component work part or display part.

or what is the replacement for this line of NX 7.5 myComponent.Prototype.OwningPart.SetAttribute("title", "attribute value") in NX 11

We are Using NX 11

Thank You for the Help

Raeed Kena
{Mechanical / Civil Engineer}

In NX 11, the .SetAttribute method is marked as obsolete. If you are creating a string type attribute, one replacement is the .SetUserAttribute(title, index, value, option) method. If you are dealing with an attribute array, the index will represent the index of the attribute you want to change. If you are dealing with a single attribute, use a value of -1 for the index. The option parameter is an enumeration value that tells NX to update the attribute now or later (attributes are closely tied to the expression system and a change to an attribute can trigger a model update).

Make sure the component part file is fully loaded and be sure to save the part after adding/changing the attribute.

Thank You for the quick respond!

This is the first version of the Journal that I was working on it, and I stopped because I did not have the code to get access to the list of the attribute for each component in the assembly. The current journal will go over the assembly components and display the total number of components that end with the word "PART".It doesn't recognize if the part has used in different subassemblies( it will count that again).

This subroutine is part of the journal and I believe your code line
workpart. SetUserAttribute(title, index, value, option)

'---------This subroutine is part of the attached journal--------------------
Sub reportComponentChildren( ByVal comp As Component, _
ByVal indent As Integer)

For Each child As Component In comp.GetChildren()
if child.GetChildren.Length=0 then
if Right(child.DisplayName(),4)="PART" then k=k+1
end if

reportComponentChildren(child, indent + 1)
Next
End Sub

'-------------------------------------------------

'-----THIS IS WORKING JOURNAL TO DISPLAY NUMBER OF COMPONENT WITH LAST 4 LETTER PART--------------------------

Option Strict Off
Imports System
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 k as integer=0
Sub Main()
Dim workPart As Part = theSession.Parts.Work
Dim dispPart As Part = theSession.Parts.Display
lw.Open
Try
Dim c As ComponentAssembly = dispPart.ComponentAssembly
if not IsNothing(c.RootComponent) then
ReportComponentChildren(c.RootComponent, 0)
msgbox(k)
exit sub
else
lw.WriteLine("Part has no components")
end if
Catch e As Exception
theSession.ListingWindow.WriteLine("Failed: " & e.ToString)
End Try
lw.Close
End Sub
'**********************************************************
Sub reportComponentChildren( ByVal comp As Component, _
ByVal indent As Integer)
For Each child As Component In comp.GetChildren()
if child.GetChildren.Length=0 then
if Right(child.DisplayName(),4)="PART" then k=k+1
end if
reportComponentChildren(child, indent + 1)
Next
End Sub
'**********************************************************
Public Function GetUnloadOption(ByVal dummy As String) As Integer
Return Session.LibraryUnloadOption.Immediately
End Function
'**********************************************************
End Module
'-----------------------------------------------------------------------

Raeed Kena
{Mechanical / Civil Engineer}

You can use the .GetUserAttributes method to access all the attributes that have been set on an object.

This the structure of simple assembly
A-TASM
B-ASM
D-PART
E-PART
C-SASM
F-PART
G-PART
D-PART
E-PART

when I update the subrotine with the current code ,it will add attribute infront of the sub assemblies only with word "RAE".It Does not recognize the part.

Sub reportComponentChildren( ByVal comp As Component, _
ByVal indent As Integer)

Dim title As String = "LBL" '---Updated line
Dim index As Integer = -1 '---Updated line
Dim value As String = "Here is my attribute value" '---Updated line
Dim updateOption As Update.Option = Update.Option.Now '---Updated line

For Each child As Component In comp.GetChildren()
if child.GetChildren.Length=0 then
if Right(child.DisplayName(),4)="PART" then k=k+1

comp.SetUserAttribute(title, index, "RAE", updateOption) '---Updated line

end if

reportComponentChildren(child, indent + 1)
Next
End Sub

Raeed Kena
{Mechanical / Civil Engineer}

Your code currently checks the "child" and if certain conditions are met, it adds an attribute to the "comp" (the parent). If I understand your requirement correctly, the code below should work for you.

Sub reportComponentChildren( ByVal comp As Component, ByVal indent As Integer)

Dim title As String = "LBL" '---Updated line

if comp.GetChildren.Length=0 then
if Right(comp.DisplayName(),4)="PART" then k=k+1
comp.SetUserAttribute(title, -1, "RAE", Update.Option.Now) '---Updated line
end if

For Each child As Component In comp.GetChildren()
reportComponentChildren(child, indent + 1)
Next
End Sub

Thank You

As I mentioned before this will add an attribute to the component (subassembly only)
I have uploaded the sample assembly with working recorded journal. Also I have attached image about how is the result need to be on the recorded image. In addition, I attached the current journal that I am working in with your upodate to the current code.I did run the code and I attached image of the result too.

at the upper right corner select direct download to get the zip file.

https://www.dropbox.com/s/em1c8yih2n1mmf3/TESA.zip?dl=0

Raeed Kena
{Mechanical / Civil Engineer}

Please update your journal with the code from my previous post, you will like the result. You missed the main modification in the subroutine. Checking the name and setting the attribute should be done outside of the For loop. The only thing in the For loop should be the call to "reportComponentChildren". I suggest copying my code above and pasting it over your existing subroutine.

Thank You for this really Perfect...

you mentioned If you are dealing with an attribute array, the index will represent the index of the attribute.
So what is the change that I need to make if I need more than one attribute at the same time?

Raeed Kena
{Mechanical / Civil Engineer}

Each call to .SetUserAttribute creates a single attribute. To set multiple attributes, make repeated calls to .SetUserAttribute with the desired parameters.

Thank You

Raeed Kena
{Mechanical / Civil Engineer}