How to split string into a lines in a particular sequence - vb.net

I have a list of members with their stats and i need to split it by lines every 5 lines with a seperator.
It goes until 1000+ lines
Code :
Dim newString As String = RichTextBox1.Text.Replace(vbCr, ";").Replace(vbLf, ";")
Dim separator As Char = CChar(";")
Dim sArr As String() = newString.Split(separator)
Dim indexOfSplit As Integer = 4
Dim sFinal As String = Join(sArr.Take(indexOfSplit).ToArray, separator) & vbNewLine &
Join(sArr.Skip(indexOfSplit).ToArray, separator)
RichTextBox2.Text = sFinal
Output :
Desired Output :
The problem with my code is it does the job only for 1 line and I need it to be all lines in the string

The RichTextBox has a Lines property that returns an array of the lines. I used a StringBuilder to build the string for RichTextBox2. The For loop increments by 4 instead of the default 1.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ParseRTB()
End Sub
Private Sub ParseRTB()
Dim lines = RichTextBox1.Lines
Dim sb As New StringBuilder
For i = 0 To lines.Count - 4 Step 4
sb.AppendLine($"{lines(i)};{lines(i + 1)};{lines(i + 2)};{lines(i + 3)}")
Next
RichTextBox2.Text = sb.ToString
End Sub

