How to transfer data from parallel arrays into a textbox? - vb.net

I'm trying to write a program that splits data from a text file into parallel arrays and then writes the content of each array in a textbox. The text file is something like this:
Title1, Genre1, Director1,
Title2, Genre2, Director2,
Title3, Genre3, Director3,
Imports System.IO
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim sr As New StreamReader("MovieData.txt")
Dim movieTitles(9), genre(9), directors(9), itemsRead() As String
Dim i As Integer = 0
Do Until sr.Peek = -1
itemsRead = sr.ReadLine.Split(",")
movieTitles(i) = itemsRead(0)
genre(i) = itemsRead(1)
directors(i) = itemsRead(2)
TextBox1.Text = movieTitles(i).PadRight(20) & genre(i).PadRight(20) & directors(i)
i += 1
Loop
sr.Dispose()
End Sub
End Class
When I click on the button, the textbox shows only:
Title3 Genre3 Director3
How can I fix this?

If you want your data to line up nicely, use a DataGridView. The extra functionality of a StreamReader is not necessary when you only need to pull data from a text file.
Now that classes and there properties are so easy you really don't need parallel arrays.
I added a custom constructor to the class so you can create a new instance and set all the properties in one line.
The list of Movie can be used as a data source for the grid. No need to set up columns.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim Movies As New List(Of Movie)
Dim lines = File.ReadAllLines("MovieData.txt")
For Each line In lines
Dim MovieProperties = line.Split(","c)
Dim M As New Movie(MovieProperties(0).Trim, MovieProperties(1).Trim, MovieProperties(2).Trim)
Movies.Add(M)
Next
DataGridView1.DataSource = Movies
End Sub
Public Class Movie
Public Property Title As String
Public Property Genre As String
Public Property Director As String
Public Sub New(T As String, G As String, D As String)
Title = T
Genre = G
Director = D
End Sub
End Class
EDIT as per OP comment
'**EDIT** Move the declaration of Movies to Form level
Private Movies As New List(Of Movie)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'**EDIT** Remove local declaration of Movies
Dim lines = File.ReadAllLines("MovieData.txt")
For Each line In lines
Dim MovieProperties = line.Split(","c)
Dim M As New Movie(MovieProperties(0).Trim, MovieProperties(1).Trim, MovieProperties(2).Trim)
Movies.Add(M)
Next
DataGridView1.DataSource = Movies
'To return the movies by Director, I strongly suggest you fill a list box with the
'director names so spelling errors won't frustate users
ListBox1.DataSource = GetUniqueDirectors()
End Sub
Private Function GetUniqueDirectors() As List(Of String)
'A bit of Linq using Distinct so we don't get duplicate listing of director names.
Dim Directors = ((From m In Movies
Order By m.Director
Select m.Director).Distinct()).ToList
Return Directors
End Function
Private Function GetMoviesByDirector(sDirector As String) As List(Of String)
'A little Linq magic to get the movies for selected director
Dim DirectorsMovies = (From s In Movies
Where s.Director = sDirector
Order By s.Title
Select s.Title).ToList
Return DirectorsMovies
End Function
Public Class Movie
Public Property Title As String
Public Property Genre As String
Public Property Director As String
Public Sub New(T As String, G As String, D As String)
Title = T
Genre = G
Director = D
End Sub
End Class
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
If ListBox1.SelectedIndex = -1 Then
MessageBox.Show("Please select a Director from the list.")
Return
End If
ListBox2.DataSource = Nothing
ListBox2.Items.Clear()
ListBox2.DataSource = GetMoviesByDirector(ListBox1.SelectedItem.ToString)
End Sub

It is done, just replace the code of the TextBox1.Text line like this one:
TextBox1.Text += movieTitles(i).PadRight(20) & genre(i).PadRight(20) & directors(i) & vbNewLine
I hope this answers your question bro,
^_^

Related

find in a text file all rows with a specific value and display them in the datagridview

