How do you calculate a result from a listbox selection in Visual Basic? (The data in the listbox is being read off a text file) - vb.net

So I am asked in school to create a Railway Ticketing System program that will allow you to buy either a single or return ticket and based off that the cost will be displayed. The information of all destinations is to be read via a text file. The text file is given below:
Knapford , 1
Crosby , 8
Weltworth , 15
Maron , 23
Cronk , 28
Kildane , 31
Keltthorpe Road , 46
Crovan's Gate , 56
Vicarstown , 76
Barrow , 77
I have managed to separate the integers from the destination names via the code below which then is displayed in a listbox:
Public Class PurchaseScreen
Dim Filename As String
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Filename = "StationFile.txt"
Dim sr As New StreamReader("StationFile.txt")
Dim Word As String = ""
Dim Words(11) As String
Dim i As Integer = 0
Do Until sr.Peek = -1
'grab one word at a time from the text file
Word = sr.ReadLine()
'place word into array
Words(i) = Word
'increment array counter
i = i + 1
Loop
Return
End Sub
The problem I am facing is that I am trying to access the numbers that were omitted by the code, since only the destination name can be displayed in the listbox. How do I go about using those numbers to perform my calculations?

I've edited your post so that the format of the text file is clearer to users reading your question
So to make it easier to access your data, you would be better having a Station structure and storing each station in list of these structures.
To populate your list, iterate through the list of stations and add the names to the list.
When an item is selected, use the selected item's index to look up the data in the stations list and there you go.
'obviously you need to change this path to match where your "stations.txt"file is stored
'and also possibly the name of the listbox you're populating
Dim Filename As String = "D:\Visual Studio 2015\Projects\blank\blank\stations.text"
Dim selectedStation As Station
'a structure of station that can be used to store the data in the stations.txt file
'in a clearer more maintainable way
Structure Station
Dim Name As String
Dim Data As Single
End Structure
'list to store the data from stations.txt
Dim stations As New List(Of Station)
'your form's load event
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
stations.Clear()
ReadStationData()
PopulateListBox()
End Sub
Private Sub ReadStationData()
Dim tempDataLine As String = ""
'read all the stations.txt data into a string
Using sr As New StreamReader(Filename)
While Not sr.EndOfStream
tempDataLine = sr.ReadLine
Dim newStation As Station
Dim tempSplit() As String = tempDataLine.Split(New String() {" , "}, StringSplitOptions.RemoveEmptyEntries)
newStation.Name = tempSplit(0)
newStation.Data = CSng(tempSplit(1))
stations.Add(newStation)
End While
End Using
End Sub
'clear the ListBox and populate it from the Stations list
Private Sub PopulateListBox()
ListBox1.Items.Clear()
For Each stationItem As Station In stations
ListBox1.Items.Add(stationItem.Name)
Next
End Sub
Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedIndexChanged
'dummy code to show usage
selectedStation = stations(ListBox1.SelectedIndex())
MessageBox.Show("Selected station = " & selectedStation.Name & vbCrLf & "Station price = " & selectedStation.Data)
End Sub

Related

Importing data from text file in VB.NET

