To all
A bit of stupid question (another one I guess!) I am experimenting/learning the use of List(of String) . As my vb knowledge is a bit limited I tend to use brute force approach sometime when a predefined function may exist
I lifted an example from a code I have and use List (of String) as follow (I didn't write the function as it was beyond me!)
Function getTheRecordNames(ByVal sAFUFileName As String) As List(Of String)
if I follow the same approach then my test case works
Sub Main()
theLW.Open()
mylist()
End Sub
function mylist() As List(Of String)
mylist = New List(Of String)
dim i,j,k as integer
mylist.Add ("aa")
mylist.Add ("bb")
mylist.Add ("cc")
' Loop through list elements.
Dim num As Integer
For Each num In mylist
theLW.WriteLine ("num is " &num.ToString)
Next
end function
However I am trying to define the List(Of String) within the Main() or within an existing function and not as an output of a function, Nx does not like it. Something like
Dim mylist As New List(Of String)
The reason I am testing this? I have a function which read the data from a (user supplied) txt file line by line and split each line at the commas. An array of string (Nx3) is then returned. The returned array looks like
"aa" | "bb" | "cc" | "dd"
"aa" | "ee" | "cc" | "dd"
"aa" | "ff" | "cc" | "dd"
"kk" | "bb" | "jj" | "dd"
etc...
the array is then used to do some stuff and works as intended
I would like now test that each "line" is unique. After reading about the List function it seems that this can easily be done with a List. The duplicate lines are then removed.
Dim myFinalList As List(Of String) = mylist.Distinct().ToList
Would a kind soul push in the right direction?
Thanks
Regards
JXB
use of As New List(Of String)? - update
just found that The Distinct method is part of System.Linq !! Not a good start
Thanks
Regards
re: list(of String)
Yes, unfortunately, we cannot use the Linq functionality unless you have an author license and compile the code.
However, the list object does have a ".Contains" property which will allow us to avoid adding duplicates to the list. A quick example journal is below; note the "Imports System.Collections.Generic" statement at the top of the code. If that is left out, you would have to declare the list variable like this:
Dim uniqueValues As New Collections.Generic.List(Of String)
Here is the full example:
Option Strict Off
Imports System
Imports System.Collections.Generic
Imports NXOpen
Module Module36
Sub Main()
Dim theSession As Session = Session.GetSession()
Dim lw As ListingWindow = theSession.ListingWindow
lw.Open()
Dim rawData() As String = {"aa", "bb", "aa", "bb", "cc", "dd", "aa", "ee"}
'list all the values
lw.WriteLine("all values:")
For Each temp As String In rawData
lw.WriteLine(temp)
Next
lw.WriteLine("")
Dim uniqueValues As New List(Of String)
For Each temp As String In rawData
If Not uniqueValues.Contains(temp) Then
uniqueValues.Add(temp)
End If
Next
'list the unique values
lw.WriteLine("unique values:")
For Each temp As String In uniqueValues
lw.WriteLine(temp)
Next
lw.Close()
End Sub
End Module
re: list(of String)
Thanks for example NXJournaling. Much appreciated. Just tested the suggestion on my test function (which takes the data from the input file) and it works with the exception of the last entry not being removed if it's a duplicate!
Below is an extract of the function I am playing/test (GetInputfile() )
Thanks for the help
Dim delim As Char() = {","c}
Dim TotalFile As String
Dim asInputDataSplit(1,3) As String 'array is initialised
Dim astemp(),stemp as String
Dim asDataBlockLine() as string
Dim sr As StreamReader = New StreamReader(openFileDialog1.FileName)
TotalFile=sr.ReadToEnd()
sr.Close
asDataBlockLine = Split(TotalFile, vbLf)
'Resize array asInputDataSplit based on the total number of block
ReDim asInputDataSplit(Ubound(asDataBlockLine),3)
For i = 0 to Ubound(asDataBlockLine)
GetInputfile.Add (Trim(Replace(asDataBlockLine(i),vbLf, "")))
TheLW.WriteLine ("item is " & GetInputfile.Item(i))
Next
Dim uniqueValues As New List(Of String)
For Each temp As String In asDataBlockLine
If Not uniqueValues.Contains(temp) Then
uniqueValues.Add(temp)
End If
Next
'list the unique values
TheLW.WriteLine("unique values:")
For Each temp As String In uniqueValues
TheLW.WriteLine(temp)
Next
Thanks
Regards
re: unique values
At a guess, I'd say there is probably a non-printing character in the last line that makes it unique from the previous value; but visually, it appears to be non-unique.
re: unique values
That's my guess too but I have to go back to do real work. So will have a look at that later this week. Probably just a check/search for the possible non-printing character as a 1st debugging step
Thanks
Regards
re: unique values
just thinking abut it. If one has a text file
a,b,c,e
a,b,d,e
a,b,d,f
If one wants to split the whole file/string read in using StreamReader at each line does one use VbCr, vbLF or VBCrLf?
Jus noticed that I split the whole string/file using
asDataBlockLine = Split(TotalFile, vbCr)
but then a few lines later I do
asInputDataSplit(i,0) = Trim(Replace(astemp(0),vbLf, ""))
Thanks
Regards
re: control characters
I would try splitting the file into lines by using the VbCrLf character.
Alternately, you could read the file line by line, using the .ReadLine method of the streamreader object. The .ReadLine method will strip out the carriage return / new line characters; you can see an example here:
https://msdn.microsoft.com/en-us/library/system.io.streamreader.readline...
or here:
http://nxjournaling.com/content/read-text-file
re: control characters
I initially started with reading line-by-line option (copying the example from one of the links provided) but switched to reading the full file
Dim sr As StreamReader = New StreamReader(openFileDialog1.FileName)
TotalFile=sr.ReadToEnd()
sr.Close
I am however considering reviewing this approach as I am adding some checks to the code. Thinking about it if I read line by line I can skip the line that are not valid for example a line like: a,b,,d would not be valid as the user forgot specify 'c'
and only return an array of valid input line to be processed
Will have to think about this one
Thanks
Regards
JXb
Thanks
Regards
re: unique values aad ReadLine()
Just spent a few minutes testing the ReadLine() approach rather than reading the whole input text file. Seems to work (see below).
I haven't figured out to get the length of the uniqueValues List so that I can Redim the string array asInputDataSplit() but using a simple counter (k) seems to work. With this approach I can
read each line
check if it is non unique AND valid
if it is add it to the list uniqueValues
I then process the line read (it's unique and valid!)
by doing so I only return an valid array of string to the main function which means that no checks are required in the Main.
Thanks for your help
Regards
JXB
'-----------------------
If openFileDialog1.ShowDialog() = DialogResult.OK Then
TheLW.WriteLine("Input File selected: " & openFileDialog1.FileName)
Using sr As StreamReader = New StreamReader(openFileDialog1.FileName)
Try
sDataBlockLine = sr.ReadLine()
While Not sDataBlockLine Is Nothing
'add the new line to uniqueValues List(of String)
'Resize array asInputDataSplit based on the total number of block
If Not uniqueValues.Contains(sDataBlockLine) And CheckInputValidity(sDataBlockLine) = True Then
uniqueValues.Add(sDataBlockLine)
k +=1
astemp = Split(sDataBlockLine, delim) 'delim is "," Line can be split because it's unique and has no error
ReDim asInputDataSplit(k,3)
'allocate each "cell" to array asInputDataSplit()
asInputDataSplit(k,0) = Trim(astemp(0))
asInputDataSplit(k,1) = Trim(astemp(1))
asInputDataSplit(k,2) = Trim(astemp(2))
asInputDataSplit(k,3) = Trim(astemp(3))
Else
iNotKeptInputLine +=1
End If
sDataBlockLine = sr.ReadLine()
End While
'Close the input file
sr.Close
If iNotKeptInputLine <> 0 Then
TheLW.WriteLine("A total of " & iNotKeptInputLine.ToString & " lines will not be processed as they contained non-valid input")
End if
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Using
Thanks
Regards
re: count of objects in list
The .Count property will return the number of objects in a list. If you are creating an array, remember that they are zero based so you will need to specify .Count - 1 as the dimension.
Dim newArray(uniqueValues.Count - 1) as String
Avoiding Redim
> I haven't figured out to get the length of the uniqueValues List so that
> I can Redim the string array asInputDataSplit()
You shouldn't need a Redim -- that's the old-fashioned way.
If you have a list, and you want to put its members into an array, you don't need to dimension the array. You just write code like this:
Dim myThingList = new List(Of Thing)()
myList.Add(thing1)
myList.Add(thing2)
Dim myThingArray as Thing() = myThingList.ToArray()
RE: Avoiding Redim
Thanks NXJournaling for the .Count. tip. modified test code to read
k=uniqueValues.Count - 1
keeps it "neater"
Thanks ciao about reminding me the .ToArray() option. I have not forgotten about it but have not tested it because
1. the List (of String) contains the full input line i.e. each item in the list looks like "a,b,c,d,"
2. if I convert it to array then I get an array of N-1 entries (as many lines as the input file -1) containing the string "a,b,c,d,"
3. what I am testing is returning a Nx3 array to the main function where each "cell" has 1 value
returnedarray(0,0) = a
returnedarray(0,1) = b
returnedarray(0,2) = c
returnedarray(0,3) = d
in other word each line is split at the comma
What I have just realised is that I cannot use Redim Preserve as I can only resize the last dimension of the array. And I want to
resize the 1st one (the total number of line). There is no Transpose option last time I checked!
So I may have to
create an temp array: astemp = uniqueValues.ToArray
size the array to return: Redim returnedarray(Ubound(astemp ),3)
split each entry in astemp at the comma and allocate to returnedarray
Regards
JXB
Thanks
Regards
RE: Avoiding Redim - tested
How does one get the text to be shown as "code". I don't quite get the explanation!
Just tested something with the idea of using .ToArray instead of the Redim approach. I think I don't have to as ~I can loop the item in the List (there are all valid input). As one can only resize the last dimension of the array I thought of creating the List(of String) of all valid lines, get the count of the List, allocate size of the array to be returned and then split each item at the comma. Seems to work...
Using sr As StreamReader = New StreamReader(openFileDialog1.FileName)
Try
sDataBlockLine = sr.ReadLine()
While Not sDataBlockLine Is Nothing
If Not uniqueValues.Contains(sDataBlockLine) And CheckInputValidity(sDataBlockLine) = True Then
uniqueValues.Add(sDataBlockLine)
Else
iNotKeptInputLine +=1
End If
sDataBlockLine = sr.ReadLine()
End While
sr.Close
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Using
If uniqueValues.Count > 0 Then
ReDim asInputDataSplit(uniqueValues.Count-1,3)
For Each sline as String In uniqueValues
k = uniqueValues.IndexOf (sline)
astemp = Split(sline, delim)
'and allocate each "cell" to array asInputDataSplit()
asInputDataSplit(k,0) = Trim(astemp(0))
asInputDataSplit(k,1) = Trim(astemp(1))
asInputDataSplit(k,2) = Trim(astemp(2))
asInputDataSplit(k,3) = Trim(astemp(3))
Next sline
Return asInputDataSplit
Thanks
Regards
re: show text as code
To show text as code, surround the desired code text with <vbnet> </vbnet> tags and make sure the "text format" option (just below the add comment input box) is set to "filtered HTML" or "geshi".
<vbnet>
Your code here
</vbnet>
re: show text as code - Test
Using sr As StreamReader = New StreamReader(openFileDialog1.FileName)
Try
sDataBlockLine = sr.ReadLine()
While Not sDataBlockLine Is Nothing
If Not uniqueValues.Contains(sDataBlockLine) And CheckInputValidity(sDataBlockLine) = True Then
uniqueValues.Add(sDataBlockLine)
Else
iNotKeptInputLine +=1
End If
sDataBlockLine = sr.ReadLine()
End While
sr.Close
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Using
If uniqueValues.Count > 0 Then
ReDim asInputDataSplit(uniqueValues.Count-1,3)
For Each sline as String In uniqueValues
k = uniqueValues.IndexOf (sline)
astemp = Split(sline, delim)
'and allocate each "cell" to array asInputDataSplit()
asInputDataSplit(k,0) = Trim(astemp(0))
asInputDataSplit(k,1) = Trim(astemp(1))
asInputDataSplit(k,2) = Trim(astemp(2))
asInputDataSplit(k,3) = Trim(astemp(3))
Next sline
Return asInputDataSplit
Thanks
Regards
re: test
Success!
Am trying to read line by
Am trying to read line by line from a text file. but having trouble converting string to multiline string() .
Dim path As String = "\mypath\file.txt"
Dim objReader As StreamReader = New StreamReader(path)
Dim line As String = objReader.ReadLine()
Dim strings As String() = line
Call Drop_Text(line)
<\code>
Doing some thing wrong in this line on line
Dim strings As String() = line
<\code>
I have calling the SUB below to drop text as note in drafting window as below:
Public Sub Drop_Text(TextToDrop As String())
Dim theSession As NXOpen.Session = NXOpen.Session.GetSession()
Dim workPart As NXOpen.Part = theSession.Parts.Work
Dim displayPart As NXOpen.Part = theSession.Parts.Display
Dim nullNXOpen_Annotations_SimpleDraftingAid As NXOpen.Annotations.SimpleDraftingAid = Nothing
Dim draftingNoteBuilder1 As NXOpen.Annotations.DraftingNoteBuilder = Nothing
draftingNoteBuilder1 = workPart.Annotations.CreateDraftingNoteBuilder(nullNXOpen_Annotations_SimpleDraftingAid)
draftingNoteBuilder1.Origin.SetInferRelativeToGeometry(True)
draftingNoteBuilder1.Style.LetteringStyle.GeneralTextSize = 0.1
Dim nullNXOpen_View As NXOpen.View = Nothing
Dim point1 As NXOpen.Point3d = New NXOpen.Point3d(1, 3.5, 0.0)
Dim nXObject1 As NXOpen.NXObject = Nothing
draftingNoteBuilder1.Text.TextBlock.SetText(TextToDrop)
draftingNoteBuilder1.Origin.Origin.SetValue(Nothing, nullNXOpen_View, point1)
nXObject1 = draftingNoteBuilder1.Commit()
draftingNoteBuilder1.Destroy()
End Sub
<\code>
Regards,
MFJ
Thank you for all the help!
I accidentally found the "carriage return" character = vbCrLf
It's probably old news for all of you, but it was new to me!
Mike