How to Parse Text File delimited with ~ into a Datatable or Array in VB.Net - vb.net

I'm trying to parse the text file into an array or datatable where Lines Starting with D, O, and L are a single Row of data.
There are never more than 1 "L" Lines.
I want to get this into a datatable or 2-dimensional array where the column header names (locations) are
Date {D3}
Customer Name {O2}
Address {O3}
City {O7}
State {O8}
Zipcode {O9}
Reference ID {D17}
Amount {D20}
I tried
TextFieldParser("C:\Users\MyAccount\test.txt")
FileReader.SetDelimiters("~")
But I'm not understanding how to work with the output. Any ideas?
B~AAA~~12/03/19~12/03/19~1~428.51~APV~REF~K8~~
D~AAA~~12/03/19~12/03/19~APV~REF~N~REFUNDCIS~~12/03/19~0~N~N~Y~~~0000244909~~~72.90~~~00~N~0~12/03/19~0~12/03/19~12/03/19~0~K8~~~N~N~0~
O~JOHN DOE~ 1000 NOAKY LN ~~~~DETROIT~MI~31000~~~
L~01~141011~000~00000~000~00~000~~REFUND0000244909JOHN DOE~72.90~N~N~~~N~
D~AAA~~12/03/19~12/03/19~APV~REF~N~REFUNDCIS~~12/03/19~0~N~N~Y~~~0000404236~~~101.42~~~00~N~0~12/03/19~0~12/03/19~12/03/19~0~K8~~~N~N~0~
O~BRUCE DOE~UNIT 1 1000 E MICHIGAN AVE ~~~~DETROIT~MI~31000~~~
L~01~141011~000~00000~000~00~000~~REFUND0000404236BRUCE DOE~101.42~N~N~~~N~
D~AAA~~12/03/19~12/03/19~APV~REF~N~REFUNDCIS~~12/03/19~0~N~N~Y~~~0000436750~~~180.00~~~00~N~0~12/03/19~0~12/03/19~12/03/19~0~K8~~~N~N~0~
O~JOEL DOE~ 100 MICHIGAN AVE ~~~~DETROIT~MI~31000~~~
L~01~141011~000~00000~000~00~000~~REFUND0000436750JOEL DOE~180.00~N~N~~~N~
D~AAA~~12/03/19~12/03/19~APV~REF~N~REFUNDCIS~~12/03/19~0~N~N~Y~~~0000448122~~~74.19~~~00~N~0~12/03/19~0~12/03/19~12/03/19~0~K8~~~N~N~0~
O~JOHN DOE~ 100 MICHIGAN AVE ~~~~DETROIT~MI~31000~~~
L~01~141011~000~00000~000~00~000~~REFUND0000448122JOHN DOE~74.19~N~N~~~N~

