Note Replacement Error

Hello all, I have used this site before wit great success. For reference I am using NX7.5 and trying to utilize the journal below

Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.UF
Imports NXOpenUI
Imports NXOpen.Utilities
Imports NXOpen.Annotations
 
Module ChangeNoteWord
    Sub Main()
        Dim s As Session = Session.GetSession()
        Dim dp As Part = s.Parts.Display
        Dim nc As NoteCollection = dp.Notes
        Dim notetext1 As String = "CURRENT WORD"
        notetext1 = NXInputBox.GetInputString("Change Note", "Note word to be changed", notetext1)
        Dim notetext2 As String = "REPLACEMENT WORD"
        notetext2 = NXInputBox.GetInputString("Change Note", "New note word", notetext2)
        Dim notestring() As String
        Dim nolines As Integer = 0
        Dim found1 As Boolean = False
        Dim m1 As Session.UndoMarkId = s.SetUndoMark(Session.MarkVisibility.Visible, "M1")
        For Each a_note As SimpleDraftingAid In nc
            notestring = a_note.GetText()
            nolines = notestring.Length
            For i As Integer = 0 To nolines - 1
                found1 = notestring(i).Contains(notetext1)
                If found1 = True Then
                    notestring(i) = notestring(i).Replace(notetext1, notetext2)
                End If
            Next
            a_note.SetText(notestring)
        Next
        s.UpdateManager.DoUpdate(m1)
    End Sub
 
    Public Function GetUnloadOption(ByVal dummy As String) As Integer
        GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately
    End Function
End Module

However, I receive this error

Runtime error:
NXOpen.NXException: Invalid text
at NXOpen.Annotations.SimpleDraftingAid.SetText(String[] lines)
at ChangeNoteWord.Main() in C:\Users\bbowley\AppData\Local\Temp\NXJournals7004\journal.vb:line 31

Any thoughts?

The error message states "invalid text"; what text are you searching for and what are you trying to replace it with?
Also, what region/language setting is your computer currently using?

Region:USA - English

Some text is XX and needs to be replaced with nothing so I blank the input line, however, with testing I tried replacing XX with AA being the new text and I receive the same message.

I'm able to reproduce your error if I try to replace text that shows up in a reference.

For instance: I have a view on the drawing with the label displayed (VIEW A). However, the "A" is reference text driven from an attribute. If I edit the annotation text of the label, it looks like this: "VIEW ". If I try to replace text that shows up in the reference, such as "VW", "TT", or "839", I get an invalid text error because the reference to the driving attribute is no longer valid. So even though "TT" doesn't show up on my drawing, it does exist as text in one of the notes/labels.

Check that the text you are trying to replace isn't driven by an expression or attribute value...

They are not driven by expression or attribute value. I am dealing with exported data and changing the sheet format, when I replace the format via importing a prt file with the new dwg format, the journal functions; I find this odd.

Can you email me a sample file where this error is occurring?
info@nxjournaling.com

Unfortunately due to the nature of the components, I cannot. I wish I could

If you copy the file and delete out the components, do you get the same error?

Yes.

I would like to change this journal to run only on note text items that I select, is that possible?

Is it possible?
Absolutely!
I suggest you start here:
http://nxjournaling.com/content/using-mask-triples-selectobject-routine

The function for selecting note objects (NX 7.5) will look something like this:

