Split text in group of "x" characters vb.net - vb.net

I need to split some text, but i'm having trouble with some extra spaces.
The following image shows the usual output text.
I want to add the split values in a checkedlistbox and i have the following code:
Dim SEPARATED = TextBox1.Text.Split(vbCr, vbLf, vbTab, ">") '" "C
CheckedListBox1.Items.Clear()
For Each item In separated
If item <> "" Then CheckedListBox1.Items.Add(item)
Next
CheckedListBox1.Items.Remove("#")
CheckedListBox1.Items.Remove("PI")
Dim MODIFIED As String() = ANSWER.ToString.Split(" ")
buuuuuuut the extra spaces are giving me headaches. I don't know how to split the text in groups of twelve chars ( they're always 12, the spaces complete them) .
In conclusion, using the example, i want to only show "DEFAULT","EX W SPACE","POTATO" and "HELP PLS".
Thank you !

I used the GetOPString() function to return a string with your items in it (DEFAULT","EX W SPACE","POTATO" and "HELP PLS") with a padding of 12 characters. That function you do not need because your source string is already built like that.
I used the following logic
Split source string into lines
If there is a word with no space in front (EXAMPLE), It is some sort of title so I ignore it (you didn't want it in the final result)
Trim word to remove all spaces and starting ">" character if found
See the example below.
You can tweak it according to your need.
Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
Dim Rawstring As String = GetOPString("DEFAULT","EX W SPACE","POTATO",">HELP PLS")
Dim SEPARATED As List(Of String) = GetListItems(Rawstring)
For Each Item As String In SEPARATED
CheckedListBox1.Items.Add(Item)
Next
End Sub
''' <summary>
''' Get a list of string by dividing Rawstring into 12 chars sequence.
''' Any space is trimmed and leading > character (if found) is removed.
''' </summary>
''' <param name="RawString"></param>
''' <returns></returns>
Private Function GetListItems(RawString As String) As IEnumerable(Of String)
Dim Output As New List(Of String)
For Each item In RawString.Split(vbCr)
If String.IsNullOrWhiteSpace(item) Then Continue For
Dim AssumeTitle As Boolean = Not String.IsNullOrWhiteSpace(item(0))
If AssumeTitle Then Continue For 'EXAMPLE is the title and we do not want it in the checkbox
item = item.Trim.TrimStart(">"c)
Output.Add(item)
Next
Return Output
End Function
''' <summary>
''' I used this function only to return the string you have in your post,
''' which is, words to be separated in 12 characters sequences.
''' </summary>
''' <returns></returns>
Private Function GetOPString(ByVal ParamArray Words As String()) As String
Dim Output As New Text.StringBuilder
Output.AppendLine("EXAMPLE")
Output.AppendLine()
For Each Item As String In Words
Output.Append(vbTab)
If Not Item.StartsWith(">") Then
Output.Append(" ")
End If
Output.AppendLine(Item.PadRight(12))
Next
Return Output.ToString
End Function

Related

Get a specific value from the line in brackets (Visual Studio 2019)

I would like to ask for your help regarding my problem. I want to create a module for my program where it would read .txt file, find a specific value and insert it to the text box.
As an example I have a text file called system.txt which contains single line text. The text is something like this:
[Name=John][Last Name=xxx_xxx][Address=xxxx][Age=22][Phone Number=8454845]
What i want to do is to get only the last name value "xxx_xxx" which every time can be different and insert it to my form's text box
Im totally new in programming, was looking for the other examples but couldnt find anything what would fit exactly to my situation.
Here is what i could write so far but i dont have any idea if there is any logic in my code:
Dim field As New List(Of String)
Private Sub readcrnFile()
For Each line In File.ReadAllLines(C:\test\test_1\db\update\network\system.txt)
For i = 1 To 3
If line.Contains("Last Name=" & i) Then
field.Add(line.Substring(line.IndexOf("=") + 2))
End If
Next
Next
End Sub
Im
You can get this down to a function with a single line of code:
Private Function readcrnFile(fileName As String) As IEnumerable(Of String)
Return File.ReadLines(fileName).Where(Function(line) RegEx.IsMatch(line, "[[[]Last Name=(?<LastName>[^]]+)]").Select(Function(line) RegEx.Match(line, exp).Groups("LastName").Value)
End Function
But for readability/maintainability and to avoid repeating the expression evaluation on each line I'd spread it out a bit:
Private Function readcrnFile(fileName As String) As IEnumerable(Of String)
Dim exp As New RegEx("[[[]Last Name=(?<LastName>[^]]+)]")
Return File.ReadLines(fileName).
Select(Function(line) exp.Match(line)).
Where(Function(m) m.Success).
Select(Function(m) m.Groups("LastName").Value)
End Function
See a simple example of the expression here:
https://dotnetfiddle.net/gJf3su
Dim strval As String = " [Name=John][Last Name=xxx_xxx][Address=xxxx][Age=22][Phone Number=8454845]"
Dim strline() As String = strval.Split(New String() {"[", "]"}, StringSplitOptions.RemoveEmptyEntries) _
.Where(Function(s) Not String.IsNullOrWhiteSpace(s)) _
.ToArray()
Dim lastnameArray() = strline(1).Split("=")
Dim lastname = lastnameArray(1).ToString()
Using your sample data...
I read the file and trim off the first and last bracket symbol. The small c following the the 2 strings tell the compiler that this is a Char. The braces enclosed an array of Char which is what the Trim method expects.
Next we split the file text into an array of strings with the .Split method. We need to use the overload that accepts a String. Although the docs show Split(String, StringSplitOptions), I could only get it to work with a string array with a single element. Split(String(), StringSplitOptions)
Then I looped through the string array called splits, checking for and element that starts with "Last Name=". As soon as we find it we return a substring that starts at position 10 (starts at zero).
If no match is found, an empty string is returned.
Private Function readcrnFile() As String
Dim LineInput = File.ReadAllText("system.txt").Trim({"["c, "]"c})
Dim splits = LineInput.Split({"]["}, StringSplitOptions.None)
For Each s In splits
If s.StartsWith("Last Name=") Then
Return s.Substring(10)
End If
Next
Return ""
End Function
Usage...
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
TextBox1.Text = readcrnFile()
End Sub
You can easily split that line in an array of strings using as separators the [ and ] brackets and removing any empty string from the result.
Dim input As String = "[Name=John][Last Name=xxx_xxx][Address=xxxx][Age=22][Phone Number=8454845]"
Dim parts = input.Split(New Char() {"["c, "]"c}, StringSplitOptions.RemoveEmptyEntries)
At this point you have an array of strings and you can loop over it to find the entry that starts with the last name key, when you find it you can split at the = character and get the second element of the array
For Each p As String In parts
If p.StartsWith("Last Name") Then
Dim data = p.Split("="c)
field.Add(data(1))
Exit For
End If
Next
Of course, if you are sure that the second entry in each line is the Last Name entry then you can remove the loop and go directly for the entry
Dim data = parts(1).Split("="c)
A more sophisticated way to remove the for each loop with a single line is using some of the IEnumerable extensions available in the Linq namespace.
So, for example, the loop above could be replaced with
field.Add((parts.FirstOrDefault(Function(x) x.StartsWith("Last Name"))).Split("="c)(1))
As you can see, it is a lot more obscure and probably not a good way to do it anyway because there is no check on the eventuality that if the Last Name key is missing in the input string
You should first know the difference between ReadAllLines() and ReadLines().
Then, here's an example using only two simple string manipulation functions, String.IndexOf() and String.Substring():
Sub Main(args As String())
Dim entryMarker As String = "[Last Name="
Dim closingMarker As String = "]"
Dim FileName As String = "C:\test\test_1\db\update\network\system.txt"
Dim value As String = readcrnFile(entryMarker, closingMarker, FileName)
If Not IsNothing(value) Then
Console.WriteLine("value = " & value)
Else
Console.WriteLine("Entry not found")
End If
Console.Write("Press Enter to Quit...")
Console.ReadKey()
End Sub
Private Function readcrnFile(ByVal entry As String, ByVal closingMarker As String, ByVal fileName As String) As String
Dim entryIndex As Integer
Dim closingIndex As Integer
For Each line In File.ReadLines(fileName)
entryIndex = line.IndexOf(entry) ' see if the marker is in our line
If entryIndex <> -1 Then
closingIndex = line.IndexOf(closingMarker, entryIndex + entry.Length) ' find first "]" AFTER our entry marker
If closingIndex <> -1 Then
' calculate the starting position and length of the value after the entry marker
Dim startAt As Integer = entryIndex + entry.Length
Dim length As Integer = closingIndex - startAt
Return line.Substring(startAt, length)
End If
End If
Next
Return Nothing
End Function

Label.Text only returns up to 8 characters

So I am currently working on a typing game in VB, and it has a random character generator.
So basically, Easy level generates 4 characters; Medium generates 8; and Hard generates 16.
The two levels (Easy and Medium) works fine, but on Hard, the generator only returns back random length of characters between 6 and 8.
What I have tried:
a. I tried to stop the Timer when the generator is working, then start it after again, because I thought it would be the problem, assuming that Timer.Tick forces the generator to stop, but it still didn't work.
b. I checked what the generator returns on message boxes (the generator is a function), and it returns 16 characters like normal.
So if b. works normal, then I am assuming that Label.Text has a problem.
Generator Function:
''' <summary>
''' </summary>
''' <param name="n">
''' <remarks>
''' Number of characters to generate.
''' </remarks>
''' </param>
''' <returns></returns>
''' <remarks></remarks>
Function GenerateCappedChar(ByVal n As Integer) As String
Dim result As String = ""
' Capital Chars
Dim charset As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Dim cs As String = Len(charset)
Dim count As Integer
Dim r As New Random
Do While count < n
Dim pos As Integer = r.Next(1, cs)
result &= charset(pos)
count += 1
Loop
Return result
End Function
Label.Text part:
Private Sub Ent_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Ent.Click
Type.Text = GenerateCappedChar(n) ' only returns character length in a range of 6-8
End Sub
I just realized that the AutoSize property of my Label is set to False, causing some text to not show.

Reading INI file with Visual Basic

I'm using Visual Basic to read a file which has frequently-used information. Specifically, my file contains information like this:
[Smith]
Name=Sam Smith
Email=sam.smith#yahoo.com
Project=Smith's Treehouse Project
Greeting=Hi Sam,
[Jones]
Name=Josh Jones
Email=josh.jones#gmail.com
Project=Jone's Second-Story Remodel
Greeting=Hi Josh,
I'm then trying to read the info into a simple VB command (actually using Dragon Naturally Speaking, but that shouldn't matter) to send an email in Microsoft Outlook. I don't need to write to the file, or change the values. I just need to read the info, so I can send the email address to the address field, the project name to the subject field, etc. through the use of List Variables.
How do I write a function to read from the file?
I've spent about 4 hours looking for answers here and on other sites, but am confused. (I'm obviously brand new to VB.) It seems like every time I find code that looks kind of close, it uses unique coding functions, so I don't know what the right one is.
Any help appreciated!
Perhaps not the most elegant solution, but here's a class that utilizes Regular Expressions to parse the INI:
Imports System.IO
Imports System.Text.RegularExpressions
Public NotInheritable Class IniParser
Private Shared SectionRegex As New Regex("\[(?<section>[^\n\[\]]+)\]\n*(?<valuelist>(.(?!\[[^\n\[\]]+\]))*)", RegexOptions.Singleline Or RegexOptions.CultureInvariant Or RegexOptions.Compiled)
Private Shared ValueRegex As New Regex("(?<valuename>[^=\n]+)=(?<value>[^\n]*)", RegexOptions.CultureInvariant Or RegexOptions.Compiled)
''' <summary>
''' Parses an .ini-file.
''' </summary>
''' <param name="FileName">The path to the file to parse.</param>
''' <remarks></remarks>
Public Shared Function ParseFile(ByVal FileName As String) As Dictionary(Of String, Dictionary(Of String, String))
Return IniParser.Parse(File.ReadAllText(FileName))
End Function
''' <summary>
''' Parses a text of .ini-format.
''' </summary>
''' <param name="Data">The text to parse.</param>
''' <remarks></remarks>
Public Shared Function Parse(ByVal Data As String) As Dictionary(Of String, Dictionary(Of String, String))
Dim Result As New Dictionary(Of String, Dictionary(Of String, String)) '(Section, (Value name, Value))
Dim Sections As MatchCollection = SectionRegex.Matches(Data)
'Iterate each section.
For Each SectionMatch As Match In Sections
Dim Section As New Dictionary(Of String, String)
Dim SectionName As String = SectionMatch.Groups("section").Value
Dim Values As MatchCollection = ValueRegex.Matches(SectionMatch.Groups("valuelist").Value)
If Result.ContainsKey(SectionName) = True Then
'A section by this name already exists.
Dim i As Integer = 1
'Append a number to the section name until a unique name is found.
While Result.ContainsKey(SectionName & i)
i += 1
End While
Result.Add(SectionName & i, Section)
Else
'A section by this name does not exist.
Result.Add(SectionName, Section)
End If
'Iterate each value of this section.
For Each ValueMatch As Match In Values
Dim ValueName As String = ValueMatch.Groups("valuename").Value
Dim Value As String = ValueMatch.Groups("value").Value
If Section.ContainsKey(ValueName) = True Then
'A value by this name already exists.
Dim i As Integer = 1
'Append a number to the value name until a unique name is found.
While Section.ContainsKey(ValueName & i)
i += 1
End While
Section.Add(ValueName & i, Value)
Else
'A value by this name does not exist.
Section.Add(ValueName, Value)
End If
Next
Next
Return Result
End Function
End Class
Example usage
Reading values in general:
Dim IniContents As Dictionary(Of String, Dictionary(Of String, String)) = IniParser.ParseFile("C:\path\to\your\file\here.ini")
For Each SectionName As String In IniContents.Keys
For Each ValueName As String In IniContents(SectionName).Keys
Dim Value As String = IniContents(SectionName)(ValueName)
'[SectionName]
'ValueName=Value
'ValueName=Value
'
'SectionName: The name of the current section (ex: Jones).
'ValueName : The name of the current value (ex: Email).
'Value : The value of [ValueName] (ex: josh.jones#gmail.com).
Console.WriteLine(SectionName & ": " & ValueName & " = " & Value)
Next
Next
Adding everything to a TreeView, where the node's Tag property is the value:
Dim IniContents As Dictionary(Of String, Dictionary(Of String, String)) = IniParser.ParseFile("C:\path\to\your\file\here.ini")
For Each SectionName As String In IniContents.Keys
Dim TopNode As TreeNode = TreeView1.Nodes.Add(SectionName)
Dim Section As Dictionary(Of String, String) = IniContents(SectionName)
For Each ValueName As String In Section.Keys
TopNode.Nodes.Add(New TreeNode(ValueName) With {.Tag = Section(ValueName)})
Next
Next
Screenshot of the TreeView example
Regex pattern explanation
SectionRegex:
\[(?<section>[^\n\[\]]+)\]\n*(?<valuelist>(.(?!\[[^\n\[\]]+\]))*)
\[ => Match '['.
(?<section> => Start of match group "section".
[^ => Match any character...
\n\[\] => ...that is not '[', ']' or a new line...
]+ => ...and match this one or more times.
) => End of match group "section".
\] => Match ']'.
\n* => Match zero or more new lines
(?<valuelist> => Start of match group "valuelist".
( => Start of unnamed match group.
. => Match any character...
(?! => ...that is not followed by...
\[[^\n\[\]]+\] => ...a section...
)
)* => ...and match this zero or more times.
) => End of match group "valuelist".
ValueRegex:
(?<valuename>[^=\n]+)=(?<value>[^\n]*)
(?<valuename> => Start of match group "valuename".
[^=\n]+ => Match one or more characters that are not '=' or a new line.
) => End of match group "valuename".
= => Match '='.
(?<value> => Start of match group "value".
[^\n]* => Match zero or more characters that are not a new line.
) => End of match group "value".
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim a() As String = IO.File.ReadAllLines(iniPath)
Dim user As String = "Jones"
Dim data As String = "Project"
For i = 0 To UBound(a)
If a(i) = "[" + user + "]" Then
For j = i To 1000
If a(j).Contains(data) Then TextBox1.Text = a(j).Replace(data + "=", "") : Exit For
Next
Exit for
End If
Next
End Sub

