Add quantity if the DataGridView item already exists - vb.net

I have created a cart using a DataGridView and on the add to cart button I have this code:
Dim a As Integer
Dim total As Integer
Dim b As Integer
a = TextBox2.Text
b = NumericUpDown56.Value
total = a * b
ShoppingCart.DataGridView1.Rows.Add(Me.Label11.Text, Me.TextBox2.Text, Me.NumericUpDown56.Value, total)
Me.Hide()
ShoppingCart.Show()
How can I add quantity if I re-added the same item?

It is a little hard to answer this without knowing quite what the textbox and updowncounter do... but assuming you only expect the updown counter to change...
You can iterate through the data and hunt for the same text in the first column
Dim a As Integer
Dim total As Integer
Dim b As Integer
a = TextBox2.Text
b = NumericUpDown56.Value
total = a * b
Dim Updated As Boolean
For Each row As DataGridViewRow In ShoppingCart.DataGridView1.Rows
If CType(row.Cells(0).Value, String) = Me.Label11.text Then
row.Cells(2).Value = CType(row.Cells(0).Value, Integer) + b
row.Cells(3).Value = CType(row.Cells(3).Value, Integer) + total
Updated = True
Exit For
End If
Next
If Not Updated Then ShoppingCart.DataGridView1.Rows.Add(Me.Label11.Text, Me.TextBox2.Text, Me.NumericUpDown56.Value, total)
Me.Hide()
ShoppingCart.Show()
Though personally I'd bind the datagridview to a of List(of T) (t = a class that retains your properties) and search / modify that instead, then rebind the list.
Something along these lines...
Private Class cls_Cart_Item
Public Property Item_Name As String
Public Property Whatever_TExtbox2_IS_SUpposed_to_be As Integer
Public Quantity As Integer
Public Sub New(wName As String, wWhatever_TExtbox2_IS_SUpposed_to_be As Integer, wQuantity As Integer)
Item_Name = wName
Whatever_TExtbox2_IS_SUpposed_to_be = wWhatever_TExtbox2_IS_SUpposed_to_be
Quantity = wQuantity
End Sub
Public ReadOnly Property Total As Integer
Get
Return Whatever_TExtbox2_IS_SUpposed_to_be * Quantity
End Get
End Property
End Class
Private Cart As New List(Of cls_Cart_Item)
Private Sub Add_Or_Update()
ShoppingCart.datagridview1.datasource = Nothing
Dim a As Integer
Dim total As Integer
Dim b As Integer
a = TextBox2.Text
b = NumericUpDown56.Value
Dim Item As New cls_Cart_Item = Cart.Find(Function(x) x.Item_Name = Me.Label11.Text)
If Item Is Nothing Then
Cart.Add(New cls_Cart_Item(Me.Label11.Text, a, b))
Else
Item.Quantity += b
End If
Me.Hide()
ShoppingCart.datagridview1.datasource = Cart
End Sub
Though it's hard to tell from your question where this code is coming from relative to the daraviewgrid.