Could do this with LINQ:
RichTextBox1.Lines _
.Select(Function(s,i) New With { .L = i\4, .S = s }) _
.GroupBy(Function(a) a.L) _
.Select(Function(g) string.Join(";"c, g.Select(Function(a) a.S))
This takes the lines of the rtb and projects them to a new sequence that includes a number that is the line number divided by 4 (so Howard's lines get 0, Roma's get 1 etc), then the input is grouped by that number and the grouping (a set of strings) is joined into a single string using semicolons..

Related

exclude header from csv in vb.net

I got a .csv and I want to load it into a datagridview. I have a button called button1 and I got a datagridview called datagridview1. I click the button and it appears... including the header, which I don't want.
Please:
How do I exclude the header from the .csv ?
code:
Imports System.IO
Imports System.Text
Public Class CSV_Reader
Private Sub CSV_Reader_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim filename As String = "C:\Users\Gaius\Desktop\meepmoop.csv"
Dim thereader As New StreamReader(filename, Encoding.Default)
Dim colsexpected As Integer = 7
Dim sline As String = ""
DataGridView1.Rows.Clear()
Do
sline = thereader.ReadLine
If sline Is Nothing Then Exit Do
Dim words() As String = sline.Split(";")
DataGridView1.Rows.Add("")
If words.Length = colsexpected Then
For ix As Integer = 0 To 6
DataGridView1.Rows(DataGridView1.Rows.Count - 2).Cells(ix).Value = words(ix)
Next
Else
DataGridView1.Rows(DataGridView1.Rows.Count - 2).Cells(0).Value = "ERROR"
End If
Loop
thereader.Close()
End Sub
End Class
meepmoop.csv:
alpha;bravo;charlie;delta;echo;foxtrot;golf
1;meep;moop;meep;moop;meep;moop
2;moop;meep;moop;meep;moop;meep
3;meep;moop;meep;moop;meep;moop
4;moop;meep;moop;meep;moop;meep
5;meep;moop;meep;moop;meep;moop
6;moop;meep;moop;meep;moop;meep
7;meep;moop;meep;moop;meep;moop
8;moop;meep;moop;meep;moop;meep
9;meep;moop;meep;moop;meep;moop
10;moop;meep;moop;meep;moop;meep
edit:
[...]
Dim sline As String = ""
DataGridView1.Rows.Clear()
Dim line As String = thereader.ReadLine()
If line Is Nothing Then Return
Do
sline = thereader.ReadLine
[...]
The above addition to the code works but I have no idea why. Nor do I understand why I have to -2 rather than -1. I can't rely on guesswork, I'm expected to one day do this professionally. But I just can't wrap my head around it. Explanation welcome.
edit:
Do
sline = thereader.ReadLine
If sline Is Nothing Then Exit Do
Dim words() As String = sline.Split(";")
If words.Count = 7 Then
DataGridView1.Rows.Add(words(0), words(1), words(2), words(3), words(4), words(5), words(6))
Else
MsgBox("ERROR - There are " & words.Count & " columns in this row and there must be 7!")
End If
Loop
I've shortened the Loop on the advice of a coworker, taking his word on it being 'better this way'.
Another method, using Enumerable.Select() + .Skip()
As noted in Ondřej answer, there's a specific tool for these operations: TextFieldParser
But, if there are no special requirements and the string parsing is straightforward enough, it can be done with the standard tools, as shown in Tim Schmelter answer.
This method enumerates the string arrays returned by the Split() method, and groups them in a list that can be then used in different ways. As a raw text source (as in this case) or as a DataSource.
Dim FileName As String = "C:\Users\Gaius\Desktop\meepmoop.csv"
Dim Delimiter As Char = ";"c
Dim ColsExpected As Integer = 7
If Not File.Exists(FileName) Then Return
Dim Lines As String() = File.ReadAllLines(FileName, Encoding.Default)
Dim StringColumns As List(Of String()) =
Lines.Select(Function(line) Split(line, Delimiter, ColsExpected, CompareMethod.Text)).
Skip(1).ToList()
DataGridView1.Rows.Clear()
'If the DataGridView is empty, add a `[ColsExpected]` number of `Columns`:
DataGridView1.Columns.AddRange(Enumerable.Range(0, ColsExpected).
Select(Function(col) New DataGridViewTextBoxColumn()).ToArray())
StringColumns.Select(Function(row) DataGridView1.Rows.Add(row)).ToList()
If you instead want to include and use the Header because your DataGridView is empty (it has no predefined Columns), you could use the Header line in the .csv file to create the control's Columns:
'Include the header (no .Skip())
Dim StringColumns As List(Of String()) =
Lines.Select(Function(line) Split(line, Delimiter, ColsExpected, CompareMethod.Text)).ToList()
'Insert the columns with the .csv header columns description
DataGridView1.Columns.AddRange(Enumerable.Range(0, ColsExpected).
Select(Function(col, idx) New DataGridViewTextBoxColumn() With {
.HeaderText = StringColumns(0)(idx)
}).ToArray())
'Remove the header line...
StringColumns.RemoveAt(0)
StringColumns.Select(Function(row) DataGridView1.Rows.Add(row)).ToList()
You can skip the header by calling ReadLine twice. Also use the Using-statement:
Using thereader As New StreamReader(filename, Encoding.Default)
Dim colsexpected As Integer = 7
Dim sline As String = ""
Dim line As String = thereader.ReadLine() ' header
if line is Nothing Then Return
Do
sline = thereader.ReadLine()
If sline Is Nothing Then Exit Do
Dim words() As String = sline.Split(";"c)
' ... '
Loop
End Using
You should use VB.NET class that is designed and tested for this purpose. It is Microsoft.VisualBasic.FileIO.TextFieldParser and you can skip header by calling ReadFields() once before you start parsing in loop.

Item pairing between two .txt

I have been trying to combine or pair two text files.
One file contains User:Key
The other file contains Key:Pass
I want a 3rd text file created containing the corresponding pairs of User:Pass based on the key matching.
Here is what Ive tried most recently
Private Sub Rotate()
Dim Cracked() As String = IO.File.ReadAllLines(TextBox1.Text)
For Each lineA In Cracked
TextBox5.Text = lineA
check()
Next
End Sub
Private Sub check()
Dim toCheck() As String = TextBox5.Text.Split(":")
Dim tHash As String = toCheck(0)
Dim tPass As String = toCheck(1)
Dim lines1() As String = IO.File.ReadAllLines(TextBox2.Text)
For Each line In lines1
If lines1.Contains(tHash) Then
Dim toAdd() As String = line.Split(":")
Dim uHash As String = toCheck(0)
Dim uUser As String = toCheck(1)
ListBox1.Items.Add(uUser + ":" + tPass)
End If
Next
End Sub
Public Sub CopyListBoxToClipboard(ByVal ListBox2 As ListBox)
Dim buffer As New StringBuilder
For i As Integer = 0 To ListBox1.Items.Count - 1
buffer.Append(ListBox1.Items(i).ToString)
buffer.Append(vbCrLf)
Next
My.Computer.Clipboard.SetText(buffer.ToString)
End Sub
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
CopyListBoxToClipboard(ListBox1)
End Sub
The delimiter changes but for now the : works.
I tried splitting and matching but either the textbox5 does not rotate or it rotates through the list and thats all.
Something like this?
Dim KeyPassFile As String = "..."
Dim UserKeyFile As String = "..."
Dim UserPassFile As String = "..."
Dim KeyPass As New Hashtable
' Read Key:Pass file
For Each Line In IO.File.ReadAllLines(KeyPassFile)
Dim iStart = Line.IndexOf(":")
Dim Key = Line.Substring(0, iStart)
Dim Pass = Line.Substring(iStart + 1)
KeyPass.Add(Key, Pass)
Next
' Create User:Pass file
Dim OutFile = IO.File.CreateText(UserPassFile)
' Read User:Key file
For Each Line In IO.File.ReadAllLines(UserKeyFile)
Dim iStart = Line.IndexOf(":")
Dim User = Line.Substring(0, iStart)
Dim Key = Line.Substring(iStart + 1)
If KeyPass.ContainsKey(Key) Then
' We have a match for the key, write it to the file
OutFile.WriteLine(User & ":" & KeyPass(Key))
End If
Next
OutFile.Close()
This will probably not work for very large files that doesn't fit in memory, and there is no duplicate check for the key insertion in the hashtable, but I'll leave something for you to do.. :)
Also, in your code, you read the file specified in the TextBox2.Text as many times as there are lines in the TextBox1.Text file..