First I took the code from MS docs https://learn.microsoft.com/en-us/dotnet/api/microsoft.visualbasic.fileio.textfieldparser?view=netcore-3.1
I needed to know how many columns I needed in the datatable.
Private Sub OpCode1()
Dim maxColumnCount As Integer
Using MyReader As New TextFieldParser("C:\Users\xxx\test.txt")
MyReader.TextFieldType = FieldType.Delimited
MyReader.Delimiters = {"~"}
Dim currentRow As String()
'Loop through all of the fields in the file.
'If any lines are corrupt, report an error and continue parsing.
While Not MyReader.EndOfData
Try
currentRow = MyReader.ReadFields()
' Include code here to handle the row.
If currentRow.Count > maxColumnCount Then
maxColumnCount = currentRow.Count
End If
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Line " & ex.Message & " is invalid. Skipping")
End Try
End While
End Using
MessageBox.Show(maxColumnCount.ToString)
End Sub
Once I had the number of columns needed, I created a DataTable and added the necessary number of columns. Then, where the Example instructed you to handle the row, I added the row to the DataTable. Lastly, I displayed the DataTable in a DataGridView.
Private Sub OPCode()
Dim dt As New DataTable
For i = 1 To 38
dt.Columns.Add(i.ToString)
Next
Using MyReader As New TextFieldParser("C:\Users\xxx\test.txt")
MyReader.TextFieldType = FieldType.Delimited
MyReader.Delimiters = {"~"}
Dim currentRow As String()
'Loop through all of the fields in the file.
'If any lines are corrupt, report an error and continue parsing.
While Not MyReader.EndOfData
Try
currentRow = MyReader.ReadFields()
' Include code here to handle the row.
dt.Rows.Add(currentRow)
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Line " & ex.Message & " is invalid. Skipping")
End Try
End While
End Using
DataGridView1.DataSource = dt
End Sub
More specific to your data...
Private Sub OpCode()
Dim dt As New DataTable
dt.Columns.Add("Date", GetType(Date))
dt.Columns.Add("Customer Name", GetType(String))
dt.Columns.Add("Address", GetType(String))
dt.Columns.Add("City", GetType(String))
dt.Columns.Add("State", GetType(String))
dt.Columns.Add("Zipcode", GetType(String))
dt.Columns.Add("RefID", GetType(String))
dt.Columns.Add("Amount", GetType(Decimal))
Dim DataDate As Date
Dim RefID As String = ""
Dim Amount As Decimal
Using MyReader As New TextFieldParser("C:\Users\maryo\test.txt")
MyReader.TextFieldType = FieldType.Delimited
MyReader.Delimiters = {"~"}
Dim currentRow As String()
'Loop through all of the fields in the file.
'If any lines are corrupt, report an error and continue parsing.
While Not MyReader.EndOfData
Try
currentRow = MyReader.ReadFields()
' Include code here to handle the row.
If currentRow(0) = "D" Then
DataDate = CDate(currentRow(3))
RefID = currentRow(17)
Amount = CDec(currentRow(20))
End If
If currentRow(0) = "O" Then
dt.Rows.Add({DataDate, currentRow(1), currentRow(2), currentRow(6), currentRow(7), currentRow(8), RefID, Amount})
End If
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Line " & ex.Message & " is invalid. Skipping")
End Try
End While
End Using
DataGridView1.DataSource = dt
End Sub
I assumed that the D row applies to the following O row. I saved the data from the D row in the 3 variables and used it when the next row is read.
Remember collections (including arrays) are zero based in .net.

Related

Skip the first line of the CSV file (Headers) Visual Basic

Like many on here, I am new to programming and mainly focus on web development. I have written a program cobbled together from help on here that works perfectly. I take a CSV file and inject it into an SQL database. I am getting a "MalformedLineException" line exception on the last line of the CSV file and believe it is because the header line is not being skipped.
Would love some help on working out how to skip the first line from my code below:
Private Sub subProcessFile(ByVal strFileName As String)
'This is the file location for the CSV File
Using TextFileReader As New Microsoft.VisualBasic.FileIO.TextFieldParser(strFileName)
'removing the delimiter
TextFileReader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited
TextFileReader.SetDelimiters(",")
ProgressBar1.Value = 0
Application.DoEvents()
'variables
Dim TextFileTable As DataTable = Nothing
Dim Column As DataColumn
Dim Row As DataRow
Dim UpperBound As Int32
Dim ColumnCount As Int32
Dim CurrentRow As String()
'Loop To read in data from CSV
While Not TextFileReader.EndOfData
Try
CurrentRow = TextFileReader.ReadFields()
If Not CurrentRow Is Nothing Then
''# Check if DataTable has been created
If TextFileTable Is Nothing Then
TextFileTable = New DataTable("TextFileTable")
''# Get number of columns
UpperBound = CurrentRow.GetUpperBound(0)
''# Create new DataTable
For ColumnCount = 0 To UpperBound
Column = New DataColumn()
Column.DataType = System.Type.GetType("System.String")
Column.ColumnName = "Column" & ColumnCount
Column.Caption = "Column" & ColumnCount
Column.ReadOnly = True
Column.Unique = False
TextFileTable.Columns.Add(Column)
ProgressBar1.Value = 25
Application.DoEvents()
Next
clsDeletePipeLineData.main()
End If
Row = TextFileTable.NewRow
'Dim Rownum As Double = Row
'If Rownum >= 1715 Then
' MsgBox(Row)
'End If
For ColumnCount = 0 To UpperBound
Row("Column" & ColumnCount) = CurrentRow(ColumnCount).ToString
Next
TextFileTable.Rows.Add(Row)
clsInsertPipeLineData.main(CurrentRow(0).ToString, CurrentRow(1).ToString, CurrentRow(2).ToString, CurrentRow(3).ToString, CurrentRow(4).ToString, CurrentRow(5).ToString, CurrentRow(6).ToString, CurrentRow(7).ToString, CurrentRow(9).ToString)
ProgressBar1.Value = 50
Application.DoEvents()
End If
Catch ex As _
Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Line " & ex.Message &
"is not valid and will be skipped.")
End Try
End While
ProgressBar1.Value = 100
Application.DoEvents()
clsMailConfirmation.main()
TextFileReader.Dispose()
MessageBox.Show("The process has been completed successfully")
End Using
"MalformedLineException" says that Line cannot be parsed using the current Delimiters, to fix it, adjust Delimiters so the line can be parsed correctly, or insert exception-handling code in order to handle the line.
Someone encountered similar question, maybe its reply can help you.