Related

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'''

Updating database at runtime

I can't update even if my code is correct.
I tried to change the data type from String to Integer but still nothing happens.
Private Sub UpdateQuanLoop()
For x As Integer = 0 To cartidentifier - 1
UpdateQuantity(ID(x), Quantity(x))
Next
End Sub
Private Sub UpdateQuantity(S_ID As String, S_Quan As String)
Dim finder As Integer
access.AddParam("#proID", S_ID)
access.ExecQuery("SELECT product_quantity FROM product WHERE product_ID = #proID;")
Dim Z As DataRow = access.DBDT.Rows(0)
finder = Z("product_quantity").ToString - S_Quan
access.AddParam("#ID", S_ID)
access.AddParam("#quan", finder)
access.ExecQuery("UPDATE product SET product_quantity = #quan WHERE product_ID = #ID;")
If NoErrors(True) = False OrElse access.RecordCount < 1 Then Exit Sub
End Sub
I don't have any error but the database is not updated.

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.

How can I put an extra value?

I have a table (DataGridView) like this :
Col1 | Col2 | Col3
3 | Mars | Regular
Here is my code:
For a As Integer = 0 To Form3.DataGridView1.Rows.Count - 1
For b As Integer = 0 To Form3.DataGridView1.Rows.Count - 1
For c As Integer = 0 To Form3.DataGridView1.Rows.Count - 1
If Form3.DataGridView1.Rows(c).Cells(2).Value = "Regular" Then
If Form3.DataGridView1.Rows(b).Cells(1).Value = Form3.MetroComboBox7.Items(0) Then
fair = 7 * Form3.DataGridView1.Rows(a).Cells(0).Value
Label1.Text += fair
End If
End If
Next
Next
Next
I want to set that if Regular is selected on Col3 and Mars on Col2 then the value is 7 and it will multiply by row Col1 and it will be the same every row.
I think you should use the event dtgv.CellMouseClick.
Then you create conditions that you want. I give you an example here :
Public Sub event_select() Handles dtgv.CellMouseClick
Dim row As Integer = dtgv.CurrentRow.Index()
' If the column 2 and 3 are selected
If dtgv.Rows(row).Cells(1).Selected = True And dtgv.Rows(row).Cells(2).Selected = True Then
' If the value of the 2nd column is Mars and the value of the 3rd column is Regular
If dtgv.Rows(row).Cells(1).Value = "Mars" And dtgv.Rows(row).Cells(2).Value = "Regular" Then
Label1.Text = 7 * dtgv.Rows(row).Cells(0).Value
End If
End If
End Sub
You should also check that no other rows have cells selected.
One loop for all rows is enough to calculate "fair" for all rows
Const REGULAR_VALUE As String = "Regular"
Const FAIR_COEFFICENT As Integer = 7
Dim fairSum As Integer = 0
For Each row As DataGridViewRow in DataGridView1.Rows
If REGULAR_VALUE.Equals(row.Cells(2).Value.ToString()) = False Then Continue For
If Equals(MetroComboBox7.Items(0), row.Cells(1).Value) = False Then Continue For
Dim col1Value As Integer = Integer.Parse(row.Cells(1).Value)
Dim fair As Integer = col1Value * FAIR_COEFFICENT
fairSum += fair
Next
Label1.Text = fairSum.ToString()
And set Option Strict On in your project or at least in the code file(first line of file).
This will save you time by giving fast feedback about possible type converting errors during compile time.
Create class which represent your data in strongly typed manner
Public Class Ticket
Public Property Passenger As Integer
Public Property Destination As String
Public Property Status As String
End Class
Then you can add rows to the DataGridView in easy way in your form
Public Class YourForm
Private _tickets As New BindigList(Of Ticket)()
Public Sub New()
InitializeComponent() ' Forms required method
DataGridView1.DataSource = _tickets
End Sub
Private Sub Populate(passenger As Integer, destination As String, Status As String)
Dim newTicket As New Ticket With
{
.Passenger = passenger,
.Destination = destination,
.Status = Status,
}
_ticket.Add(newTicket)
End Sub
'Then you can loop all rows with correct types
Private Sub Calculate()
Dim fairSum As Integer = 0
For Each ticket As Ticket in _tickets
If REGULAR_VALUE.Equals(ticket.Status) = False Then Continue For
If ticket.Destination.Equals(MetroComboBox7.Items(0)) = False Then Continue For
Dim fair As Integer = ticket.Passenger * FAIR_COEFFICENT
fairSum += fair
Next
Label1.Text = fairSum.ToString()
End Sub
End Class

Send text from textboxes to datagrid

I have for textboxes on my form and I would like the text there to be send to a datagrid. I wrote the following:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim itemName As String = txtItem.Text
Dim qty As Double = CDbl(txtQTY.Text)
Dim price As Double = CDbl(txtPrice.Text)
Dim Total As Double = price * qty
txtTotal.Text = Convert.ToString(Total)
Dim row As Integer = grdNewInvoice.Rows.Count
Dim data As TextBox() = New TextBox() {txtItem, txtQTY, txtPrice, txtTotal}
grdNewInvoice.Rows.Add()
For i As Integer = 0 To data.Length - 1
grdNewInvoice(i, row).Value = data(0)
Next
End Sub
But I get the following on my datagrid row: System.Windows.Forms.TextBox, Text: [textbox string]
I tried the following code as well to make sure there was nothing wrong with my settings on my datagrid:
'grdNewInvoice.Rows(0).Cells(0).Value = itemName
'grdNewInvoice.Rows(0).Cells(1).Value = qty
'grdNewInvoice.Rows(0).Cells(2).Value = price
'grdNewInvoice.Rows(0).Cells(3).Value = Total
That worked fine and the text went in as expected but since I will be writing to multiple lines on the datagrid, I will need to use a loop.
What am I doing wrong here?
One way to do this is to use a list of string array.
Dim row As Integer = grdNewInvoice.Rows.Count
Dim data As New List(Of String())
data.Add({txtItem.Text, txtQTY.Text, txtPrice.Text, txtTotal.Text})
data.Add({"Item2", "qtr2", "price2", "total2"})
data.Add({"Item3", "qty3", "price3", "total3"})
For i As Integer = 0 To data.Count - 1
grdNewInvoice.Rows.Add(data(i))
Next