Copy values of cells from a DataGridView column to an ArrayList - vb.net

I am using a DataGridView with an ArrayList. When a user clicks a button, I want the values of the first column (there will be 4 columns total, each having its own ArrayList) of the DataGridView to be written to an ArrayList. I am using an ArrayList because the number of rows in the Datagridview can vary, so the array size cannot be static. The code that I have written, actually searched and got help online with is "almost" working. It will write the values of the first column to the arraylist, but I have to click on the button twice. It will only update the ArrayList on the second click of my button. What needs to change with my code? Thanks from a newbie!
Private Sub btnPrintArray_Click(sender As Object, e As EventArgs) Handles btnPrintArray.Click
Dim message = String.Join(Environment.NewLine, lftMtrAccelRates.ToArray())
lftMtrAccelRates.Clear() 'clears ArrayList
rchTxtBox.Clear() 'Clears rich text box that has array element values in it
For Each d In LftMtr_Data_Grid.Rows.Cast(Of DataGridViewRow)()
Dim num As Integer
If Int32.TryParse(d.Cells(0).Value, num) Then
lftMtrAccelRates.Add(num)
End If
Next
rchTxtBox.Text = message
End Sub`

One possibility:
Private values As New List(Of Integer)
Private Sub btnPrintArray_Click(sender As Object, e As EventArgs) Handles btnPrintArray.Click
values.Clear()
Dim num As Integer
For Each d As DataGridViewRow In LftMtr_Data_Grid.Rows
If Int32.TryParse(d.Cells(0).Value, num) Then
values.Add(num)
End If
Next
rchTxtBox.Lines = values.ConvertAll(Function(x) x.ToString).ToArray
End Sub

Related

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

How to pass the 2nd selected row in datagridview to textbox?

How do i pass my 2nd selected row in datagridview to textboxt. I only know how to put the first data. How do i pass the 2nd selected to textbox?
Dim i As Integer
i = DataGridView2.SelectedRows(0).Index
Me.txtEmployeeID.Text = DataGridView2.Item(0, i).Value
you can use this code it worked for me
Dim test As String = DataGridView1.SelectedRows(0).Cells(2).Value.ToString
You need to only change the .cell(Here write the index value of the cell)
Then you can use the string value to fill up textbox
Try using the following:
Dim secondRow as integer = 0
Private Sub DataGridView2_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView2.CellClick
'assuming that by second selected row, you mean the row after the selected row
secondRow = e.RowIndex + 1
End Sub
Private Sub RowToTextBox()
Try
For i = 0 to DataGridView2.ColumnCount - 1
txtEmployeeID.Text &= DataGridView2.Item(i, secondRow)
Next
Catch ex as Exception
MsgBox("You have selected the final row")
End Try
End Sub
I don't think Me. is needed when referring to a textbox in the same form.
Since you don't know how many rows your user will select, I think looping thought the SelectedRows collection might work. I used the Name column because that is what I happened to have in my grid. Instead of a MessageBox you could add the values to a ListBox.
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
For Each GridRow As DataGridViewRow In DataGridView1.SelectedRows
MessageBox.Show($"Value is {GridRow.Cells("Name").Value}")
Next
End Sub

Compare the values of two listboxes and add the non-equivalent values to a third listbox

My knowledge of programming is not too extensive but I have just finished my second year of higher education in computer engineering and have taken a few low level programming courses.
In Visual Basic, I am having trouble comparing the values of two ListBox controls and putting the values that aren't the same into another ListBox.
I need to compare the items of ListBox2 to the items of ListBox1 and if there are any items in ListBox2 that are not in ListBox1, add them to ListBox3. I do not need to find the items in ListBox1 that are not in ListBox2. I cannot use a loop to compare their values based on index because these lists are of names which will be constantly added to and removed from. I also cannot sort these ListBoxes.
There was an example for C# that I found here that used LINQ (I don't really know what that is) to compare the lists and then add the result to a TextBox control. However, I need to know how to add them to a ListBox and not a TextBox.
[EDIT] The example that I have tried is this:
Dim result As List(Of String) = (From s1 As String In Me.ListBox1.Items Where Not Me.ListBox2.Items.Contains(s1) Select s1).ToList()
Me.TextBox1.Text = String.Join(Environment.NewLine, result)
Dim one As ListBox = New ListBox()
Dim two As ListBox = New ListBox()
Dim three As ListBox = New ListBox()
Dim unique As Boolean = True
For i As Integer = 0 To one.Items.Count
For j As Integer = 0 To two.Items.Count
If (one.Text = two.Text) Then
unique = False
Else
two.SelectedIndex = j
End If
Next
If (unique) Then
three.Items.Add(one.Text)
Else
one.SelectedIndex = i
unique = True
End If
Next
I believe this may be what you're looking for. What it does is compares each value in Listbox one to all values in Listbox two and if a value is seen to be a duplicate the Boolean flag unique is switched to false and the item is not added to Listbox three.
I think i found the solution:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ListBox3.Items.Clear()
Dim result As List(Of String) = (From s1 As String In Me.ListBox2.Items Where Not Me.ListBox1.Items.Contains(s1) Select s1).ToList()
For Each l In result
ListBox3.Items.Add(l)
Next
End Sub
or
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim result As List(Of String) = (From s1 As String In Me.ListBox2.Items Where Not Me.ListBox1.Items.Contains(s1) Select s1).ToList()
For Each l In result
If Not ListBox3.Items.Contains(l) Then
ListBox3.Items.Add(l)
End If
Next
End Sub
Try which works best for you :)

Reading txt file line by line in DataGrid View

I'm completely new to VB.net and have been given a homework assignment. I need to be able to read certain lines and display them in a DataGridView. I have been able to link my .txt file to the DGV however it reads the whole file as opposed to the specific line. I have 4 buttons: btn1, btn2, btn3, btn4. I want each button to show the respective lines in the text file. After researching on-line for the past week I'm still stuck. If anyone could help me I would really appreciate it.
Text File ("database.txt")
(Line1) c1 c2 c3
(Line2) one 1-1 1-2
(Line3) two 2-2 2-3
(Line4) three 3-2 3-3
(Line5) four 4-2 4-3
Public Class Form1
Private Sub btn1_Click(sender As Object, e As EventArgs) Handles btn1.Click
Dim lines = (From line In IO.File.ReadAllLines("database.txt") _
Select line.Split(CChar(vbTab))).ToArray
For x As Integer = 0 To lines(0).GetUpperBound(0)
DataGridView1.Columns.Add(lines(0)(x), lines(0)(x))
Next
For x As Integer = 1 To lines.GetUpperBound(0)
DataGridView1.Rows.Add(lines(x))
Next
End Sub
End Class
You did not describe the result you get, so I cannot tell what's wrong right now, as I am not on a computer and usually use c++/cli (visual c++). If I have to make a guess, I would say that you fill each file row into one DGV row, but you want just 1 row, not all. Correct?
Anyway, here are some suggestions:
Do you have to read the file on each button click? If not, I would read it once, store the content and fill into the DGV when desired.
Debug your code! Set a breakpoint at the start of the function, step over the code lines, check the variable content.
Split up the code line dim lines into 3 or more separate lines to make it more readable. Also helps at debugging.
I made following assumptions based on what you had in your question:
First line of the file was the column names
The (Line#) was just there for reference and isn't in the actual file
The number in the button name (btn#) was the row index that should be displayed in the DGV
I added a new button to the form that loads the data from the text file, parses it to a datatable and sets the DataGridView1.DataSource to that DataTable. The second method then creates a new datatable and imports the specified row from the main datatable and shows it in the DGV. Of course many will say you should use a DataView with a DataView.RowFilter for this rather than creating a new datatable, however this way works just the same.
Private txtDataTable As DataTable
Private Sub loadFileBtn_Click(sender As Object, e As EventArgs) Handles loadFileBtn.Click
txtDataTable = New DataTable("txtContents")
Dim txtContents As String()
Try
txtContents = IO.File.ReadAllLines("C:\StackOverflow\database.txt")
Catch ex As Exception
MsgBox(ex.Message)
Return
End Try
Dim txtLines As New List(Of String())
txtContents.ToList().ForEach(Sub(x) txtLines.Add(x.Split(CChar(vbTab))))
If txtLines.Count > 0 Then
txtLines.Item(0).ToList.ForEach(Sub(x) txtDataTable.Columns.Add(New DataColumn(x.ToString)))
txtLines.RemoveAt(0)
End If
If txtLines.Count > 0 Then
txtLines.ToList.ForEach(Sub(x) txtDataTable.Rows.Add(x.ToArray))
End If
DataGridView1.DataSource = txtDataTable
End Sub
Private Sub btn_Click(sender As Object, e As EventArgs) Handles btn1.Click, btn2.Click, btn3.Click, btn4.Click
If txtDataTable Is Nothing Then Return
Dim rowIndex As Integer
If Integer.TryParse(DirectCast(sender, Button).Name.Replace("btn", String.Empty), rowIndex) Then
rowIndex -= 1
Else
Return
End If
Dim TempTable As DataTable = txtDataTable.Clone
If rowIndex < txtDataTable.Rows.Count Then
TempTable.ImportRow(txtDataTable.Rows(rowIndex))
End If
DataGridView1.DataSource = TempTable
End Sub

multidimension Arrays and Listboxes (VB.Net)

I'm new to VB.Net and feel a bit confused about something.
I want to have two list boxes, in each ones I already have items. In my first list box I have 4 items, in my second List box I have 5 items. I have also added a text box, for the value I want to be stored in the array.
For example: if I select the first value of the first text box, and the second value of the second text box and type "5" in the text box, 5 will be stored in (0,1) of the array.
I then want all the values for each item of my first list box to be displayed in a label, same for the second items, third item, and fourth item. I suppose I would need a loop for this.
I know how to create an array, and how to store values in an array, but I can't seem to figure out how to get it to work using list boxes and a text box.
I've created a form with the following controls:
ComboBox1
ComboBox2
Button1
TextBox1
I've added code to the Form_Load and Button1_Click events and created a single ComboBox_SelectedIndexChanged event handler to deal with both combo boxes index changes.
Public Class Form1
Private _array(,) As String
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ReDim _array(0 To ComboBox1.Items.Count, 0 To ComboBox2.Items.Count)
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim c1 As Integer = If(ComboBox1.SelectedIndex = -1, 0, ComboBox1.SelectedIndex)
Dim c2 As Integer = If(ComboBox2.SelectedIndex = -1, 0, ComboBox2.SelectedIndex)
Debug.Print(String.Format("Set ({0},{1}) to {2}", c1, c2, TextBox1.Text))
_array(c1, c2) = TextBox1.Text
End Sub
Private Sub ComboBox_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged, ComboBox2.SelectedIndexChanged
Dim c1 As Integer = If(ComboBox1.SelectedIndex = -1, 0, ComboBox1.SelectedIndex)
Dim c2 As Integer = If(ComboBox2.SelectedIndex = -1, 0, ComboBox2.SelectedIndex)
Debug.Print(String.Format("Get ({0},{1}) to {2}", c1, c2, TextBox1.Text))
TextBox1.Text = _array(c1, c2)
End Sub
End Class
What I'm demonstrating is that:
1. the array is resized when the form is loaded to match the number of elements in your comboboxes.
2. the data is loaded into the array on an event (in this case the button click event).
3. Retrieving the data again as either of the combo boxes changes.
Hope that helps.