change the text of buttons from database (list of string)

I'm new to vb.net so I'm seeking for help,
I have method to create buttons in panel layout, and what I want is to set the TEXT for each button from database table ( but the customer TEXT ),
so how can I do it?
this is the method to generate buttons:
Private Sub GenerateTable(columnCount As Integer, rowCount As Integer)
'Clear out the existing controls, we are generating a new table layout
TableLayoutPanel1.Controls.Clear()
'Clear out the existing row and column styles
TableLayoutPanel1.ColumnStyles.Clear()
TableLayoutPanel1.RowStyles.Clear()
'Now we will generate the table, setting up the row and column counts first
TableLayoutPanel1.ColumnCount = columnCount
TableLayoutPanel1.RowCount = rowCount
For x As Integer = 0 To columnCount - 1
'First add a column
TableLayoutPanel1.ColumnStyles.Add(New ColumnStyle(SizeType.AutoSize))
For y As Integer = 0 To rowCount - 1
'Next, add a row. Only do this when once, when creating the first column
If x = 0 Then
TableLayoutPanel1.RowStyles.Add(New RowStyle(SizeType.AutoSize))
End If
'Create the control, in this case we will add a button
Dim cmd As New Button()
cmd.Width = 200
cmd.Height = 40
Dim count As Integer = TableLayoutPanel1.Controls.OfType(Of Button)().ToList().Count
fill_combobox
cmd.Name = "button_" & (count + 1)
cmd.Text = "button_" & (count + 1)
AddHandler cmd.Click, AddressOf Button_Click
Panel1.Controls.Add(cmd)
'cmd.Text = String.Format("({0}, {1})", x, y)
'Finally, add the control to the correct location in the table
TableLayoutPanel1.Controls.Add(cmd, x, y)
Next
Next
End Sub
this is how to call all customers TEXT or id as list of strings from database :
Dim myList As New List(Of String)()
Private Sub fill_combobox()
Try
If SQL.conn.State = ConnectionState.Open Then
SQL.conn.Close()
End If
SQL.conn.Open()
Dim cmd As New SqlCommand()
cmd.Connection = SQL.conn
cmd.CommandText = "SELECT cust_id FROM customers order by date"
Dim dr As SqlDataReader = cmd.ExecuteReader
While dr.Read
Dim esection As String = dr.Item(0)
myList.Add(String.Format(esection))
End While
dr.Close()
SQL.conn.Close()
Catch ex As SqlException
MsgBox(ex.Message, MsgBoxStyle.Critical, "SQL Error")
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, "General Error")
End Try
End Sub
Im elaborating on Subazs' comment. It could be easier to create a collection or List(of Button) then add all of your buttons into this as you itterate them into the flowtable. You can then call back to these at a later date, they will be stored in the list until you dispose of the form. NOTE they are with the form if you code it like this.
I have altered your code slightly too, you must remember to dispose the cmd as well as closing the connection (I had an awful experience not doing this which cost me!)
Dim myList As New List(Of String)
Dim myButtons As List(Of Button)
Public Sub Run_Me()
Retrieve_Customers()
'You can change the 5 and it will change the layout panel for you... :)
GenerateTable_and_Buttons(5)
MsgBox("All done!")
End Sub
'Replaces your (Fill_Combo_Box) method
Private Sub Retrieve_Customers()
Try
myList = New List(Of String)
If Sql.conn.State = ConnectionState.Open Then Sql.conn.Close()
Sql.conn.Open()
'Do you want to add in the customer name instead of ID? - if so we can change here...
Dim qry As String = "SELECT cust_id FROM customers order by date"
Dim cmd As New SqlCommand(qry, Sql.conn)
Dim dr As SqlDataReader = cmd.ExecuteReader
While dr.Read
Dim s As String = dr.Item(0)
myList.Add(String.Format(s))
End While
dr.Close()
cmd.Dispose()
Sql.conn.Close()
Catch ex As SqlException
MsgBox(ex.Message, MsgBoxStyle.Critical, "SQL Error")
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, "General Error")
End Try
'Now we have built a list of the customer - myList we can go on to count these...
End Sub
Private Sub GenerateTable_and_Buttons(columnCount As Integer)
If myList Is Nothing Then Exit Sub 'Just exit if we have no customers?
myButtons = New List(Of Button)
'This will round UP to make sure we have enough rows - also can do something like +1 on end if want extra?
Dim rowCount As Integer = CInt(Math.Round(Math.Ceiling(myList.Count / columnCount), 0))
Dim tlp As TableLayoutPanel = Me.TableLayoutPanel1
'Clear out the existing controls, we are generating a new table layout
tlp.Controls.Clear()
'Clear out the existing row and column styles
tlp.ColumnStyles.Clear()
tlp.RowStyles.Clear()
'Now we will generate the table, setting up the row and column counts first
tlp.ColumnCount = columnCount
tlp.RowCount = rowCount
Dim count As Integer = 0
For x As Integer = 0 To columnCount - 1
'First add a column
tlp.ColumnStyles.Add(New ColumnStyle(SizeType.AutoSize))
For y As Integer = 0 To rowCount - 1
'Next, add a row. Only do this when once, when creating the first column
If x = 0 Then
tlp.RowStyles.Add(New RowStyle(SizeType.AutoSize))
End If
'Create the control, in this case we will add a button
Dim cmd As New Button
cmd.Width = 200
cmd.Height = 40
'<<Add the customer ID into the TAG of the control, the tag is great place to store things
'We can then access the tag in another method, ie if we want to open it using your Button_Click
'method. We can say :
'Dim CustID As String = sender.Tag
'Then we can do other things with the ID....>>
If mylist.count > count then
cmd.Tag = myList(count)
cmd.Text = myList(count)
end if
'fill_combobox() ' I dont know why this is here?
cmd.Name = "button_" & (count + 1)
cmd.Text = "button_" & (count + 1)
AddHandler cmd.Click, AddressOf Button_Click
myButtons.Add(cmd)
'<<<<<<<<<<<<<<<<<
Panel1.Controls.Add(cmd) '<<<<<<<<< Whats Panel1????
'>>>>>>>>>>>>>>>>>>
'Finally, add the control to the correct location in the table
tlp.Controls.Add(cmd, x, y)
count += 1
Next
Next
End Sub