Good day!
There is a .csv text file in the following format:
Fred Smith
f.smith
engineer
21.12.2021
Ben Taylor
b.taylor
programmer
23.12.2021
Bill Davis
b.davis
programmer
19.12.2021
Steve Harris
s.harris
engineer
23.12.2021
Tom Walker
t.walker
engineer
23.12.2021
with the following code I display data from a text file into a DataGridView:
Dim list() As String = IO.File.ReadAllLines("D:\UserList.csv", System.Text.Encoding.Default)
For i = 0 To UBound(list)
DataGridView1.Rows.Add()
Dim data() As String = Split(list(i), "|")
For j = 0 To UBound(data) - 1
DataGridView1.Item(j, i).Value = data(j)
Next
Next
Tell me how you can display in the datagridview from a text file only those employees where a certain date is indicated in the line of the text file?
For instance:
Specified the date - 23.12.2021
In the DataGridView I want the following result to be displayed:
Ben Taylor
b.taylor
programmer
23.12.2021
Steve Harris
s.harris
engineer
23.12.2021
Tom Walker
t.walker
engineer
23.12.2021
Tell me how you can make such a selection before displaying data from a text file in the DataGridView?
However, do not delete these lines in the text file.
For j = 0 To UBound(data)-1
loop run before Date of joining column so that data not add to grid so i removed -1.
Actual problem for the new row should specify the row and column number as below code.
Dim list() As String = IO.File.ReadAllLines("D:\UserList.csv", System.Text.Encoding.Default)
For i = 0 To UBound(list)
DataGridView1.Rows.Add()
Dim data() As String = Split(list(i), "|")
For j = 0 To UBound(data)
'DataGridView1.Item(j, i).Value = data(j)
DataGridView1.Rows(i).Cells(j).Value = data(j)
Next
Next
There are several ways available. If you put the data into something which implements the IBindingListView interface such as a DataTable then you could use the Filter property. Documentation for that: BindingSource.Filter Property
Or, as I show here, you can use a List and use LINQ to create the filter, like this:
Imports System.IO
Public Class Form1
Dim userData As List(Of User) = Nothing
Dim inputDateFormat As String = "dd.MM.yyyy"
Dim displayDateFormat As String = "dd.MM.yyyy"
Public Class User
Property Name As String
Property Email As String
Property Title As String
Property MagicDate As DateTime
Sub New(name As String, email As String, title As String, magicDate As DateTime)
Me.Name = name
Me.Email = email
Me.Title = title
Me.MagicDate = magicDate
End Sub
End Class
Sub LoadData(src As String)
userData = New List(Of User)
For Each a In File.ReadLines(src)
Dim parts = a.Split("|"c)
If parts.Count = 4 Then
Dim md = DateTime.ParseExact(parts(3), inputDateFormat, Nothing)
Dim u = New User(parts(0), parts(1), parts(2), md)
userData.Add(u)
End If
Next
End Sub
Sub ShowData()
' show all the data
ShowData(Nothing)
End Sub
Sub ShowData(selectedDate? As DateTime)
If userData Is Nothing Then
Exit Sub
End If
Dim bs As New BindingSource
If selectedDate.HasValue Then
' select only the data with the desired date
bs.DataSource = userData.Where(Function(u) u.MagicDate = selectedDate.Value)
Else
' show all the data
bs.DataSource = userData
End If
DataGridView1.DataSource = bs
DataGridView1.Columns("MagicDate").DefaultCellStyle.Format = displayDateFormat
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
LoadData("C:\temp\UserList.csv")
ShowData(New Date(2021, 12, 23))
End Sub
End Class
To get:
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Dim pattern As String = "23.12.2021"
Dim Path As String = "D:\UserList.csv"
Dim _row As String
Dim separator As Char = "|"
For Each _row In File.ReadAllLines(Path, Encoding.Default)
If _row.Contains(pattern) Then
DataGridView1.Rows.Add(_row.Split(separator))
End If
Next _row
End Sub
Why not do something like:
Dim list() As String = IO.File.ReadAllLines("D:\UserList.csv", System.Text.Encoding.Default)
Dim ub as Integer
For i = 0 To UBound(list)
Dim data() As String = Split(list(i), "|")
ub = UBound(data)
If data(ub) = "23.12.2021" Then
DataGridView1.Rows.Add()
For j = 0 To ub - 1
DataGridView1.Item(j, i).Value = data(j)
Next
End If
Next
Using the "User" class that Andrew Morton created:
Dim fileName = "C:\Bin\myFile.csv"
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim filterDate = Date.Parse("23.12.2021")
SetDataSource(filterDate)
End Sub
Private Sub SetDataSource(dateStamp As Date)
Dim data = File.ReadAllLines(fileName).Skip(1).
Select(Function(line) line.Split(",")).
Select(Function(x) New User(x)).
Where(Function(x) x.MagicDate = dateStamp)
DataGridView1.DataSource = data.ToList()
End Sub
Public Class User
Public Sub New(x() As String)
Name = x.ElementAt(0)
Email = x.ElementAt(1)
Title = x.ElementAt(2)
MagicDate = x.ElementAt(3)
End Sub
Property Name As String
Property Email As String
Property Title As String
Property MagicDate As DateTime
End Class
I added the Skip(1) in the LINQ so it ignores the header row. This can be removed if no header is present.

