none
How to avoid duplicate products in a VB.NET 2010 listview and increase the quantity

    Question

  • What I want to do is:

    It is a form for sales, from a textbox I enter the product code and then the product information in the listview is displayed with the code, product name, price, quantity, discount, subtotal and tax.

    When I add the same product, it is added in another line but what I want to do is instead of adding another line with the same product what I want it to do is to increase the quantity automatically and not add it to another line unless it is a different product, I have been trying for a long time and it is not achieved, if you can help me I would be very grateful.

    Tuesday, April 4, 2017 8:58 PM

Answers

  •  From the sounds of it,  i am taking a wild guess that you are entering the data into TextBoxes and that a Button is pressed to add the new product and its info to the ListView.

     If that is what you are doing,  then here is an example. However,  it is just an example and could use some error checking in it.  For example,  using Integer.TryParse would be better than using the CInt() function for converting the Strings to Integers.  That would allow for error checking which the CInt() function does not allow for.

     You can try it in a new form project with 1 ListView, 1 Button, and 2 TextBoxes added to the form.  I am only using two columns,  one for the product id,  and one for the quantity.  When you understand how it is working,  you should be able to update your existing project`s code to do the same thing.

    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            With ListView1
                .View = View.Details
                .Columns.Add("Column_ProductId", "Product Id") 'name 1st column as "Column_ProductId" and set its text to "Product Id"
                .Columns.Add("Column_Quantity", "Quantity") 'name 2nd column as "Column_Quantity" and set its text to "Quantity"
            End With
        End Sub
    
        Private Sub Button_AddProduct_Click(sender As Object, e As EventArgs) Handles Button_AddProduct.Click
            'get the ListViewItem of the first ListViewItem in the ListView that has the same Product Id that was entered into the ProductId textbox.
            'if none exist, then lvi will be nothing.
            Dim lvi As ListViewItem = ListView1.FindItemWithText(TextBox_ProductId.Text)
    
            If lvi IsNot Nothing Then
                Dim indx As Integer = ListView1.Columns("Column_Quantity").Index 'get the index of the Quantity column
                Dim Quant As Integer = CInt(lvi.SubItems(indx).Text) 'get an Integer value of the text String in the Quantity column from the matching ListViewItem
                Quant += CInt(TextBox_Quantity.Text) 'add the Integer value of the Quantity textbox to the Integer value from the Quantity column
                lvi.SubItems(indx).Text = Quant.ToString 'now set the text String in the Quantity column to the new Quantity
            Else
                Dim newlvi As ListViewItem = ListView1.Items.Add(TextBox_ProductId.Text) 'add the pruduct id to the 1st column
                newlvi.SubItems.Add(TextBox_Quantity.Text) 'add the quantity to the 2nd column
            End If
        End Sub
    End Class
    

     

     Here is an example of how it works...


    If you say it can`t be done then i`ll try it

    Tuesday, April 4, 2017 10:56 PM
  •  @ Ivannovish,

     Try replacing this line...

    Dim lvi As ListViewItem = ListProducts.FindItemWithText(txtCodProd.Text)

     

     With this line...

    Dim lvi As ListViewItem = (From i As ListViewItem In ListProducts.Items.Cast(Of ListViewItem) Where i.Text = txtCodProd.Text).FirstOrDefault

     

     The difference between the two lines is that the FindItemWithText method will find items that start with the same text.  Such as if the first item`s text was "A1112" and you tried adding a new item of "A11",  it would find the item "A1112".  This sounds like it may be the problem with it replacing the first item as you mentioned.  The second line will find any item that has the exact same text.

     Also,  if you are not giving the columns names and are going by the column indexes instead,  then the first line below is not needed.  You can just replace the (indx) in the second line with your column index.

                'Dim indx As Integer = ListProducts.Columns(3).Index 'not needed if your columns don't have names and you are using column indexes
                Dim Quant As Integer = CInt(lvi.SubItems(3).Text) 'just use the index (3) in this line
    
     

     One last thing is,  in the If part of the If Then Else statement,  when a matching item is found,  you only need to change the text of the subitems that need to be changed.  You would not need to set the SubItem(0) and probably 1 or two others.


    If you say it can`t be done then i`ll try it

    • Marked as answer by Ivannovish Thursday, April 6, 2017 7:43 PM
    Wednesday, April 5, 2017 10:22 AM