So, I am trying to develop a book database. I have created a table with 11 columns which populates a DGV, where only 6 columns are showed. The full data of each book is shown in a lower part of the form, where I have textboxes, which are bounded (BindingSource) to the table, that change as I move in the DGV.
Now, what I want to do is to have the posibility to export/import data from a file.
I have accomplished the exporting part with the following code:
Private Sub BtnExport_Click(sender As Object, e As EventArgs) Handles BtnExport.Click
Dim txt As String = String.Empty
For Each row As DataGridViewRow In DbdocsDataGridView.Rows
For Each cell As DataGridViewCell In row.Cells
'Add the Data rows.
txt += CStr(cell.Value & ","c)
Next
'Add new line.
txt += vbCr & vbLf
Next
Dim folderPath As String = "C:\CSV\"
File.WriteAllText(folderPath & "DataGridViewExport.txt", txt)
End Sub
However, I can't manage to import from the txt. What I've tried is this: https://1bestcsharp.blogspot.com/2018/04/vb.net-import-txt-file-text-to-datagridview.html
It works perfectly if you code the table and it populates de DGV without problem. I can't see how should I adapt that code to my need.
Private Sub BtnImport_Click(sender As Object, e As EventArgs) Handles BtnImport.Click
DbdocsDataGridView.DataSource = table
Dim filas() As String
Dim valores() As String
filas = File.ReadAllLines("C:\CSV\DataGridViewExport.txt")
For i As Integer = 0 To filas.Length - 1 Step +1
valores = filas(i).ToString().Split(",")
Dim row(valores.Length - 1) As String
For j As Integer = 0 To valores.Length - 1 Step +1
row(j) = valores(j).Trim()
Next j
table.Rows.Add(row)
Next i
End Sub
That is what I've tried so far, but I always have an exception arising.
Thanks in advance to anyone who can give me an insight about this.
The DataTable class has built-in methods to load/save data from/to XML called ReadXml and WriteXml. Take a look at example which uses the overload to preserve the schema:
Private ReadOnly dataGridViewExportPath As String = IO.Path.Combine("C:\", "CSV", "DataGridViewExport.txt")
Private Sub BtnExport_Click(sender As Object, e As EventArgs) Handles BtnExport.Click
table.WriteXml(path, XmlWriteMode.WriteSchema)
End Sub
Private Sub BtnImport_Click(sender As Object, e As EventArgs) Handles BtnImport.Click
table.ReadXml(path)
End Sub
While users can manually edit the XML file that is generated from WriteXML, I would certainly not suggest it.
This is code which writes to a text file:
speichern means to save.
Note that I use a # in my example for formatting reasons. When reading in again, you can find the # and then you know that and that line is coming...
And I used Private ReadOnly Deu As New System.Globalization.CultureInfo("de-DE") to format the Date into German format, but you can decide yourself if you want that. 🙂
Note that I'm using a FileDialog that I downloaded from Visual Studio's own NuGet package manager.
Private Sub Button_speichern_Click(sender As Object, e As EventArgs) Handles Button_speichern.Click
speichern()
End Sub
Private Sub speichern()
'-------------------------------------------------------------------------------------------------------------
' User can choose where to save the text file and the program will save it .
'-------------------------------------------------------------------------------------------------------------
Dim Path As String
Using SFD1 As New CommonSaveFileDialog
SFD1.Title = "store data in a text file"
SFD1.Filters.Add(New CommonFileDialogFilter("Textdatei", ".txt"))
SFD1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
If SFD1.ShowDialog() = CommonFileDialogResult.Ok Then
Path = SFD1.FileName & ".txt"
Else
Return
End If
End Using
Using textfile As System.IO.StreamWriter = My.Computer.FileSystem.OpenTextFileWriter(Path, True, System.Text.Encoding.UTF8)
textfile.WriteLine("Timestamp of this file [dd.mm.yyyy hh:mm:ss]: " & Date.Now.ToString("G", Deu) & NewLine & NewLine) 'supposed to be line break + 2 blank lines :-)
textfile.WriteLine("your text")
textfile.WriteLine("#") 'Marker
textfile.Close()
End Using
End Sub
Private Sub FormMain_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
speichern()
End Sub
And this is to read from a text file:
'read all Text
Dim RAT() As String = System.IO.File.ReadAllLines(Pfad, System.Text.Encoding.UTF8)
If RAT.Length = 0 Then Return Nothing
For i As Integer = 0 To RAT.Length - 1 Step 1
If RAT(i) = "#" OrElse RAT(i) = "" Then Continue For
'do your work here with (RAT(i))
Next

Select random person from text file and change corresponding values

I have a form with a button and a label. I also have a text file with the following contents:
Bob:Available:None:0
Jack:Available:None:0
Harry:Available:None:0
Becky:Unavailable:Injured:8
Michael:Available:None:0
Steve:Available:None:0
Annie:Unavailable:Injured:12
Riley:Available:None:0
The values in the text file are:
person-name:available-or-unavailable:sick-or-injured:months-they-will-be-unavailable
What I would like to do is to have the user click the button and a random (available) person will be selected from the text file. The label's text will then say:
personname & " has gotten injured and will be unavailable for 10 months."
I would then like to overwrite the text file with the corresponding values for that particular person. For example that person's second value will now be "Unavailable", the third value will be "Injured" and the fourth value will be 10.
I hope this makes sense.
I don't have any code, as I literally have no idea how to do this. Any help would be much appreciated!
Explanations and code in line.
Private r As New Random
Private RandomIndex As Integer
Private dt As New DataTable
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
AddColumnsToDataTable()
FillDataTable()
End Sub
Private Sub AddColumnsToDataTable()
'Need to prepare the table to receive the data
dt.Columns.Add("Name")
dt.Columns.Add("Available")
dt.Columns.Add("Injury")
dt.Columns.Add("Months")
End Sub
Private Sub FillDataTable()
'ReadAllLines returns an array of lines in the text file
Dim lines = File.ReadAllLines("workers.txt")
'Loop through each line in the lines array
For Each line As String In lines
'.Split returns an array based on splitting the line
'by the colon. The c following ":" tells the compiler
'that this is a Char which the split function requires.
Dim items = line.Split(":"c)
'We can add a row to the data table all at once by
'passing in an array of objects.
'This consists of the elements of the items array
dt.Rows.Add(New Object() {items(0), items(1), items(2), items(3)})
Next
'Now we have an in memory DataTable that contains all the data from the text file.
End Sub
Private Function GetRandomWorker() As String
'A list of all the row indexes that are available
Dim AvailableList As New List(Of Integer)
For i As Integer = 0 To dt.Rows.Count - 1
'Loop through all the data in the date table row by row
If dt.Rows(i)("Available").ToString = "Available" Then
'Add only the row indexes that are Available
AvailableList.Add(i)
End If
Next
'Get a random index to use on the list of row indexes in IndexList
If AvailableList.Count = 0 Then
'No more workers left that are Available
Return ""
End If
'Get a random number to use as an index for the available list
Dim IndexForList = r.Next(AvailableList.Count)
'Selects a row index based on the random index in the list of Available
RandomIndex = AvailableList(IndexForList)
'Now use the index to get information from the row in the data table
Dim strName = dt.Rows(RandomIndex)("Name").ToString
Return strName
End Function
Private Sub SaveDataTable()
'Resave the whole file if this was a real app you would use a database
Dim sb As New StringBuilder
'A string builder keeps the code from creating lots of new strings
'Strings are immutable (can't be changed) so every time you think you are
'changing a string, you are actually creating a new one.
'The string builder is mutable (changable)
For Each row As DataRow In dt.Rows
'The ItemsArray returns an array of objects containing all the
'values in each column of the data table.
Dim rowValues = row.ItemArray
'This is a bit of Linq magic that turns the values into strings
Dim strRowValues = From s In rowValues
Select DirectCast(s, String)
'Now that we have strings we can use the String.Join with the colon
'to get the format of the text file
sb.AppendLine(String.Join(":", strRowValues))
Next
'Finally we change the StringBuilder to a real String
'The workers.txt is stored in the Bin\Debug directory so it is current directory
'no additional path required
File.WriteAllText("workers.txt", sb.ToString)
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
SaveDataTable()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim WorkerName As String = GetRandomWorker()
If WorkerName = "" Then
MessageBox.Show("There are no available workers")
Return
End If
Label1.Text = $"{WorkerName} has gotten injured and will be unavailable for 10 months."
dt.Rows(RandomIndex)("Available") = "Unavailable"
dt.Rows(RandomIndex)("Injury") = "Injured"
dt.Rows(RandomIndex)("Months") = "10"
End Sub

