Storing Objects into a Class & Retrieving upon Request - vb.net

I seriously need help with my project.
I am trying to store specific jobs into a Class, which then displays in a List Box.
When selecting the List Box, I want the rest of the information to be displayed into a Text Box.
I can add Jobs into the List Box, and the Report button sorts the Job by Earliest to Latest.
I just CANNOT seem to code the Display Button to retrieve the rest of the information.
http://i.stack.imgur.com/0eV5j.png
What am I doing wrong?
My Code:
Public Class Form1
Dim jobList As List(Of UserInformation) = New List(Of UserInformation)
Dim j As UserInformation = New UserInformation()
Private Sub btnReport_Click(sender As Object, e As EventArgs) Handles btnReport.Click
Dim p As UserInformation = New UserInformation()
Dim qty As Integer = jobList.Count - 1
Dim name(qty) As String
Dim deadline(qty) As Date
Dim i As Integer = 0
'fill the array
For i = 0 To qty
p = jobList(i)
name(i) = p.Name
deadline(i) = p.Deadline
Next
'sort the array
Dim done As Boolean = False
While done = False
done = True
For i = 0 To qty - 1
Dim tempName As String
Dim tempDate As Date
If deadline(i) > deadline(i + 1) Then
tempName = name(i)
tempDate = deadline(i)
name(i) = name(i + 1)
deadline(i) = deadline(i + 1)
name(i + 1) = tempName
deadline(i + 1) = tempDate
done = False
End If
Next
End While
lsbReport.Items.Clear()
lblListbox.Text = "List in date order"
For i = 0 To name.Length - 1
Dim str As String
str = name(i) + ", "
str += deadline(i).ToString + "."
lsbReport.Items.Add(str)
Next
End Sub
Private Sub updateListBox()
lsbReport.Items.Clear()
lblListbox.Text = "All people in the List"
For Each person As UserInformation In jobList
Dim str As String
str = person.Name + ", "
str += person.Deadline.ToString + "."
lsbReport.Items.Add(str)
Next
End Sub
Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
Dim p As UserInformation = New UserInformation()
p.Name = firstNameText.Text
p.Deadline = lastNameText.Value
jobList.Add(p)
updateListBox()
End Sub
Private Sub btnDisplay_Click(sender As Object, e As EventArgs) Handles btnDisplay.Click
Dim job_info As UserInformation = CType(lsbReport.SelectedItem(), UserInformation)
txtReport.Text = "Job Title: " & job_info.Name() & Environment.NewLine
txtReport.Text &="Job DeadLine: " & job_info.Deadline & Environment.NewLine
txtReport.Text &="Job Description" & job_info.Description
End Sub
End Class
Public Class UserInformation
Public job_deadline As Date
Public job_name As String
Public job_description As String
Public Property Name() As String
Get
Return job_name
End Get
Set(ByVal value As String)
job_name = value
End Set
End Property
Public Property Deadline() As String
Get
Return job_deadline
End Get
Set(ByVal value As String)
job_deadline = value
End Set
End Property
Public Property Description() As String
Get
Return job_description
End Get
Set(ByVal value As String)
job_description = value
End Set
End Property
End Class

The bottom line is that you stored string values to the LBs:
str = person.Name & ", " & person.Deadline.ToString
lsbReport.Items.Add(str)
So, that is what you get back making it difficult to connect the string created with the object it represents.
Listboxes and comboboxes can store objects as well as strings. Simple Demo:
Public Class Employee
Public Property ID As Integer ' a db ID maybe
Public Property Name As String
Public Property Department As String
Public Property HireDate As Date
Public Overrides Function ToString As String
Return Name ' text to show in controls
' in a more realistic class it might be:
' Return String.Format("{0}, {1} ({2})", LastName,
' FirstName, BadgeNumber)
' e.g. "Whitman, Ziggy (123450)"
End Function
End Class
Friend EmpList As New List(of Employee) ' if needed
storing an object to a listbox is simple:
Dim newEmp As Employee
newEmp.Name = "Ziggy"
' set props as needed
myLB.Items.Add(newEmp) ' add to a ListBox directly.
Once you have a class for these things, you have many options. You can store them to a List(Of T) which can be used with a List or ComboBox:
Private EmpList As New List(Of Employee)
...
EmpList.Add(newEmp) ' adding to a list is same as a ListBox
' add from List to a control:
myLB.Items.AddRange(Emps.ToArray)
myLB.SelectedItem will now be an Employee object, which should make displaying details elsewhere simple.
To make it even more efficent, you can use the list as a DataSource so you dont have to add references to the listbox:
myLB.DataSource = EmpList
myLB.DisplayMember = "Name" ' the property to display
myLB.ValueMember = "Id" ' what to use for SelectedValue