Parse fixed-width .csv file

i have .csv file which i need to parse. Its not delimted but fixed-with, ca you tell me what is the best way to parse such can of fail. This is the sample:
Object Name IP Address Name NE ID NE Type/Release Partition Access Profile Supervision State
MS-POLT01 10.45.3.11 MS-POLT01 1 7302 ISAM IHUB R4.3 defaultPAP Supervised
TPO-POLT02 10.34.1.33/10.74..61 TPO-POLT02 10 7302 ISAM IHUB R4.3 defaultPAP Supervised
WPU-POLT02 10.70.8.21 WPU-POLT02 100 7302 ISAM IHUB R4.3 defaultPAP Supervised
MOV-POLT01 10.70.2.45 MOV-POLT01 101 7302 ISAM IHUB R4.3 defaultPAP Supervised
Results of 'EROS': 6 records found. Duration 0 s.
This query was executed by john
EDIT - for further discussions:
Sub Main()
Using MyReader As New Microsoft.VisualBasic.FileIO.
TextFieldParser("file.csv")
MyReader.TextFieldType =
Microsoft.VisualBasic.FileIO.FieldType.Delimited
MyReader.Delimiters = New String() {vbTab}
Dim currentRow As String()
'Loop through all of the fields in the file.
'If any lines are corrupt, report an error and continue parsing.
While Not MyReader.EndOfData
Try
currentRow = MyReader.ReadFields()
' Debug.Print(String.Join(",", currentRow))
For Each currentField In currentRow
Debug.Print(currentField)
Next
' Include code here to handle the row.
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
Console.WriteLine("Line " & ex.Message & " is invalid. Skipping")
End Try
End While
End Using
Console.ReadLine()
End Sub
Use the TextFieldParser-class, it was exactly developed for this purpose:
MSDN Example:
Using Reader As New Microsoft.VisualBasic.FileIO.TextFieldParser("C:\TestFolder\test.log")
Reader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.FixedWidth
Reader.SetFieldWidths(5, 10, 11, -1)
Dim currentRow As String()
While Not Reader.EndOfData
Try
currentRow = Reader.ReadFields()
Dim currentField As String
For Each currentField In currentRow
MsgBox(currentField)
Next
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Line " & ex.Message &
"is not valid and will be skipped.")
End Try
End While
End Using