Select random element from array and display in textbox

I have a form with a button and a textbox. I also have a text file with the following contents..
Bob:Available:None:0
Jack:Available:None:0
Harry:Available:None:0
Becky:Unavailable:Injured:8
Michael:Available:None:0
Steve:Available:None:0
Annie:Unavailable:Injured:8
Riley:Available:None:0
When the user loads the form each value of the text file gets stored into an array. This works fine. What i would like to happen is when the button is pressed a random person (name) who has the value 'Available' will be retrieved from the array and displayed in the textbox.
The code i have so far (which stores each item in text file into arrays):
Public Class Form1
'define profile of person
Public Structure PersonInfo
Public name As String
Public status As String
Public status_type As String
Public monthsunavailable As Integer
End Structure
'Profile List of persons
Public Shared personInfos As New List(Of PersonInfo)() 'roster data
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'read all infomations of person from file. lines is profile array
Dim lines() As String = IO.File.ReadAllLines(filelocation)
For Each line In lines
'Parses the line string, make Person Info and add it to Person List
'split string with ":"
If line.Trim.Equals("") Then Continue For
Dim strArr() = line.Split(":")
'make Person Info
Dim pi As New PersonInfo()
pi.name = strArr(0)
pi.status = strArr(1)
pi.status_type = strArr(2)
pi.monthsunavailable = strArr(3)
'add Person Info to Person List
personInfos.Add(pi)
Next
How do i select a random name from the array and display it in a textbox?
You can use something like this. Try reading the docs!
Private Sub Button1_click (sender As Object, e As EventArgs) Handles Button1.Click
Dim r As New Random ()
Textbox1.Text = personinfos(r.Next (0,personinfos.count)).name
End Sub
Update
To select only names with status "Available"
Private Sub Button1_click (sender As Object, e As EventArgs) Handles Button1.Click
'Instantiate a new random variable
Dim r As New Random ()
'This is a LINQ query to select all items from the list where a property of the item
'(in this case , status) is equal to something.
'Try changing Available to something else and see what you get
Dim qr = From pi in personinfos
Where pi.status = "Available"
Select pi
'The following line can be simplified as follows
'Dim i As Integer = r.Next (0,qr.count)
'Dim s As String = qr (i).name
'Textbox1.Text = s
Textbox1.Text = qr(r.Next (0,qr.count)).name
End Sub