Related

How to create a Loop to push Values to different TextBox with Similar Labels names and Change their text?

I am new to this VB. I'm building an application where I need to fill some 48 text boxes with 4 sets of similar names like
L1onHHxx
L1onMMxx
L1offHHxx
L1offMMxx
Where xx is a number from 1 to 24 for each label.
What I'm trying to do is calculate some values based on the user input and fill the text boxes with results.
Private Async Sub Line1Calc_Click(sender As Object, e As EventArgs) Handles Line1Calc.Click
Dim Cycle_Time As Integer
Dim Cycle_Count As Integer
Dim srtHH As Integer
Dim srtMM As Integer
Dim stpHH As Integer
Dim stpMM As Integer
Dim inDelay As Integer
Dim i As Integer
Dim lineONHH As New Label
Dim lineONMM As New Label
Dim lineOFFHH As New Label
Dim lineOFFMM As New Label
'Dim controls = GetAllTextBoxes(Me)
'Line1Tab
Cycle_Time = CInt(L1Time.Text)
Cycle_Count = CInt(L1Count.Text)
srtHH = CInt(L1ONHH.Text)
srtMM = CInt(L1ONMM.Text)
stpHH = CInt(L1OFFHH.Text)
stpMM = CInt(L1OFFMM.Text)
inDelay = (24 / CInt(Cycle_Count))
L1onhh1.Text = srtHH
L1onhh1.Text = srtHH
L1offhh1.Text = stpHH
L1offmm1.Text = stpMM
For i = 2 To (Cycle_Count)
srtHH += inDelay
stpHH += inDelay
lineONHH.Name = "L1onhh" & i.ToString()
lineONMM.Name = "L1onmm" & i.ToString()
lineOFFHH.Name = "L1offhh" & i.ToString()
lineOFFMM.Name = "L1offmm" & i.ToString()
lineONHH.Text = srtHH
lineONMM.Text = srtMM
lineOFFHH.Text = stpHH
lineOFFMM.Text = stpMM
' To Check if the labels name are correct
Box1.Text = lineONHH.Name
Box2.Text = lineONMM.Name
Box3.Text = lineOFFHH.Name
Box4.Text = lineOFFMM.Name
Await Task.Delay(1000)
Next
End Sub
Here when I pass the value of the New label to Box 1,2,3 & 4 for test purposes they are correct but the values don't appear on the respective text boxes.
Please can anyone point me in the right direction of what I'm doing wrong?
This should get you close, with a few assumptions made.
It assumes you have constant textbox naming pattern.
Assumes you want hour and minute in string.
Switch that structure to a DateTime if you want it in that format.
'class to hold all your time value entries
Private Class TimeValue
Public Property HourValue As String
Public Property MinValue As String
End Class
'class for each control time slow and its associated timevalues
Private Class ControlTime
Public Property TimeSlot As String
Public Property OnValue As TimeValue
Public Property OffValue As TimeValue
End Class
'method to set control values
Private Function SetControlValus(controlTimeItem As ControlTime) As Boolean
'find the control
Dim OnHourTextBox As TextBox = DirectCast(Me.Controls.Find(String.Concat("L1onHH", controlTimeItem.TimeSlot), False)(0), TextBox)
OnHourTextBox.Text = controlTimeItem.OnValue.HourValue
Dim OnMinTextBox As TextBox = DirectCast(Me.Controls.Find(String.Concat("L1onMM", controlTimeItem.TimeSlot), False)(0), TextBox)
OnMinTextBox.Text = controlTimeItem.OnValue.MinValue
Dim OffHourTextBox As TextBox = DirectCast(Me.Controls.Find(String.Concat("L1offHH", controlTimeItem.TimeSlot), False)(0), TextBox)
OffHourTextBox.Text = controlTimeItem.OffValue.HourValue
Dim OffMinTextBox As TextBox = DirectCast(Me.Controls.Find(String.Concat("L1offMM", controlTimeItem.TimeSlot), False)(0), TextBox)
OffMinTextBox.Text = controlTimeItem.OffValue.MinValue
Return True
End Function
Private Sub Test()
'set up some results
Dim results As List(Of ControlTime) = New List(Of ControlTime)
results.Add(New ControlTime() With {.TimeSlot = "01",
.OnValue = New TimeValue() With {.HourValue = "08", .MinValue = "56"},
.OffValue = New TimeValue() With {.HourValue = "08", .MinValue = "58"}})
results.Add(New ControlTime() With {.TimeSlot = "02",
.OnValue = New TimeValue() With {.HourValue = "09", .MinValue = "14"},
.OffValue = New TimeValue() With {.HourValue = "09", .MinValue = "29"}})
For Each controlTimeItem In results
SetControlValus(controlTimeItem)
Next
End Sub
Private Sub TestControlTimeButton_Click(sender As Object, e As EventArgs) Handles TestControlTimeButton.Click
Try
Test()
Catch ex As Exception
MessageBox.Show(String.Concat("An error occurred: ", ex.Message))
End Try
End Sub