All replies

  • Hi

    Sounds straightforward, but you will need to show the code you use. Details of the data, the source of the data, the structure of the data, the format and details of the ListView.


    Regards Les, Livingston, Scotland

    Tuesday, April 4, 2017 10:04 PM
  •  From the sounds of it,  i am taking a wild guess that you are entering the data into TextBoxes and that a Button is pressed to add the new product and its info to the ListView.

     If that is what you are doing,  then here is an example. However,  it is just an example and could use some error checking in it.  For example,  using Integer.TryParse would be better than using the CInt() function for converting the Strings to Integers.  That would allow for error checking which the CInt() function does not allow for.

     You can try it in a new form project with 1 ListView, 1 Button, and 2 TextBoxes added to the form.  I am only using two columns,  one for the product id,  and one for the quantity.  When you understand how it is working,  you should be able to update your existing project`s code to do the same thing.

    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            With ListView1
                .View = View.Details
                .Columns.Add("Column_ProductId", "Product Id") 'name 1st column as "Column_ProductId" and set its text to "Product Id"
                .Columns.Add("Column_Quantity", "Quantity") 'name 2nd column as "Column_Quantity" and set its text to "Quantity"
            End With
        End Sub
    
        Private Sub Button_AddProduct_Click(sender As Object, e As EventArgs) Handles Button_AddProduct.Click
            'get the ListViewItem of the first ListViewItem in the ListView that has the same Product Id that was entered into the ProductId textbox.
            'if none exist, then lvi will be nothing.
            Dim lvi As ListViewItem = ListView1.FindItemWithText(TextBox_ProductId.Text)
    
            If lvi IsNot Nothing Then
                Dim indx As Integer = ListView1.Columns("Column_Quantity").Index 'get the index of the Quantity column
                Dim Quant As Integer = CInt(lvi.SubItems(indx).Text) 'get an Integer value of the text String in the Quantity column from the matching ListViewItem
                Quant += CInt(TextBox_Quantity.Text) 'add the Integer value of the Quantity textbox to the Integer value from the Quantity column
                lvi.SubItems(indx).Text = Quant.ToString 'now set the text String in the Quantity column to the new Quantity
            Else
                Dim newlvi As ListViewItem = ListView1.Items.Add(TextBox_ProductId.Text) 'add the pruduct id to the 1st column
                newlvi.SubItems.Add(TextBox_Quantity.Text) 'add the quantity to the 2nd column
            End If
        End Sub
    End Class
    

     

     Here is an example of how it works...


    If you say it can`t be done then i`ll try it

    Tuesday, April 4, 2017 10:56 PM
  • Ivan,

    You really need to go back to the data source itself. It doesn't have to be a "database", but you do need to think in terms of the separation of the data and the display of the data.

    Also, consider using a DataGridView - it's a better animal for this use than a ListView is.

    For what it's worth.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Wednesday, April 5, 2017 12:02 AM
  • Thank you for the answer IronRazerz, I was testing the code you posted and it increments the quantity but when I add a third product or second product the last product I add overwrites the first product on the first line.

    This is my code: I´m not a programmer with experience so please be patience with me any suggestion and help I will very much appreciate it. 

     Dim lvi As ListViewItem = ListProducts.FindItemWithText(txtCodProd.Text)

     If lvi IsNot Nothing Then
      Dim indx As Integer = ListProducts.Columns(3).Index 'get the index of the Quantity column
      Dim Quant As Integer = CInt(lvi.SubItems(indx).Text) 'get an Integer value of the text String in the Quantity column from the matching ListViewItem
                Quant += CInt(txtProd_Quantity.Text) 'add the Integer value of the Quantity textbox to the Integer value from the Quantity column
                lvi.SubItems(0).Text = CInt(txtCodProd.Text)
                lvi.SubItems(1).Text = TxtNameProd.Text.ToString
                lvi.SubItems(2).Text = Format(Decimal.Parse(txtPriceProd.Text), Fmt) 
                lvi.SubItems(3).Text = Quant.ToString
                lvi.SubItems(5).Text = Format(Decimal.Parse(ListProducts.Items(0).SubItems(5).Text) + Decimal.Parse(ListProducts.Items(0).SubItems(2).Text), Fmt)
                lvi.SubItems(6).Text = Format(Decimal.Parse(ListProducts.Items(0).SubItems(2).Text) * Decimal.Parse(ListProducts.Items(0).SubItems(3).Text) / 100 * Decimal.Parse(txtTax.Text), Fmt)

            Else

                Dim newlvi As ListViewItem = ListProducts.Items.Add(txtCodProd.Text) 'add the pruduct id to the 1st column
                newlvi.SubItems.Add(TxtNameProd.Text)
                newlvi.SubItems.Add(Format(Decimal.Parse(txtPriceProd.Text), Fmt))
                newlvi.SubItems.Add(txtProd_Quantity.Text) 'add the quantity to the 2nd 
                newlvi.SubItems.Add(Format(Decimal.Parse(TxtDiscount.Text), Fmt))
                newlvi.SubItems.Add(Format(Decimal.Parse(txtSubtotal.Text), Fmt))
                newlvi.SubItems.Add(Format(Decimal.Parse(txtSubtotal.Text) / 100 * Decimal.Parse(txtTax.Text), Fmt))
            End If

    "Fmt is for decimals that I declared ###,###,##0.00"

    Frank L. Smith you are right datagridview is best choice but i have been working with listview on this project and if I change it for a datagridview I will need to redo a lot code that i have done already, thanks anyways.

    Best regards,

    Ivannovish.


    Ivannovish



    • Edited by Ivannovish Wednesday, April 5, 2017 4:26 AM
    Wednesday, April 5, 2017 4:20 AM
  •  @ Ivannovish,

     Try replacing this line...

    Dim lvi As ListViewItem = ListProducts.FindItemWithText(txtCodProd.Text)

     

     With this line...

    Dim lvi As ListViewItem = (From i As ListViewItem In ListProducts.Items.Cast(Of ListViewItem) Where i.Text = txtCodProd.Text).FirstOrDefault

     

     The difference between the two lines is that the FindItemWithText method will find items that start with the same text.  Such as if the first item`s text was "A1112" and you tried adding a new item of "A11",  it would find the item "A1112".  This sounds like it may be the problem with it replacing the first item as you mentioned.  The second line will find any item that has the exact same text.

     Also,  if you are not giving the columns names and are going by the column indexes instead,  then the first line below is not needed.  You can just replace the (indx) in the second line with your column index.

                'Dim indx As Integer = ListProducts.Columns(3).Index 'not needed if your columns don't have names and you are using column indexes
                Dim Quant As Integer = CInt(lvi.SubItems(3).Text) 'just use the index (3) in this line
    
     

     One last thing is,  in the If part of the If Then Else statement,  when a matching item is found,  you only need to change the text of the subitems that need to be changed.  You would not need to set the SubItem(0) and probably 1 or two others.


    If you say it can`t be done then i`ll try it

    • Marked as answer by Ivannovish Thursday, April 6, 2017 7:43 PM
    Wednesday, April 5, 2017 10:22 AM
  • I have to thank you for helping me with this code, I really appreciete it. 

    I changed this code as you suggested and now it works greate.

    Dim lvi As ListViewItem = (From i As ListViewItem In ListProducts.Items.Cast(Of ListViewItem) Where i.Text = txtCodProd.Text).FirstOrDefault


     If lvi IsNot Nothing Then
                Dim indx As Integer = ListProducts.Columns(3).Index 'get the index of the Quantity column
                Dim Quant As Integer = CInt(lvi.SubItems(indx).Text) 'get an Integer value of the text String in the Quantity column from the matching ListViewItem
                Quant += CInt(txtProd_Quantity.Text) 'add the Integer value of the Quantity textbox to the Integer value from the Quantity column
                lvi.SubItems(2).Text = Format(Decimal.Parse(txtPriceProd.Text), Fmt) 
                lvi.SubItems(3).Text = Quant.ToString
                lvi.SubItems(5).Text =   lvi.SubItems(2).Text  * lvi.SubItems(3).Text 
                lvi.SubItems(6).Text = Format(Decimal.Parse(ListProducts.Items(0).SubItems(2).Text) * Decimal.Parse(ListProducts.Items(0).SubItems(3).Text) / 100 * Decimal.Parse(txtTax.Text), Fmt)

            Else

                Dim newlvi As ListViewItem = ListProducts.Items.Add(txtCodProd.Text) 'add the pruduct id to the 1st column
                newlvi.SubItems.Add(TxtNameProd.Text)
                newlvi.SubItems.Add(Format(Decimal.Parse(txtPriceProd.Text), Fmt))
                newlvi.SubItems.Add(txtProd_Quantity.Text) 'add the quantity to the 2nd 
                newlvi.SubItems.Add(Format(Decimal.Parse(TxtDiscount.Text), Fmt))
                newlvi.SubItems.Add(Format(Decimal.Parse(txtSubtotal.Text), Fmt))
                newlvi.SubItems.Add(Format(Decimal.Parse(txtSubtotal.Text) / 100 * Decimal.Parse(txtTax.Text), Fmt))

            End If


    Thank you,

    Ivannovish.



    • Edited by Ivannovish Thursday, April 6, 2017 4:24 PM
    Thursday, April 6, 2017 4:23 PM
  • I have to thank you for helping me with this code, I really appreciate it. 

    I changed this code as you suggested and now it works great.

    Ivannovish.



     You`re welcome.  8)

     PS - Please don't forget to mark the post or posts that answer your question as the answer(s).  Thanks.


    If you say it can`t be done then i`ll try it

    Thursday, April 6, 2017 6:36 PM
  • I just did mark the posts as answered for you.

    Thank you very much!


     

    Ivannovish

    Thursday, April 6, 2017 7:47 PM