How to Replace string and loop between commas with another string

can you help me how to get Index of the same string and replace it one by one with another string?
Here my example code :
For i As Integer = 0 To 10
Dim str As String = "abcd,abcd,abcd,abcd,abcd,abcd,abcd,abcd"
Dim replace As String = "efgh"
Dim value As String
value = str.Replace("abcd", replace)
TextBox4.AppendText(value)
Next
The value will be result : efgh,efgh,efgh,efgh,efgh...
How i can create the result like this :
efgh,abcd,abcd,abcd,abcd,abcd...
for the next loop it will be like this :
abcd,efgh,abcd,abcd,abcd,abcd...
for the next loop it will be like this :
abcd,abcd,efgh,abcd,abcd,abcd...
Thank you
There are lots of ways this could be done. One perhaps inefficient way would be to split the string at the commas, replace the appropriate item in the resulting array, and then join the array back up.
Dim str As String = "abcd,abcd,abcd,abcd,abcd,abcd,abcd,abcd"
Dim replace As String = "efgh"
For i As Integer = 0 To str.Count(Function(x) x = ","c)
Dim strParts = str.Split(","c)
strParts(i) = replace
Dim value As String = String.Join(",", strParts)
Console.WriteLine(value)
Next
Output:
efgh,abcd,abcd,abcd,abcd,abcd,abcd,abcd
abcd,efgh,abcd,abcd,abcd,abcd,abcd,abcd
abcd,abcd,efgh,abcd,abcd,abcd,abcd,abcd
abcd,abcd,abcd,efgh,abcd,abcd,abcd,abcd
abcd,abcd,abcd,abcd,efgh,abcd,abcd,abcd
abcd,abcd,abcd,abcd,abcd,efgh,abcd,abcd
abcd,abcd,abcd,abcd,abcd,abcd,efgh,abcd
abcd,abcd,abcd,abcd,abcd,abcd,abcd,efgh
As #Mark mentioned there are lots of ways this could be done. One of this ways to add and remove ranges in a string is to use the StringBuilder.
Imports System.Text
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For i As Integer = 0 To 35 Step 5
Dim sDefaultString As String = "abcd,abcd,abcd,abcd,abcd,abcd,abcd,abcd"
Dim sbText = New StringBuilder(sDefaultString)
sbText.Remove(i, 4)
sbText.Insert(i, "efgh")
TextBox1.AppendText(sbText.ToString & vbNewLine)
Next
End Sub
End Class

Flesch Readability Index in Visual Basic