How to auto fill a textbox from a comobobox using a textfile

I 'm currently creating a form in VB that uses a text file to gather information for a combo box then automatic use the next word in the text file that's comma delimited to automatically populate a textbox.
But the current code I wrote show the list for the combo box but always auto fills the textbox with the second word on the second line and will not change the textbox after i select another option from the combo box can someone help?
Sorry if this isn't very clear.
My Text file is in this format:
Robert,5 BellView Road
Martin,6 BellView Road
Ect....
My code is as follows:
Dim LineString As String
Dim FieldString As String()
Try
Dim ContactInfoStreamReader As StreamReader = New StreamReader("C:\temp\test1.txt")
Do Until ContactInfoStreamReader.Peek = -1
LineString = ContactInfoStreamReader.ReadLine()
FieldString = LineString.Split(CChar(","))
LineString = FieldString(0)
ComboBox1.Items.Add(LineString)
Loop
RichTextBox2.Text = FieldString(1)
ContactInfoStreamReader.Close()
Catch ex As Exception
MsgBox("""Customers Name & Address.txt"" file was not found")
End Try
Ok, I know you have provided code, however this is how I would do it.
First of all we make a Person Class and create a Person List to store each Person
After that we read / load the text file into a string array and then we use Linq to split the text files line where the comma is and have it sort the name and address into two keys one being NAME and the other being ADDRESS. Once that is done we loop through each of the items and create a new Person with the values value.NAME and Value.Address for the persons name and address as well as add the person's name into a comboboxand finally we add a ComboBox Event that changes the Textbox's text to the selected ComboBox's Index that matches the List of People that was created to store each Person
Public Class Form1
Dim People As New List(Of Person)
Private Sub ComboBox1_SelectedValueChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedValueChanged
Try
TextBox1.Text = People(ComboBox1.SelectedIndex).address
Catch
''this will prevent errors if there is a name with no address
TextBox1.Text = ""
End Try
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
''This is the location I used, feel free to change it here.
Dim location As String = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
Dim fileName As String = "test1.txt"
Dim path As String = System.IO.Path.Combine(location, fileName)
Dim query = From line In System.IO.File.ReadAllLines(path)
Let val = line.Split(",")
Select New With {Key .NAME = val(0), Key .ADDRESS = val(1)}
For Each value In query
Dim p = New Person(value.NAME, value.ADDRESS)
People.Add(p)
ComboBox1.Items.Add(value.NAME)
Next
''ADD OTHER COMBOBOX ITEMS HERE IF NEED BE, SO EVERYTHING IS IN ORDER
ComboBox1.Items.Add("ANDREW")
End Sub
End Class
Class Person
Public Property name() As String
Public Property address() As String
Public Sub New(name As String, address As String)
Me.name = name
Me.address = address
End Sub
End Class
EDIT:This is how I formatted the text file.Robert,5 BellView Road
Martin,6 BellView Road

Reading from text file & displaying on form load

I have 2 text files named sQue.txt containing single words in each lines (each word in each line) and sObj.txt also containing single word in each line (but no. of entries are more in this file than in sQue.txt).
Now, I have a blank form in which I want to read both the above files & display them in a manner such that:
Each entry from sQue.txt file gets displayed in separate labels in the form
All the entries of file sObj.txt are put in a CheckedListBox & this CheckedListBox appears for each label displayed in point 1. above.
Example:
sObj.txt contains 3 entries aaa, bbb & ccc (vertically i.e each in new line).
sQue.txt contains 5 entries p,q,r,s & t (vertically i.e each in new line).
Now, when the form loads, 3 labels are seen with texts aaa, bbb & ccc. Also 3 CheckedListBoxes are seen containg p,q,r,s & t in each box.
Can it be done? I'm trying to find a solution with no luck yet.
Please help.
Till now all I have is
Private Sub Form7_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim queue As String() = IO.File.ReadAllLines("C:\temp\sQue.txt")
Dim objects As String() = IO.File.ReadAllLines("C:\temp\sObj.txt")
For i = 0 To queue.Count - 1
'create labels here
For j=0 to objects.Count - 1
'create CheckedListBoxes
Next
Next
End Sub
If you use a groupbox you can use the text property as your label, and add a checkedlistbox to the groupbox with the items you want. This code will do that:
Imports System.IO
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim NewForm2 As New Form2
NewForm2.Show()
Dim sObj() As String = File.ReadAllLines("sobj.txt")
Dim sQue() As String = File.ReadAllLines("sQue.txt")
For Each s As String In sObj
Me.Controls.Add(MakeNewGB(s, sQue))
Next
End Sub
End Class
Public Module Module1
Friend WithEvents NewGB As System.Windows.Forms.GroupBox
Friend WithEvents NewCLB As System.Windows.Forms.CheckedListBox
Public NextColumn As Integer = 0
Public Function MakeNewGB(lbl As String, clbItems() As String) As GroupBox
NewGB = New System.Windows.Forms.GroupBox()
NewCLB = New System.Windows.Forms.CheckedListBox()
NewGB.SuspendLayout()
'GroupBox1
'
NewGB.Controls.Add(NewCLB)
NewGB.Location = New System.Drawing.Point(NextColumn, 0)
NewGB.Name = lbl
NewGB.Size = New System.Drawing.Size(126, 210)
NewGB.TabIndex = 0
NewGB.TabStop = False
NewGB.Text = lbl
'
'CheckedListBox1
'
NewCLB.FormattingEnabled = True
NewCLB.Location = New System.Drawing.Point(6, 19)
NewCLB.Name = "clb" + lbl
NewCLB.Size = New System.Drawing.Size(103, 184)
NewCLB.TabIndex = 0
NewCLB.Items.AddRange(clbItems)
NextColumn += NewGB.Size.Width + 10
Return NewGB
End Function
End Module
I think your code should look like this. But i am not sure what the purpose of it is.
Private Sub Form7_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim queue As String() = IO.File.ReadAllLines("C:\temp\sQue.txt")
Dim objects As String() = IO.File.ReadAllLines("C:\temp\sObj.txt")
For i = 0 To queue.Count - 1
'create labels here
Dim label as new Label
label.Text = queue(i)
Dim chklst as new CheckedListBox
For j=0 to objects.Count - 1
'create CheckedListBoxes
chklst.Items.Add(object(j))
Next
Me.Controls.Add(label)
Me.Controls.Add(chklst)
Next
End Sub