search for phrase in line of text box vb.net - vb.net

I'm using VB.NET and I've got a text box which contains the following information (that changes depending on the video file selected in a list box):-
type: ffmpeg-producer
filename: C:\caspar\Server\media\\adi.divx
width: 640
height: 360
progressive: false
fps: 25
loop: false
frame-number: 0
nb-frames: 4626
file-frame-number: 0
file-nb-frames: 4626
When I click a button, I need to add the data to a variable. So for example, I would need to take 4626 from the line
nb-frames: 4626
and 25 from the
line fps:25
and put them both in variables to then calculate the actual duration.

Public Function GetValue(ByVal varName As String) As String
Dim lines() As String = Split(TextBox1.Text, Delimiter:=Environment.NewLine)
For Each line As String In lines
Dim words() As String = Split(line, Delimiter:=": ", Limit:=2)
If words(0) = varName And words.Length = 2 Then
Return words(1)
End If
Next
Return Nothing
End Function

You could also use a regular expression approach. If you you are not familiar with regular expressions I strongly encourage you to into it.
Here is what you would do (where txtMyTextbbox is the textbox, that holds your data:
Dim strRegex as String = "([\w-]*):\s*(.*)"
Dim myRegex As New Regex(strRegex, RegexOptions.None)
Dim strTargetString As String = txtMyTextbox.Text
For Each myMatch As Match In myRegex.Matches(strTargetString)
If myMatch.Success Then
dim category = myMatch.Groups(1).Value
dim value = myMatch.Groups(2).Value
End If
Next
This code loops through all matches in your textbox text and looks for a text followed by a colon followed by spaces and the rest of the line. Each match is captured in the myMatch variable where you can access the part before the colon through myMatch.Groups(1).value and the part after the colon (excluding the space) through the second group.
Leave a comment if you have further questions.

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

Reading a file in and outputting to two listboxes

I'm using Imports System.IO and StreamReader inside a Windows Forms App.
I am trying to take a file, read it in, and output it into two listboxes. The text file is formatted like this.
Blue, 23.7
Green, 60.1
Black, 45.3
I want to output colours that have a higher value than 50 into one listbox, and the ones lower into another. So far all I've done is output the whole list into a textbox. The code for that looks like this:
srTextFile = File.OpenText(dataFile)
Do While srTextFile.EndOfStream = False
'read file by line, use the comma as a splitter
thisFile = srTextFile.ReadLine().Split(",")
For i As Integer = 0 To thisFile.GetUpperBound(0)
txtFileDisplay.AppendText(thisFile(i) &vbTab)
Next
txtFileDisplay.AppendText(vbCrLf)
Loop
I'm completely new to reading in files. I really don't know what I'm doing. I'm pretty new to arrays as well.
Thanks!
By using a class, you can create objects containing the color names as well as the double value and add those to the listboxes.
Public Class ColorValue
Public Property Name As String
Public Property Value As Double
Public Overrides Function ToString() As String
Return $"{Name} ({Value})"
End Function
End Class
Note that I've overridden ToString, because ListBox uses it to display a text for each item.
Now, you can add colors to the listboxes like this
For Each line As String In File.ReadLines(dataFile)
Dim parts As String() = line.Split(","c)
If parts.Length = 2 Then 'If line is well-shaped.
Dim value As Double
Double.TryParse(Trim(parts(1)), value) 'Gets 0 into value if conversion fails.
Dim color = New ColorValue With {.Name = parts(0), .Value = value}
If value > 50.0 Then
listBox1.Items.Add(color)
Else
listBox2.Items.Add(color)
End If
End If
Next
Now, you can get a color value back with
Dim c As ColorValue = DirectCast(listBox1.SelectedItem, ColorValue)
Dim n As String = c.Name
Dim v As Double = c.Value
You can make use of the System.IO.File Class to do this
Simply read the text file into a string
Split the string into lines
Split the lines into arrays
Parse the strings into doubles
Compare the doubles and get values greater than 50 into a seperate listbox
You can write your code like this:
For Each line As String In File.ReadAllLines("Your file here")
Dim Spl() AS String = Split(line, ",")
'Convert string value to integer
Dim myNum As Double = Double.Parse(Spl(1))'The number is the second item in the array
If myNum < 50.0 Then
'Add to your first Listbox here using
'Listbox.Add(myNum)
Else
'Add to your second Listbox here using
'Listbox.Add(myNum)
End If
Next

Lowercase the first word

Does anybody know how to lowercase the first word for each line in a textbox?
Not the first letter, the first word.
I tried like this but it doesn't work:
For Each iz As String In txtCode.Text.Substring(0, txtCode.Text.IndexOf(" "))
iz = LCase(iz)
Next
When you call Substring, it is making a copy of that portion of the string and returning it as a new string object. So, even if you were successfully changing the value of that returned sub-string, it still would not change the original string in the Text property.
However, strings in .NET are immutable reference-types, so when you set iz = ... all you are doing is re-assigning the iz variable to point to yet another new string object. When you set iz, you aren't even touching the value of that copied sub-string to which it previously pointed.
In order to change the value of the text box, you must actually assign a new string value to its Text property, like this:
txtCode.Text = "the new value"
Since that is the case, I would recommend building a new string, using a StringBuilder object, and then, once the modified string is complete, then set the text box's Text property to that new string, for instance:
Dim builder As New StringBuilder()
For Each line As String In txtCode.Text.Split({Environment.NewLine}, StringSplitOptions.None)
' Fix case and append line to builder
Next
txtCode.Text = builder.ToString()
The solutions here are interesting but they are ignoring a fundamental tool of .NET: regular expressions. The solution can be written in one expression:
Dim result = Regex.Replace(txtCode.Text, "^\w+",
Function (match) match.Value.ToLower(), RegexOptions.Multiline)
(This requires the import System.Text.RegularExpressions.)
This solution is likely more efficient than all the other solutions here (It’s definitely more efficient than most), and it’s less code, thus less chance of a bug and easier to understand and to maintain.
The problem with your code is that you are running the loop only on each character of the first word in the whole TextBox text.
This code is looping over each line and takes the first word:
For Each line As String In txtCode.Text.Split(Environment.NewLine)
line = line.Trim().ToLower()
If line.IndexOf(" ") > 0 Then
line = line.Substring(0, line.IndexOf(" ")).Trim()
End If
// do something with 'line' here
Next
Loop through each of the lines of the textbox, splitting all of the words in the line, making sure to .ToLower() the first word:
Dim strResults As String = String.Empty
For Each strLine As String In IO.File.ReadAllText("C:\Test\StackFlow.txt").Split(ControlChars.NewLine)
Dim lstWords As List(Of String) = strLine.Split(" ").ToList()
If Not lstWords Is Nothing Then
strResults += lstWords(0).ToLower()
If lstWords.Count > 1 Then
For intCursor As Integer = 1 To (lstWords.Count - 1)
strResults += " " & lstWords(intCursor)
Next
End If
End If
Next
I used your ideas guys and i made it up to it like this:
For Each line As String In txtCode.Text.Split(Environment.NewLine)
Dim abc() As String = line.Split(" ")
txtCode.Text = txtCode.Text.Replace(abc(0), LCase(abc(0)))
Next
It works like this. Thank you all.

how to read all strings that are between 2 other strings

i have managed to find a string between 2 specified strings,
the only issue now is that it will only find one and then stop.
how am i possible to make it grab all the strings in a textbox?
the textbox is multiline and i have put a litle config in it.
now i want that the listbox will add all the strings that are between my 2 specified strings.
textbox3.text containts "<"
and textbox 4.text contains ">"
Public Function GetClosedText(ByVal source As String, ByVal opener As String, ByVal closer As String) As String
Dim intStart As Integer = InStr(source, opener)
If intStart > 0 Then
Dim intStop As Integer = InStr(intStart + Len(opener), source, closer)
If intStop > 0 Then
Try
Dim value As String = source.Substring(intStart + Len(opener) - 1, intStop - intStart - Len(opener))
Return value
Catch ex As Exception
Return ""
End Try
End If
End If
Return ""
End Function
usage:
ListBox1.Items.Add(GetClosedText(TextBox1.Text, TextBox3.Text, TextBox4.Text))
The easiest way (least lines of code) to do this would be to use a regular expression. For instance, to find all of that strings enclosed in pointy brackets, you could use this regular expression:
\<(?<value>.*?)\>
Here's what that all means:
\< - Find a string which starts with a < character. Since < has a special meaning in RegEx, it must be escaped (i.e. preceded with a backslash)
(?<value>xxx) - This creates a named group so that we can later access this portion of the matched string by the name "value". Everything contained in the name group (i.e. where xxx is), is considered part of that group.
.*? - This means find any number of any characters, up to, but not including whatever comes next. The . is a wildcard which means any character. The * means any number of times. The ? makes it non-greedy so it stops matching as soon as if finds whatever comes next (the closing >).
\> - Specifies that matching strings must end with a > character. Since > has a special meaning in RegEx, it must also be escaped.
You could use that RegEx expression to find all the matches, like this:
Dim items As New List(Of String)()
For Each i As Match In Regex.Matches(source, "\<(?<value>.*?)\>")
items.Add(i.Groups("value").Value)
Next
The trick to making it work in your scenario is that you need to dynamically specify the opening and closing characters. You can do that by concatenating them to the RegEx, like this:
Regex.Matches(source, opener & "(?<value>.*?)" & closer)
But the problem is, that will only work if source and closer are not special RegEx characters. In your example, they are < and >, which are special characters, so they need to be escaped. The safe way to do that is to use the Regex.Escape method, which only escapes the string if it needs to be:
Private Function GetClosedText(source As String, opener As String, closer As String) As String()
Dim items As New List(Of String)()
For Each i As Match In Regex.Matches(source, Regex.Escape(opener) & "(?<value>.*?)" & Regex.Escape(closer))
items.Add(i.Groups("value").Value)
Next
Return items.ToArray()
End Function
Notice that in the above example, rather than finding a single item and returning it, I changed the GetClosedText function to return an array of strings. So now, you can call it like this:
ListBox1.Items.AddRange(GetClosedText(TextBox1.Text, TextBox3.Text, TextBox4.Text))
I ssume you want to loop all openers and closers:
' always use meaningful variable/control names instead of
If TextBox3.Lines.Length <> TextBox4.Lines.Length Then
MessageBox.Show("Please provide the same count of openers and closers!")
Return
End If
Dim longText = TextBox1.Text
For i As Int32 = 0 To TextBox3.Lines.Length - 1
Dim opener = TextBox3.Lines(i)
Dim closer = TextBox4.Lines(i)
listBox1.Items.Add(GetClosedText(longText, opener , closer))
Next
However, you should use .NET methods as shown here:
Public Function GetClosedText(ByVal source As String, ByVal opener As String, ByVal closer As String) As String
Dim indexOfOpener = source.IndexOf(opener)
Dim result As String = ""
If indexOfOpener >= 0 Then ' default is -1 and indices start with 0
indexOfOpener += opener.Length ' now look behind the opener
Dim indexOfCloser = source.IndexOf(closer, indexOfOpener)
If indexOfCloser >= 0 Then
result = source.Substring(indexOfOpener, indexOfCloser - indexOfOpener)
Else
result = source.Substring(indexOfOpener) ' takes the rest behind the opener
End If
End If
Return result
End Function

VB.Net Parse/Replace a substring in a line

I know this should be simple yet I am a little stuck. I am reading in a text file line by line. Each line is formated the same based off an ICD. I need to take the data at a specific location and replace it with x's.
For Example:
Line = "First Name Last Name Street Address State ZIP Other Data"
This is a fixed length ICD so address always starts at lets say position 100 and goes through 150
I need to replace everything position 100 to 150 with x's.
From there I am writing the line out to a new file and that part is working fine.
Thank you so much for your help.
Use this:
Dim newLine As String = Line.Substring(0, 100) & New String("x"c, 50) & line.Substring(150)
You can create a function that takes in the string, start index, and length and returns the string with the replaced characters. This will also handle error cases where the length is greater than string length (in which case the rest of the string is replaced with the char you've chosen).
Private Shared Function ReplaceCharsWithChar(input As String, firstIndex As Integer, length As Integer, replaceChar As Char) As String
Dim sb As New StringBuilder(input)
For i As Integer = firstIndex To Math.Min(firstIndex + length, input.Length) - 1
sb(i) = replaceChar
Next
Return sb.ToString()
End Function
And call it like this
Dim input As String = "First Name Last Name Street Address State ZIP Other Data"
Dim result As String = ReplaceCharsWithChar(input, 10, 5, "x"C)
'output would be First Namexxxxx Name Street Address State ZIP Other Data
There is no built-in method to do that, so you'll need to implement it yourself. The simplest way would be to use the String.Substring method to extract the parts you want (the beginning and ending of the string), and then concatenate them back together with the replacement value. For instance:
Dim newValue As String = line.Substring(0, 99) & New String("X"c, 50) & line.Substring(150)
However, if you need to replace more than one section of the string, it may be easier and more efficient to use the StringBuilder, which allows you to manipulate each character in place:
Dim builder As New StringBuilder(line)
For i As Integer = 100 to 149
builder.Chars(i) = "X"c
Next
line = builder.ToString()