Passing list to function as parameter

I have a function that will perform work on a list, but I cannot get it to accept more than one datatype. For example:
Public Sub PopulateListBox (objectList as List(of VariantType), ListboxToPopulate as Listbox)
listboxToPopulate.Items.Clear() 'clears the items in the listbox
For Each item In objectList
listboxToPopulate.Items.Add(item.ToString)
Next
End
The problem is that I have lists of different classes, like employee, building address, etc. I cannot pass a List(Of EmployeeClass) because it says it cannot be converted to List(Of VariantType). I have also tried List(Of Object) and the same result.
I will demonstrate the use by first showing you a sample class.
Public Class Coffee
Public Property ID As Integer
Public Property Name As String
Public Property Type As String
Public Sub New(iid As Integer, sname As String, stype As String)
ID = iid
Name = sname
Type = stype
End Sub
Public Overrides Function ToString() As String
Return Name
End Function
End Class
I added a parameterized constructor just to make it easy to get a fully populate Coffee. You need to add the .ToString override so the list box will know what to display.
Here is where my List(Of Coffee) comes from.
Private Function FillCoffeeList() As List(Of Coffee)
Dim CoffeeList As New List(Of Coffee)
Using cn As New SqlConnection(My.Settings.CoffeeConnection),
cmd As New SqlCommand("Select Top 10 ID, Name, Type From Coffees;", cn)
cn.Open()
Using reader = cmd.ExecuteReader
Do While reader.Read
Dim c As New Coffee(reader.GetInt32(0), reader.GetString(1), reader.GetString(2))
CoffeeList.Add(c)
Loop
End Using
End Using
Return CoffeeList
End Function
As commented by Hans Passant, change the datatype of objectList to IEnumerable(Of Object).
Public Sub PopulateListBox(objectList As IEnumerable(Of Object), ListboxToPopulate As ListBox)
ListboxToPopulate.Items.Clear() 'clears the items in the listbox
For Each item In objectList
ListboxToPopulate.Items.Add(item)
Next
End Sub
Now I can pass a List(Of Coffee) to the PopulateListBox method.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim CList = FillCoffeeList()
PopulateListBox(CList, ListBox1)
End Sub
I can access the properties of the underlying type be casting.
Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedIndexChanged
Dim t = ListBox1.SelectedItem.GetType
Select Case t.Name
Case "Coffee"
Dim c = DirectCast(ListBox1.SelectedItem, Coffee)
TextBox1.Text = c.ID.ToString
TextBox2.Text = c.Type
End Select
End Sub
You can add additionsl cases depending on what types you are expecting. There is probably a better way to do this.

Own class can't convert string to integer

https://imgur.com/a/gaXh4
Ok so I have a problem a really weird problem. So I created a new class which is a new type of TextBox. It keeps track of the objects created from it with the help of a list but. This all works, with for each I can get all objects of the class but when I want to convert the string from the TextBox into a integer I can't do it because it thinks its not convertable eventhought the string only consists out of number symbols
Code for Button
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'TextBox1.Text = CInt(SumTextBox1.Text) + CInt(SumTextBox2.Text)
For Each item As SumTextBox In SumTextBox.sumList
Dim textItem As SumTextBox = item
TextBox1.Text = CInt(TextBox1.Text) + CInt(textItem.Text)
Next
End Sub
Public Class SumTextBox
Inherits TextBox
Public Shared sumList As New List(Of SumTextBox)
Sub New()
Size = New Size(90, 10)
sumList.Add(Me)
End Sub
End Class
Try using Convert.toInt32(TextBox1.Text) and the same for textitem.text

How to save many object (with the same class) to txt file and binding those object with listbox VB.NET

