Search code examples
vb.nettext-filesfile-manipulation

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!


Solution

  • 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