I'm working on a program that is supposed to perform the calculations for the Flesch Readability Index. The program is supposed to read in a text file "Project7.txt", it's then supposed to display the text in a multi-line text box and perform the following calculations:
Count the number of words in the file.
Count the number of syllables in the file.
Count the number of sentences in the file (a sentence can be ended by a ".", "?", "!", or ":"
The program is then supposed to plug the values into the following formula and display the result in a label (label1).
206.835-85.6*(Number of syllables/Number of words) - 1.015*(Number of words/Number of sentences)
Here is the code I have written so far.
Option Strict On
Imports System.IO
Public Class Form1
Private Sub ExitToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ExitToolStripMenuItem.Click
Me.Close()
End Sub
Private Sub OpenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles OpenToolStripMenuItem.Click
Dim open As New OpenFileDialog
open.Filter = "text files |project7.txt|All file |*.*"
open.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)
If open.ShowDialog() = Windows.Forms.DialogResult.OK Then
Dim selectedFileName As String = System.IO.Path.GetFileName(open.FileName)
If selectedFileName.ToLower = "project7.txt" Then
Dim doc As String = ""
Dim line As String
Using reader As New StreamReader(open.OpenFile)
While Not reader.EndOfStream
doc += reader.ReadLine
Console.WriteLine(line)
End While
Dim text = File.ReadAllText("Project7.txt")
Dim words = text.Split(" "c)
Dim wordCount = words.Length
Dim separators As Char() = {"."c, "!"c, "?"c, ":"c}
Dim sentences = text.Split(separators, StringSplitOptions.RemoveEmptyEntries)
Dim sentenceCount = sentences.Length
End Using
Else
MessageBox.Show("You cannot use that file!")
End If
End If
End Sub
Function CountSyllables(word As String) As Integer
word = word.ToLower()
Dim dipthongs = {"oo", "ou", "ie", "oi", "ea", "ee", _
"eu", "ai", "ua", "ue", "au", "io"}
For Each dipthong In dipthongs
word = word.Replace(dipthong, dipthong(0))
Next
Dim vowels = "aeiou"
Dim vowelCount = 0
For Each c In word
If vowels.IndexOf(c) >= 0 Then vowelCount += 1
Next
Return vowelCount
End Function
End Class
Any suggestions are appreciated. Thanks in advance for the help.
Is the code always reporting one more sentence than there actually is?
If so take a look at this from the String.Split method MSDN docs:
When the Split function encounters two delimiters in a row, or a
delimiter at the beginning or end of the string, it interprets them as
surrounding an empty string ("")...
I'm sure your last sentence ends with your sentence delimiter so what's happening is your assignment to sentences is getting an extra, empty array element. See for yourself by breakpointing the line after your assignment and hovering your mouse over sentences. Examine the contents of the array.
The fix is to call Split with the option to remove empty array values. To do that though you'll need to call the Split overload that takes an array of Char for the delimiters:
Replace this line:
Dim sentences = text.Split("."c, "!"c, "?"c, ":"c)
With this:
Dim separators As Char() = {"."c, "!"c, "?"c, ":"c}
Dim sentences = text.Split(separators, StringSplitOptions.RemoveEmptyEntries)
And you should be good.

how to extract certain text from string