I try to program a simple project to save data to txt file, read it and use binding data to show it. My project like this.
When I add ID Person to "Add ID" textbox (Textbox which near Button "Add ID"). It will add ID to Listbox and "ID Name" textbox. With this IDName, I insert FirstName and LastName for first person and Save Person's Name. Then, I Add new ID in "Add ID" textbox and fill First,last name and save it again
I refer this page http://vbnetsample.blogspot.de/2007/12/serialize-deserialize-class-to-file.html?m=1 to save and read data to txt file. It's run ok. But my problem is that when I save Person 2 with ID 2, Person 1 is overwrited. I think I can save Person to List Person. But it will make difficult when I want to update any Person's data. I don't know whether Is there any way to save and update each person. And by the way How can I show data by binding data in listbox.
Here is my code
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.IO
Public Class Form1
Public pPerson As New Person
'Serialize and Save Data to txt file
Private Sub SaveButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveButton.Click
pPerson.IDName = IDNameTextBox.Text
pPerson.FirstName = FirstNameTextBox.Text
pPerson.LastName = LastNameTextBox.Text
Dim fs As FileStream = New FileStream("C:\Users\Bruce\Desktop\test.txt", FileMode.OpenOrCreate)
Dim bf As New BinaryFormatter()
bf.Serialize(fs, pPerson)
fs.Close()
End Sub
'Deserialize and Read Data from txt file
Private Sub ReadButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ReadButton.Click
If FileIO.FileSystem.FileExists("C:\Users\Bruce\Desktop\test.txt") Then
Dim fsRead As New FileStream("C:\Users\Bruce\Desktop\test.txt", FileMode.Open)
Dim bf As New BinaryFormatter()
Dim objTest As Object = bf.Deserialize(fsRead)
fsRead.Close()
IDNameTextBox.Text = objTest.IDName
FirstNameTextBox.Text = objTest.FirstName
LastNameTextBox.Text = objTest.LastName
End If
End Sub
Private Sub AddIDButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AddIDButton.Click
ListBox1.Items.Insert(0, AddIDTextBox.Text)
IDNameTextBox.Text = AddIDTextBox.Text
End Sub
End Class
'Create Class Person
<System.Serializable()>
Public Class Person
Private m_sIDName As String
Private m_sFirstName As String
Private m_sLastName As String
Public Sub New()
End Sub
Public Property IDName() As String
Get
Return Me.m_sIDName
End Get
Set(ByVal value As String)
Me.m_sIDName = value
End Set
End Property
Public Property FirstName() As String
Get
Return Me.m_sFirstName
End Get
Set(ByVal value As String)
Me.m_sFirstName = value
End Set
End Property
Public Property LastName() As String
Get
Return Me.m_sLastName
End Get
Set(ByVal value As String)
Me.m_sLastName = value
End Set
End Property
End Class
To me it seems like the issue here is
Dim fs As FileStream = New FileStream("C:\Users\Bruce\Desktop\test.txt", FileMode.OpenOrCreate)
you have to change it to this:
If not File.Exists("C:\Users\Bruce\Desktop\test.txt") Then
File.create("C:\Users\Bruce\Desktop\test.txt")
End If
Dim fs As FileStream = New FileStream("C:\Users\Bruce\Desktop\test.txt", FileMode.Append)
The whole problem was that your file was simply open (or created if it was not there before) and being written from the first line.By using FileMode.Append your File will be opened and anything new will be tried to be written at the end of the file.
Let me know if this worked :)

Multiple Search Criteria (VB.NET)