Function SelectObjects(ByVal prompt As String, ByRef selObj() as NXObject) As Selection.Response
 
	Dim theUI as UI = UI.GetUI
	Dim title As String = "Select notes"
	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.WorkPart
	Dim selectionMask_array(0) As Selection.MaskTriple
 
	With selectionMask_array(0)
		.Type = UFConstants.UF_drafting_entity_type
		.Subtype = UFConstants.UF_draft_note_subtype
	End With
 
	Dim resp as Selection.Response = theUI.SelectionManager.SelectObjects(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

The overall strategy is:

  • prompt user to select one or more note objects
  • loop through selected note objects
  • search and replace text

If you run into trouble, post back with specific questions.

after reading it seems that I am appending this block of code to the end, something like this perhaps?

Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.UF
Imports NXOpenUI
Imports NXOpen.Utilities
Imports NXOpen.Annotations
 
Module ChangeNoteWord
    Sub Main()
 
        Dim s As Session = Session.GetSession()
        Dim dp As Part = s.Parts.Display
        Dim nc As NoteCollection = dp.Notes
        Dim notetext1 As String = "CURRENT WORD"
        notetext1 = NXInputBox.GetInputString("Change Note", "Note word to be changed", notetext1)
        Dim notetext2 As String = "REPLACEMENT WORD"
        notetext2 = NXInputBox.GetInputString("Change Note", "New note word", notetext2)
        Dim notestring() As String
        Dim nolines As Integer = 0
        Dim found1 As Boolean = False
        Dim m1 As Session.UndoMarkId = s.SetUndoMark(Session.MarkVisibility.Visible, "M1")
        For Each a_note As SimpleDraftingAid In nc
            notestring = a_note.GetText()
            nolines = notestring.Length
            For i As Integer = 0 To nolines - 1
                found1 = notestring(i).Contains(notetext1)
                If found1 = True Then
                    notestring(i) = notestring(i).Replace(notetext1, notetext2)
                End If
            Next
            a_note.SetText(notestring)
        Next
        s.UpdateManager.DoUpdate(m1)
    End Sub
    Function SelectObjects(ByVal prompt As String, ByRef selObj() As NXObject) As Selection.Response
 
        Dim theUI As UI = UI.GetUI
        Dim title As String = "Select notes"
        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.WorkPart
        Dim selectionMask_array(0) As Selection.MaskTriple
 
        With selectionMask_array(0)
            .Type = UFConstants.UF_drafting_entity_type
            .Subtype = UFConstants.UF_draft_note_subtype
        End With
 
        Dim resp As Selection.Response = theUI.SelectionManager.SelectObjects(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
 
    Public Function GetUnloadOption(ByVal dummy As String) As Integer
        GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately
    End Function
End Module

I feel this is not correct.

Congratulations!
Step 1 is to add the function to the module, which you have done correctly. You will now be able to call the newly added function from any code within the module (such as Sub Main).

Step 2 is: we need to modify the existing code in Sub Main to make use of the new function.
About 1/2 through the Main subroutine (Sub Main), you will see the line:

For Each a_note As SimpleDraftingAid In nc

We need to understand what this line is doing so that we can modify it.
"For Each" - this starts a loop construct; we are going to perform some action on every item in a given collection. We don't need to know beforehand how many items are in the collection, the For Each loop will stop when the collection runs out of items.

"a_note As SimpleDraftingAid" - this part is a variable declaration. We are creating a variable named "a_note" and declaring it to be of type "SimpleDraftingAid". A "SimpleDraftingAid" is an object type defined by the NXOpen API; to see more details about this type of object, open the NXOpen .NET reference document (the compiled help file), activate the "index" tab and type in the keyword "SimpleDraftingAid". Selecting the resulting "SimpleDraftingAid class" link will open a page that lists all the available properties and methods that this object gives us access to (we'll be using the .GetText and .SetText methods).

"In nc" - this specifies what collection we want to work with. "nc" is the name of a variable; if we look at the variable declarations near the beginning of the code, we see it refers to the currently displayed part's note collection.

So, the programmer of this particular journal is going to process every note object in the currently displayed part without the user's intervention. We want to change that to only process the note objects that the user selects. We won't need the "nc" variable since we won't be using the part's note collection. However, we can modify it to our needs. Change this line of code:

Dim nc As NoteCollection = dp.Notes

to this:

Dim nc() As NXObject

The selection function is going to return an array of objects of type "NXObject", so we have modified "nc" to be an array of NXObject (the parentheses behind "nc" designate it as being an array).

Almost there!
Finally, we need to add the code that will call our selection function, allowing the user to select the note objects. Just before the "For Each" loop in the journal, add the following code:

If SelectObjects("Select objects", nc) = Selection.Response.Cancel Then
    Exit Sub
End if		

When the selection function is called, the familiar NX selection dialog will pop up. At this point the user can select one or more objects and press "OK", or they can press "Cancel". If the response = "Cancel" then we exit the subroutine (the Main subroutine), which in our particular case will end the journal with no questions asked. If the response is anything other than "Cancel" ("OK" is the only other option in this case), the journal will continue executing.

Try it out!

That was really helpful. I use it for Labels too, it works the same way.

I tyed to implement this for dimensions, particularly for after text. I can select the after text and print it in a listing window with .GetAppendedText.GetAfterText but i don't know how to change it. I have tried using SetAfterText instead of SetText but it didn't work.

I am new to this and i really don't know how to get it to work.

After you edit and set the appended text, you will need to perform an update to apply the changes, see example code below:

Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.UF
 
Module Module1
 
    Sub Main()
 
        Dim theSession As Session = Session.GetSession()
        Dim workPart As Part = theSession.Parts.Work
 
        Dim lw As ListingWindow = theSession.ListingWindow
        lw.Open()
 
        Dim markId1 As Session.UndoMarkId
        markId1 = theSession.SetUndoMark(Session.MarkVisibility.Invisible, "Start")
 
        Dim myDim As Annotations.Dimension
        If SelectDimension("Select a dimension", myDim) = Selection.Response.Back Then
            Exit Sub
        End If
 
        Dim myAppendedText As Annotations.AppendedText = myDim.GetAppendedText
 
        Dim newAfterText(0) As String
        newAfterText(0) = "NEW APPENDED TEXT"
        myAppendedText.SetAfterText(newAfterText)
 
        myDim.SetAppendedText(myAppendedText)
 
        'update dimension display
        myAppendedText.Dispose()
        Dim nErrs1 As Integer
        nErrs1 = theSession.UpdateManager.DoUpdate(markId1)
 
    End Sub
 
    Function SelectDimension(ByVal prompt As String, ByRef selDim As Annotations.Dimension) As Selection.Response
 
        Dim selObj As TaggedObject
        Dim theUI As UI = UI.GetUI
        Dim title As String = "Select a dimension"
        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.WorkPart
        Dim selectionMask_array(0) As Selection.MaskTriple
 
        With selectionMask_array(0)
            .Type = UFConstants.UF_dimension_type
            .Subtype = UFConstants.UF_all_subtype
        End With
 
        Dim resp As Selection.Response = theUI.SelectionManager.SelectTaggedObject(prompt, _
         title, scope, selAction, _
         includeFeatures, keepHighlighted, selectionMask_array, _
         selobj, cursor)
        If resp = Selection.Response.ObjectSelected OrElse resp = Selection.Response.ObjectSelectedByName Then
            selDim = selObj
            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

Hi,

I have used above journal to find and replace a text in a note.
But I need to get text after a string. i.e., If RGB393 or RGB465 is there in a note, I have to get both specifications separately by searching RGB.
Can you please help me to extract text or numbers after a string in a note.

Thanks,
Muthu

Regular expressions is one way to handle this situation. The code below extracts any numbers that follow the string "RGB". The code illustrates the technique on a string variable, but you can use the text from a note or other NX object that returns text.

Option Strict Off
Imports System
Imports System.Collections.Generic
Imports System.Text.RegularExpressions
Imports NXOpen
 
Module Module2
 
    Dim theSession As Session = Session.GetSession()
    Dim workPart As Part = theSession.Parts.Work
    Dim lw As ListingWindow = theSession.ListingWindow
 
    Sub Main()
 
        If IsNothing(theSession.Parts.BaseWork) Then
            'active part required
            Return
        End If
 
        lw.Open()
 
        Const undoMarkName As String = "regex replace"
        Dim markId1 As Session.UndoMarkId
        markId1 = theSession.SetUndoMark(Session.MarkVisibility.Visible, undoMarkName)
 
        Dim myRGBnums As New List(Of String)
 
        Dim myString As String = "A STRING RGB12 OTHER STUFF RGB987 AND ANOTHER RGB123456"
        myRGBnums = RGBNum(myString)
 
        If myRGBnums.Count > 0 Then
            lw.WriteLine("-------------------------")
        End If
 
        For Each temp As String In myRGBnums
            lw.WriteLine(temp)
        Next
 
        lw.Close()
 
    End Sub
 
    Function RGBNum(ByVal inputString As String) As List(Of String)
 
        Dim theMatches As New List(Of String)
 
        'change search string as needed
        Dim strRegex As String = "RGB(?<num>\d+)"
        Dim myRegex As New Regex(strRegex, RegexOptions.IgnoreCase Or RegexOptions.Multiline)
 
        Dim myMatches As MatchCollection = myRegex.Matches(inputString)
 
        lw.WriteLine(myMatches.Count.ToString & " matches found")
 
        For Each match As Match In myMatches
            Dim groups As GroupCollection = match.Groups
            'lw.WriteLine("match: " & groups.Item(0).Value)
            'lw.WriteLine("numbers found: " & groups.Item(1).Value)
            theMatches.Add(groups.Item(1).Value)
        Next
 
        Return theMatches
 
    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

That works fantastic. I really appreciate your help. On top of trying to learn VB.NET (as I know python and matlab really well) I do not have access to the help files for this project as they are on a different part of our network. Do you have any suggestions on how to utilize an access database with this Journal so that Col A has the value that is in the "current word" and Col B has the "replacement word"

I think that I need to add this code so far:

Imports System.Data.OleDb

and

Dim provider As String
Dim dataFile As String
Dim connString As String
Public myConnection As OleDbConnection = New OleDbConnection
Public dr As OleDbDataReader

and

Sub SpecCon
        provider = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source ="
        dataFile = "C:\XXXX\.accdb" ' Change it to your Access Database location
        connString = provider & dataFile
        myConnection.ConnectionString = connString
End Sub

If you are using 32 bit NX with 32 bit Office or 64 bit NX with 64 bit Office, it will probably work fine. However, if you are using 64 bit NX with 32 bit Office, you will probably run into a database driver issue. If this is the case, do some web searching - MS has a driver that allows a 64 bit application to talk to a 32 bit access database. Some claim that it "works like a charm"; others (myself included) had considerably less luck with it.

Sorry for bringing up this old Topic, could you Point me in the right direction where I can find this miraculous Driver that supposedly works for 64 to 32 Bit Communication? I am trying to do a macro that utilizes communication between NX and Access and I get Errors due to the 64/32 Bit Problem.
Thanks for your Help!