How do I filter/extract strings?
I have converted a PDF file into String using itextsharp and I have the text displayed into a Richtextbox1.
However there are too many irrelevant text that I don't need in the Richtextbox.
Is there a way I can display the text I want based on keywords, the entire length of the text.
Example of text that is displayed in textrichbox1 after conversation of PDF to text:
**774**
**Bos00232940
Bos00320491
Das1234
Das3216**
RAGE*
So the keywords would be "Bos", "Das", "774". and the new text that would be displayed in the richtextbox1 is shown below, instead of the entire text above.
*Bos00232940
Bos00320491
Das1234
Das3216
774*
Here is what I have so far. But it doesn't work it still displays the entire PDF in the richtextbox.
Public Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim pdffilename As String
pdffilename = TextBox1.Text
Dim filepath = "c:\temp\" & TextBox1.Text & ".pdf"
Dim thetext As String
thetext = GetTextFromPDF(filepath)
Dim lines() As String = System.Text.RegularExpressions.Regex.Split(thetext, Environment.NewLine)
Dim keywords As New List(Of String)
keywords.Add("Bos")
keywords.Add("Das")
keywords.Add("774")
Dim newTextLines As New List(Of String)
For Each line As String In lines
For Each keyw As String In thetext
If line.Contains(keyw) Then
newTextLines.Add(line)
Exit For
End If
Next
Next
RichTextBox1.Text = String.Join(Environment.NewLine, newTextLines.ToArray)
End Sub
SOLUTION
Thanks everyone for your help. Below is the code that worked and did exactly what I wanted it to do.
Public Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim pdffilename As String
pdffilename = TextBox1.Text
Dim filepath = "c:\temp\" & TextBox1.Text & ".pdf"
Dim thetext As String
thetext = GetTextFromPDF(filepath)
Dim re As New Regex("[\t ](?<w>((774)|(Bos)|(Das))[a-z0-9]*)[\t ]", RegexOptions.ExplicitCapture Or RegexOptions.IgnoreCase Or RegexOptions.Compiled)
Dim Lines() As String = {thetext}
Dim words As New List(Of String)
For Each s As String In Lines
Dim mc As MatchCollection = re.Matches(s)
For Each m As Match In mc
words.Add(m.Groups("w").Value)
Next
Next
RichTextBox1.Text = String.Join(Environment.NewLine, words.ToArray)
End Sub
For Each Word As String In thetext.Split(" ")
For Each key As String In keywords
If Word.StartsWith(key) Then
newTextLines.Add(Word)
Continue For
End If
Next
Next
or using LINQ:
Dim q = From word In thetext.Split(" ")
Where keywords.Any(Function(s) word.StartsWith(s))
Select word
RichTextBox1.Text = String.Join(Environment.NewLine, q.ToArray())
If don't know the keywords in advance but know in which context they occur, you can find them with a Regex expression. Two very handy Regex expressions allow you to find occurences succeeding or preceeding another:
(?<=prefix)find finds a pattern that follows another.
find(?=suffix) finds a pattern that comes before another.
If your number keyword (774) always preceeds " SIZE" you can find it like this: \w+(?=\sSIZE).
If the other keywords are always between "EX " and " DETAILS" you can find them like this: (?<=EX\s)(\w+\s)+(?=DETAILS).
You can put the whole thing together like this: \w+(?=\sSIZE)|(?<=EX\s)(\w+\s)+(?=DETAILS).
The disadvantage is that the keywords between "EX " and "DETAILS" will be returned as one match. But you can split the matches afterwards as in:
Const input As String = "2 3 3 4 4 A A B B SHEET 1 OF 1 774 SIZE SCALE 24.000-47.999 12.000-23.999 CON BAG WIRE 90in. EX Bos00232940 Bos00320491 Das1234 Das3216 DETAILS 1 2 RAGE"
Dim matches = Regex.Matches(input, "\w+(?=\sSIZE)|(?<=EX\s)(\w+\s)+(?=DETAILS)")
For Each m As Match In matches
Dim words = m.Value.Split(" "c)
For Each word As String In words
If word.Length > 0 Then ' Suppress the last empty word.
Console.WriteLine(word)
End If
Next
Next
Output:
774
Bos00232940
Bos00320491
Das1234
Das3216
How to do it with regular expression...
Dim re As New Regex("[\t ](?<w>((774)|(Bos)|(Das))[a-z0-9]*)[\t ]", RegexOptions.ExplicitCapture Or RegexOptions.IgnoreCase Or RegexOptions.Compiled)
Private Sub test()
Dim Lines() As String = {"2 3 3 4 4 A A B B SHEET 1 OF 1 774 SIZE SCALE 24.000-47.999 12.000-23.999 CON BAG WIRE 90in. EX Bos00232940 Bos00320491 Das1234 Das3216 DETAILS 1 2 RAGE"}
Dim words As New List(Of String)
For Each s As String In Lines
Dim mc As MatchCollection = re.Matches(s)
For Each m As Match In mc
words.Add(m.Groups("w").Value)
Next
Next
End Sub
Regex break down...
[\t ] Single tab or space (there is an alternative for whitespace too)
(?<w> Start of capture group called "w" This the the text returned later in the "m.Groups"
((774)|(Bos)|(Das)) one of the 3 blobs of text
[a-z0-9]* any a-z or 0-9 character, * = any number of them
) End of Capture group "w" from above.