So my problem is:
I have a List of a custom Type {Id as Integer, Tag() as String},
and i want to perform a multiple-criteria search on it; eg:
SearchTags={"Document","HelloWorld"}
Results of the Search will be placed a ListBox (ListBox1) in this format:
resultItem.id & " - " & resultItem.tags
I already tried everything i could find on forums, but it didn't work for me (It was for db's or for string datatypes)
Now, i really need your help. Thanks in advance.
For Each MEntry As EntryType In MainList
For Each Entry In MEntry.getTags
For Each item As String In Split(TextBox1.Text, " ")
If Entry.Contains(item) Then
If TestIfItemExistsInListBox2(item) = False Then
ListBox1.Items.Add(item & " - " & Entry.getId)
End If
End If
Next
Next
Next
Example Custom Array:
(24,{"snippet","vb"})
(32,{"console","cpp","helloworld"})
and so on...
I searched for ("Snippet vb test"):
snippet vb helloWorld - 2
snippet vb tcpchatEx - 16
cs something
test
So, i'll get everything that contains one of my search phrases.
I expected following:
snippet vb tcp test
snippet vb dll test
snippet vb test metroui
So, i want to get everything that contains all my search phrases.
My entire, code-likely class
Imports Newtonsoft.Json
Public Class Form2
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Dim MainList As New List(Of EntryType)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
MainList.Clear()
Dim thr As New Threading.Thread(AddressOf thr1)
thr.SetApartmentState(Threading.ApartmentState.MTA)
thr.Start()
End Sub
Delegate Sub SetTextCallback([text] As String)
Private Sub SetTitle(ByVal [text] As String) ' source <> mine
If Me.TextBox1.InvokeRequired Then
Dim d As New SetTextCallback(AddressOf SetTitle)
Me.Invoke(d, New Object() {[text]})
Else
Me.Text = [text]
End If
End Sub
Sub thr1()
Dim linez As Integer = 1
Dim linex As Integer = 1
For Each line As String In System.IO.File.ReadAllLines("index.db")
linez += 1
Next
For Each line As String In System.IO.File.ReadAllLines("index.db")
Try
Application.DoEvents()
Dim a As saLoginResponse = JsonConvert.DeserializeObject(Of saLoginResponse)(line) ' source <> mine
Application.DoEvents()
MainList.Add(New EntryType(a.id, Split(a.tags, " ")))
linex += 1
SetTitle("Search (loading, " & linex & " of " & linez & ")")
Catch ex As Exception
End Try
Next
SetTitle("Search")
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim searchTags() As String = TextBox1.Text.Split(" ")
Dim query = MainList.Where(Function(et) et.Tags.Any(Function(tag) searchTags.Contains(tag))).ToList
For Each et In query
ListBox1.Items.Add(et.Id)
Next
End Sub
Private Sub Button4_Click(sender As Object, e As EventArgs) ' test
MsgBox(Mid(ListBox1.SelectedItem.ToString, 1, 6)) ' test
End Sub 'test, removeonrelease
End Class
Public Class EntryType
Public Property Id As Integer
Public Property Tags() As String
Public Sub New(ByVal _id As Integer, ByVal _tags() As String)
Me.Id = Id
Me.Tags = Tags
End Sub
Public Function GetTags() As String
'to tell the Listbox what to display
Return Tags
End Function
Public Function GetId() As Integer
'to tell the Listbox what to display
Return Id
End Function
End Class
I also edited your EntryType class; I added a constructor, removed toString and added GetTags and GetID.
Example "DB" im working with ("db" as "index.db" in exec dir):
{"tags":"vb.net lol test qwikscopeZ","id":123456}
{"tags":"vb.net lol test","id":12345}
{"tags":"vb.net lol","id":1234}
{"tags":"vb.net","id":123}
{"tags":"cpp","id":1}
{"tags":"cpp graphical","id":2}
{"tags":"cpp graphical fractals","id":3}
{"tags":"cpp graphical fractals m4th","id":500123}
Error:
Debugger:Exception Intercepted: _Lambda$__1, Form2.vb line 44
An exception was intercepted and the call stack unwound to the point before the call from user code where the exception occurred. "Unwind the call stack on unhandled exceptions" is selected in the debugger options.
Time: 13.11.2014 03:46:10
Thread:<No Name>[5856]
Here is a Lambda query. The Where filters on a predicate, since Tags is an Array you can use the Any function to perform a search based on another Array-SearchTags. You can store each class object in the Listbox since it stores Objects, you just need to tell it what to display(see below).
Public Class EntryType
Public Property Id As Integer
Public Property Tags() As As String
Public Overrides Function ToString() As String
'to tell the Listbox what to display
Return String.Format("{0} - {1}", Me.Id, String.Join(Me.Tags, " "))
End Function
End Class
Dim searchTags = textbox1.Text.Split(" "c)
Dim query = mainlist.Where(Function(et) et.Tags.Any(Function(tag) searchTags.Contains(tag))).ToList
For Each et In query
Listbox1.Items.Add(et)
Next