How to replace text string in a text file

I am new to vb.net and am trying to do something really simple. I have this code which reads certain line of text from .ini file.
Dim FilePath As String = Application.StartupPath & "\bin\userconfig.ini"
Dim text As String = IO.File.ReadAllText(FilePath)
Dim newText = text.Replace("UserName = ", TextBox_NewUser.Text)
IO.File.WriteAllText(FilePath, newText)
How do I make it replace that line of text after the "=" with something you type in TextBox_NewUser. As you can see with current code it just replaces the whole "UserName =" which I don't want.
That specific line of text in the .ini by default has this value:
"UserName = Unnamed"
So how do I make it replace just that "Unnamed" with something I type in TextBox_NewUser?
Any assistance will be most appreciated.
Dim newText = text.Replace("UserName = Unnamed", "UserName = " & TextBox_NewUser.Text)
Here is another way to go about this, there are additional assertions that could be done e.g. the code below assumes the lines don't begin with spaces and if they did you would first do a trim on each line before using StartsWith etc.
Config file
Role = Moderator
UserName = xxxx
Joined = 09/23/1006
Code
Public Class Form1
Private fileName As String =
IO.Path.Combine(
AppDomain.CurrentDomain.BaseDirectory, "userConfig.ini")
''' <summary>
''' assumes the file exist but does not assume there is text in
''' the text box.
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If Not String.IsNullOrWhiteSpace(TextBox_NewUser.Text) Then
Dim lines As List(Of String) = IO.File.ReadAllLines(fileName).ToList
For index As Integer = 0 To lines.Count - 1
If lines(index).ToLower.StartsWith("username") Then
lines(index) = String.Concat("UserName = ", TextBox_NewUser.Text)
End If
Next
IO.File.WriteAllLines(fileName, lines.ToArray)
End If
End Sub
End Class
Sample project on Microsoft OneDrive, VS2013
https://onedrive.live.com/redir?resid=A3D5A9A9A28080D1!907&authkey=!AKQCanSTiCLP4mE&ithint=file%2czip

VB.NET Search string

I want to search a specific part of a string in VB.NET. For example in the string below I want the following part: "Tennis".
Football ... Basketball ... Tennis ... Golf
I'm not sure how I would crop out the other part of the string so that im left with Tennis. Thanks :)
The solution below is my thought... You can use this function in any class you want, you pass it the string you want to check, what we should split on and finally what position do we want to get... I hope you do not mind Linq and lamda expression's...
''' <summary>
''' Return's word at index if it exist.
''' </summary>
''' <param name="Sentence"></param>
''' <param name="SplitString"></param>
''' <param name="Position"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function GetWordAtPosition(ByVal Sentence As String, ByVal SplitString As String, ByVal Position As Integer) As String
Dim ReturnWord As String = String.Empty
Dim ListPossibleWords As New List(Of String)
Try
'First see if we have a string, it's not empty or null, we have something to split on, and the actual word
'at the given position...
If Sentence IsNot Nothing AndAlso Not String.IsNullOrEmpty(Sentence) AndAlso SplitString IsNot Nothing AndAlso Not String.IsNullOrEmpty(SplitString) AndAlso Position > -1 Then
'Trim the string out...
Sentence = Sentence.Trim.Replace(" ", String.Empty)
'Does the string have what we need to split on?
If Sentence.Contains(SplitString) Then
'Split all this into a List(Of String)...
With ListPossibleWords
.AddRange(Strings.Split(Sentence, SplitString.ToCharArray))
.RemoveAll(Function(s As String) As Boolean
Return s.Equals(SplitString)
End Function)
End With
'Do we have a list now?
If ListPossibleWords.Count >= Position Then ReturnWord = ListPossibleWords.Item(Position - 1)
End If
End If
Return ReturnWord
Catch ex As Exception
Return ReturnWord
End Try
End Function
The following might do what you want.
Module VBModule
Sub Main()
Dim sSearchIn As String = "Football ... Basketball ... Tennis ... Golf"
Dim sSearchFor As String = " ... "
Dim lItemPosition As Long = 3
Dim lSkipLen As Long = sSearchFor.Length
Dim lIndex As Long
Dim sTemp as String
Dim i As Long
' Mid is one-based, IndexOf is zero-based
sTemp = sSearchIn
For lIndex = 1 To lItemPosition - 1
sTemp = Mid (sTemp, sTemp.IndexOf(sSearchFor) + 1 + lSkipLen)
Next lIndex
i = sTemp.IndexOf(sSearchFor)
If (i > 0) Then
Console.WriteLine(Left (sTemp, i))
Else
Console.WriteLine(sTemp)
End If
End Sub
End Module