Deleting multiple records from sql bound Datagrid

The procedures below allowed me to delete several records at once by checking the checkbox on my datagrid. The procedure was written on ASP.net but now I am using a winform on VB.net.
I have a datagrid with column name "Delete" where the checkboxes are located. The user would check
the records it wants to delete and the would delete those records. I use the "Ticket Number" column values as the parameter for my query.
The issue I have is that since was written for ASP.Net, I cannot find how the winform VB.net equivalent for this line:
Dim chkDelete As CheckBox = DirectCast(grdRoster.Rows(i).Cells(0).FindControl("Delete_Row"), CheckBox)
FindControl is not a member of System.Windows.Forms.DataGridViewCell. Plus I am pretty sure that the whole line is wrong since the checkboxes
are located on a datagrid column set as ColumnType: DataGridViewCheckBoxColumn and are not really individual controls.
How can I get the same result on a winform? Here is my entire code.
Private Sub btnDelete_Click(sender As Object, e As EventArgs) Handles btnDelete.Click
'Create String Collection to store
'IDs of records to be deleted
Dim ticketNumberCollection As New StringCollection()
Dim strTicketNumber As String = String.Empty
'Loop through GridView rows to find checked rows
For i As Integer = 0 To grdRoster.Rows.Count - 1
Dim chkDelete As CheckBox = DirectCast(grdRoster.Rows(i).Cells(0).FindControl("Delete_Row"), CheckBox)
If chkDelete IsNot Nothing Then
If chkDelete.Checked Then
strTicketNumber = grdRoster.Rows(i).Cells(1).ToString
ticketNumberCollection.Add(strTicketNumber)
End If
End If
Next
'Call the method to Delete records
DeleteMultipleRecords(ticketNumberCollection)
' rebind the GridView
grdRoster.DataBind()
End Sub
' Sub to delete multiple records
' #param "idCollection" calls the string collection above
' and deletes the selected record separated by ","
Private Sub DeleteMultipleRecords(ByVal ticketNumberCollection As StringCollection)
Dim IDs As String = ""
'Create string builder to store
'delete commands separated by ,
For Each id As String In ticketNumberCollection
IDs += id.ToString() & ","
Next
Try
Dim strTicketID As String = IDs.Substring(0, IDs.LastIndexOf(","))
DataSheetTableAdapter.DeleteRecord(strTicketID)
Catch ex As Exception
Dim errorMsg As String = "Error in Deletion"
errorMsg += ex.Message
Throw New Exception(errorMsg)
Finally
Me.Close()
End Try
End Sub
for deleting multiple records from a data bound gridview you should create the DataGridViewCheckBoxColumn at run time
Dim chk As New DataGridViewCheckBoxColumn()
DataGridView1.Columns.Add(chk)
chk.HeaderText = "Select"
'then bind your datagridview with dataset
Dim sql As String = "SELECT * FROM table_name"
' Dim connection As New SqlConnection(connectionString)
conn.Open()
sCommand = New SqlCommand(sql, conn)
sAdapter = New SqlDataAdapter(sCommand)
sBuilder = New SqlCommandBuilder(sAdapter)
sDs = New DataSet()
sAdapter.Fill(sDs, "table_name")
sTable = sDs.Tables("table_name")
DataGridView1.DataSource = sDs.Tables("table_name")
'then traverse through each column and get the checked values
Try
DataGridView1.EndEdit()
For j = Me.DataGridView1.Rows.Count - 1 To 0 Step -1
If Not IsDBNull(DataGridView1.Rows(j).Cells(0).Value) Then
If DataGridView1.Rows(j).Cells(0).Value = True Then
check = True
If MessageBox.Show("Do you want to delete these records?", "Delete", MessageBoxButtons.YesNo) = DialogResult.Yes Then
For i = Me.DataGridView1.Rows.Count - 1 To 0 Step -1
If Not IsDBNull(DataGridView1.Rows(i).Cells(0).Value) Then
If DataGridView1.Rows(i).Cells(0).Value = True Then
'remove the checked columns and update datatable
DataGridView1.Rows.RemoveAt(i)
sAdapter.Update(sTable)
End If
End If
Next
Else
Return
End If
Else
End If
End If
Next
If check = False Then
MsgBox("Nothing Selected")
End If
Catch ex As Exception
MsgBox(ex.ToString)
End Try