calling a part of a structure into a button click

I'm relatively new to vb. I have made a structure and now I want to do a bubble sort on the values. I'm unsure on how to call all of the data in the single part of the structure which is also a list.
(module)
module module 1
structure studenttype
dim id as string
dim name as string
end structure
public studentdetails as new list(of studenttype)
(main code)
Private Function bubbleSortbyID(ByVal namelist() As String) As String()
Dim n As Integer = namelist.Length()
Dim swapped As Boolean
Do
swapped = False
For i As Integer = 1 To n - 2
If namelist(i) > namelist(i + 1) Then
Dim temp As String = namelist(i + 1)
namelist(i + 1) = namelist(i)
namelist(i) = temp
swapped = True
End If
Next
Loop Until swapped = False 'no swap made so order Is correct
Return namelist
End Function
Private Sub BtnSort_Click(sender As Object, e As EventArgs) Handles BtnSort.Click
Dim id As String ' it is here I do not how how to call the whole variable
bubbleSortbyID(id)' id remains empty
ClearAndAdd()
End Sub'''

How to change this code to find all matches

I need to perform a substring match on the ID. For example, search for all the IDs that begin with "AB" and return all matches. ID format is AB1234.
Dim CPosition, HashPostion As Integer
Dim StudentID, Fileline, IdPart As String
Dim SPostion As Char
Dim found As Boolean = False
FileOpen(1, "StudendRecord.txt", OpenMode.Input)
Console.Write("Enter ID to find the email: ")
StudentID = Console.ReadLine()
Do
CPosition = 1
Fileline = LineInput(1)
Do
SPostion = Mid(Fileline, CPosition, 1)
CPosition = CPosition + 1
Loop Until SPostion = "#"
HashPostion = Len(Fileline) - (CPosition - 1)
CPosition = 1
Do
SPostion = Mid(Fileline, CPosition, 1)
IdPart = IdPart + SPostion
If StudentID = IdPart Then
Console.WriteLine("the email: " & Right(Fileline, HashPostion))
found = True
End If
CPosition = CPosition + 1
Loop Until SPostion = "#"
Loop Until EOF(1)
If found = False Then
Console.WriteLine("ID not found.")
End If
FileClose(1)
To use this code add Imports System.IO to the top of the file. This namespace has a File class. File.ReadLines returns and array of the lines in a text file.
I created a simple class to hold the data in the file.
Then a list of the class's type.
I then split each line on the # character getting a 2 element array. The first element will contain the ID and the second element contains the email.
Create a new student and pass the data to the constructor. Then add the new student to the list.
To search the list I used Linq. Linq returns an IEnumerable(Of T) T in this case is StudentRecord.
To search the list I used Linq. I used .ToArray on the resulting IEnumerable because we only need the first element.
Public Class StudentRecord
Public Property ID As String
Public Property Email As String
Public Sub New(id As String, email As String)
Me.ID = id
Me.Email = email
End Sub
End Class
Module Module1
Private StudentRecords As New List(Of StudentRecord)
Public Sub Main()
Dim Records = File.ReadLines("StudentRecord.txt")
For Each line In Records
Dim SplitLine = line.Split("#"c)
Dim stu As New StudentRecord(SplitLine(0), SplitLine(1))
StudentRecords.Add(stu)
Next
Console.Write("Enter ID to find the email: ")
Dim StudentID = Console.ReadLine()
Dim students = From stu In StudentRecords
Where stu.ID.StartsWith(StudentID)
Select stu
If students.Count > 0 Then
For Each stu In students
Console.WriteLine($"Student {stu.ID} email is {stu.Email}")
Next
Else
Console.WriteLine("ID not found.")
End If
Console.ReadLine()
End Sub
End Module

Removing duplicates in Text Box and adding the corresponding values

I have a VB form with three TextBoxes. Here's an example of what I'd like the program to achieve:
So, that's the form ... the program sorts a text file and gets names, goals, and positions. E.g.
Jordan 26 Center
James 10 Mid
Jordan 4 Center
Jack 6 Forward
James 10 Mid
When the update button is clicked, the program should realize that James and Jordan are written twice, remove one of them and add their goals, so it should output:
Jordan 30 Center
James 20 Mid
Jack 6 Forward
To do this I've had the data transferred into ListBoxes which makes it easier to remove duplicates, the data is then transferred back into a multi-line TextBox so it is editable. Here's my code so far. It either gives the wrong results or an index out of range error.
Dim Count1 As Integer
Dim Count2 As Integer
Dim Count3 As Integer
Dim NewInt As Integer
Dim ValOne As Integer
Dim ValTwo As Integer
ListBox1.Items.Clear()
ListBox2.Items.Clear()
ListBox3.Items.Clear()
NewInt = 0
ValOne = 0
ValTwo = 0
ListBox1.Items.AddRange(Players.Text.Split(vbNewLine))
ListBox2.Items.AddRange(Goals.Text.Split(vbNewLine))
ListBox3.Items.AddRange(Positions.Text.Split(vbNewLine))
Count1 = ListBox1.Items.Count
Count2 = ListBox2.Items.Count
Count3 = ListBox3.Items.Count
If Count1 = Count2 And Count1 = Count3 And Count2 = Count3 Then
'Set two counters to compare all words with each other
For iFirstCounter As Integer = 0 To ListBox1.Items.Count - 1
For iSecondCounter As Integer = 0 To ListBox1.Items.Count - 1
'Make sure there will not be an 'out of range' error,
'because you are removing items from the listbox.
iSecondCounter = Convert.ToInt64(iSecondCounter)
iFirstCounter = Convert.ToInt64(iFirstCounter)
ListBox2.Items.RemoveAt(iSecondCounter)
ListBox2.Items.RemoveAt(iFirstCounter)
If iFirstCounter < iSecondCounter Then
ListBox2.Items.Insert(iFirstCounter, NewInt.ToString)
Else
ListBox2.Items.Insert(iSecondCounter, NewInt.ToString)
End If
Next
Next
Players.Text = ""
Goals.Text = ""
Positions.Text = ""
Dim i As Integer
For i = 0 To ListBox1.Items.Count - 1
If Players.Text = "" Then
Players.Text = ListBox1.Items(i)
Else
Players.Text = Players.Text & vbNewLine & ListBox1.Items(i)
End If
Next
Dim a As Integer
For a = 0 To ListBox2.Items.Count - 1
If Goals.Text = "" Then
Goals.Text = ListBox2.Items(a)
Else
Goals.Text = Goals.Text & vbNewLine & ListBox2.Items(a)
End If
Next
Dim b As Integer
For b = 0 To ListBox3.Items.Count - 1
If Positions.Text = "" Then
Positions.Text = ListBox3.Items(b)
Else
Positions.Text = Positions.Text & vbNewLine & ListBox3.Items(b)
End If
Next
Else
MessageBox.Show("The Text Boxes don't contain an equal number of values ... please add more/remove some values")
End If
Could be done in multiple ways, for example:
If TextBox2.Lines.Count > 1 Then
Dim LineList As List(Of String) = TextBox2.Lines.ToList 'textbox lines
Dim NewLines As List(Of String) = TextBox2.Lines.ToList 'can't edit list we're looping over, a copy of lines
Dim NamesList As New List(Of String)
For x = 0 To LineList.Count - 1
Dim linesplit As String() = LineList(x).Split({" "}, StringSplitOptions.RemoveEmptyEntries)
If NamesList.Contains(linesplit(0)) Then
NewLines.Remove(LineList(x))
Else
NamesList.Add(linesplit(0))
End If
Next
TextBox2.Lines = NewLines.ToArray
End If
Here's an example of code that does this via LINQ and Lambdas.
Module Module1
Sub Main()
Dim ungroupedPlayers(1) As String
ungroupedPlayers(0) = "Jordan 26 Center"
ungroupedPlayers(1) = "Jordan 4 Center"
Dim players = ungroupedPlayers.ToList().ConvertAll(Of Player)(Function(x As String) As Player
Dim split() As String = x.Split(" "c)
Dim p As New Player
p.PlayerName = split(0)
p.Count = split(1)
p.Position = split(2)
Return p
End Function)
Dim playersGrouped = From p In players
Group By PlayerName = p.PlayerName Into g = Group
Select PlayerName, Count = g.Sum(Function(ip As Player) ip.Count), Position = g.Min(Function(ip As Player) ip.Position.ToString())
Dim groupedPlayers() As String = playersGrouped.ToList().ConvertAll(Of String)(Function(ip)
Return ip.PlayerName.ToString() & " " & ip.Count.ToString() & " " & ip.Position.ToString()
End Function).ToArray()
For Each groupedPlayer as String in groupedPlayers
Console.WriteLine(groupedPlayer)
Next
Console.Read()
End Sub
Public Class Player
Public PlayerName As String
Public Count As Integer
Public Position As String
End Class
End Module
You don't need heavy ListBox control for working with players data.
Use List(Of T) and create class Player for better readability.
You can remove duplicates before you will display values in your form.
And instead of multiline textbox you can use DataGridView as "right tool for the editing data".
Public Class Player
Public Property Name As String
Public Property Position As String
Public Property Goals As Integer
End
Public Class PlayersForm : Form
Private Sub Form_Load(sender As Object, e As System.EventArgs) Handles MyBase.Load
Dim data As List(Of Player) = LoadPlayersData()
Dim players As List(Of Player) = NormalizeData(data)
' Use DataGridView
Me.DataGridView1.DataSource = players
End Sub
Private Function LoadPlayersData() As List(Of Player)
Dim rawData As String() = File.ReadAllLines("pathToTextFile")
Return rawData.Select(Function(line) LineToPlayer(line)).ToList()
End Function
Private Function NormalizeData(players As List(Of Player)) As List(Of Player)
Return players.Group(Function(player) player.Name)
.Select(Function(group)
Return New Player With
{
.Name = group.Key,
.Position = group.First().Position,
.Goals = group.Sum(Function(player) player.Goals)
}
End Function)
.ToList()
End Function
Private Function LineToPlayer(line As String) As Player
Dim values = line.Split(" "c)
Return New Player With
{
.Name = values(0),
.Position = values(2),
.Goals = Integer.Parse(values(1))
}
End Function
End Class
DataGridView control will automatically update your List(Of Players) when you make any change. which give you possibility to have some other controls which automatically display best scorers for example, without extra converting data from string to integer and back.

Sort an array of structures in .NET

This is one of those times when only the hive mind can help - no amount of Google-fu can!
I have an array of structures:
Structure stCar
Dim Name As String
Dim MPH As Integer
Sub New(ByVal _Name As String, ByVal _MPH As Integer)
Name = _Name
MPH = _MPH
End Sub
End Structure
How do I sort the array on one variable / property of the structure?
Dim cars() as stCar = {new stCar("ford",10), new stCar("honda",50)}
cars.sort("MPH") // how do I do this?
Assuming that the structure has a property called MPH:
cars = cars.OrderBy(Function(c) c.MPH)
Note: the above code was auto-converted from the following c# code (in case it contains errors):
cars = cars.OrderBy(c => c.MPH);
The easiest way to perform the sort would be to use LINQ to Objects.
Dim q = From c In cars Order By c.MPH Select c
I don't know VB.NET, but you should be able to do this my implimenting IComparer. Take a look at this example
http://www.java2s.com/Code/VB/Data-Structure/UseIComparertosortbydifferentproperties.htm
Alternativly you can also use Linq
Another possibility, that doesn't use Linq but instead uses the .Net Array class' Sort method:
Module Module1
Structure stCar
Dim Name As String
Dim MPH As String
Sub New(ByVal _Name As String, ByVal _MPH As Integer)
Name = _Name
MPH = _MPH
End Sub
End Structure
Class CarCompareMph : Implements IComparer
Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
Dim xCar As stCar = DirectCast(x, stCar)
Dim yCar As stCar = DirectCast(y, stCar)
Return New CaseInsensitiveComparer().Compare(xCar.MPH, yCar.MPH)
End Function
End Class
Sub Main()
Dim cars() As stCar = {New stCar("honda", 50), New stCar("ford", 10)}
Array.Sort(cars, New CarCompareMph)
For Each c As stCar In cars
Console.WriteLine("{0} - {1} MPH", c.Name, c.MPH)
Next
End Sub
End Module
I'm not sure if that's what you're looking for, but it's another approach.
A simple way that seems to be working for me in vb.net 2013 is as follows:
cars.Sort(Function(c1,c2) c1.MPH.CompareTo(c2.MPH))
In VB.Net of VS2015 there is another method of sorting:
cars.Sort(New Comparison(Of stCar)(Function(x, y) 'x and y are of type of stCar
If x.MPH > y.MPH Then
Return 1 ' Return Value>0 means x>y
End If
If x.MPH < y.MPH Then
Return -1 ' Return Value<0 means x<y
End If
If x.MPH = y.MPH Then
Return 0 ' Return Value=0 means x=y
End If
End Function))
Public Class Form1
Public Structure EstruturaPessoa
Dim nome As String
Dim idade As Integer
End Structure
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
Dim nome(,) As String = {{"Milton Inácio Pozza", 30}, _
{"Araci Moraes", 34}, _
{"Marli Lipi Jesus", 21}, _
{"Gerson Guebur", 45}, _
{"Marli Ulths", 72}, _
{"Mauro Jesus Nadolni", 56}, _
{"Cristiano Kobashikawa Ferreira", 44}, _
{"Débora Nadolni", 90}, _
{"Samanta Gomes Guebur", 66}, _
{"Miguel Barbosa", 42}, _
{"Luis Jesus", 24} _
}
Dim Pessoa As EstruturaPessoa
Dim ListaPessoa = New List(Of EstruturaPessoa)
Dim i As Integer
'Load ListaPessoa
For i = 0 To (nome.Length / 2) - 1
Pessoa.nome = nome(i, 0)
Pessoa.idade = nome(i, 1)
ListaPessoa.Add(Pessoa)
Next i
'Fill the ListView1 with the ListaPessoa before sorting
For Each item_pessoa In ListaPessoa
With Me.ListView1
.Items.Add(item_pessoa.nome)
With .Items(.Items.Count - 1).SubItems
.Add(item_pessoa.idade)
End With
End With
Next
'Sort ListaPessoa
ListaPessoa.Sort(Function(c1, c2) c1.nome.CompareTo(c2.nome))
'Modifiy the 6th item of ListaPessoa
Pessoa = ListaPessoa(5)
Pessoa.nome += " ***" 'Acrescenta asteriscos ao nome
Pessoa.idade = 99 'Modifica a idade para 99
ListaPessoa(5) = Pessoa 'Atualiza o item na ListaPessoa
'Fill ListView2 with the ListaPessoa after sorting
For Each item_pessoa In ListaPessoa
With Me.ListView2
.Items.Add(item_pessoa.nome)
With .Items(.Items.Count - 1).SubItems
.Add(item_pessoa.idade)
End With
End With
Next
End Sub
End Class