VB.NET read only some cells for each row from csv file

I have a csv file that has the following structure :
id,name,adress,email,age
1,john,1 str xxxx,john#gmail.com,19
2,mike,2 bd xxxx,mike#gmail.com,21
3,jeana,1 str ssss,jeana#gmail.com,18
.......................
.......................
What I would like to do is to read the csv file, skip the first line (contains headers) and extract the 2nd, 3rd and 4th data from each row and populate a datagridview.
This is the code I'm using however it brings me all the csv content :
DataGridView1.ColumnCount = 4
DataGridView1.Columns(0).Name = "ID"
DataGridView1.Columns(1).Name = "NAME"
DataGridView1.Columns(2).Name = "ADRESS"
DataGridView1.Columns(3).Name = "AGE"
Using MyReader As New Microsoft.VisualBasic.FileIO.TextFieldParser _
(openFile.FileName)//the csv path
'Specify that reading from a comma-delimited file'
MyReader.TextFieldType = FileIO.FieldType.Delimited
MyReader.SetDelimiters(",")
Dim currentRow As String()
While Not MyReader.EndOfData
Try
currentRow = MyReader.ReadFields()
With DataGridView1.Rows.Add(currentRow) 'Add new row to data gridview'
End With
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Line " & ex.Message & "is not valid and will be skipped.")
End Try
End While
End Using
So can someone show me how to do that?
Thanks.
It could be simple as reading the first line and discard it, Then start to read the real data from your file
Using MyReader As New TextFieldParser(openFile.FileName)
MyReader.TextFieldType = FileIO.FieldType.Delimited
MyReader.SetDelimiters(",")
Dim currentRow As String()
' Read the first line and do nothing with it
If Not MyReader.EndOfData Then
currentRow = MyReader.ReadFields()
End If
While Not MyReader.EndOfData
Try
' Read again the file
currentRow = MyReader.ReadFields()
DataGridView1.Rows.Add(currentRow(1), currentRow(2),currentRow(3))
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Line " & ex.Message & "is not valid and will be skipped.")
End Try
End While
End Using
EDIT Seeing your comment below then I have changed the line that add the row to add only the strings at position 1,2 and 3. This of course is different from the columns added to the DataGridView. It is not clear if you want to change these columns to contains only these 3 fields. If you still want the column for ID and AGE in the grid you could change the Add to
DataGridView1.Rows.Add("", currentRow(1), currentRow(2),currentRow(3), "")