VIsual Basic - Scan same item - vba

How to check if textbox contains the same barcode of the previous item scaned so that if it does, i will automatically increase quantity something like this:
Dim nextItemBarcode As String = Me.txtBarkodi.Text
Dim quantity As Integer = 1
If Me.txtBarkodi.Text = nextItemBarcode Then
quantity += 1
Else
quantity = 1
End If
Do you think I am missing sth or could there be a better algorithm for this scenario?

You're missing something. :-)
You need to store the value of the last bar code, not the next bar code. If the new one is the same as the last, you increment the quantity. If it's not the same, you reset quantity to one and store the new bar code as the last bar code.
Dim lastItemBarcode As String = ""
Dim quantity As Integer
' Scan now. If this is the first bar code,
' quantity will be set to 1 in the Else branch below
' Your scan should work in a loop starting here, so
' it keeps going and doesn't reset lastItemBarcode
' or quantity
If Me.txtBarkodi.Text = lastItemBarcode Then
' bar code same as last. Just increase quantity
quantity += 1
Else
' Either the first item scanned, or a different
' item. Save this bar code as the current one,
' and start our queantity at 1
lastItemBarcode = me.txtBarkodi.Text
quantity = 1
End If

Related

How to do math in VBA in Word?

As the 2020 tax season approaches, I'm trying to create a simple macro in Word that will take a few user inputs and populate an email template relating to stimulus checks to send to my clients. The actual macro just opens an info box with spaces for three user inputs. Inside of that box, there is an 'OK' button and a 'Cancel' button. The cancel button just hides the box, and the OK button performs the following:
Private Sub CommandButton1_Click()
Dim taxpayerName As Range
Set taxpayerName = ActiveDocument.Bookmarks("tpName").Range
taxpayerName.Text = Me.TextBox1.Value
Dim numberOfDep As Range
Set numberOfDep = ActiveDocument.Bookmarks("numDep").Range
numberOfDep.Text = Me.TextBox3.Value
Dim numberOfDep1 As Integer
numberOfDep1 = Me.TextBox3.Value
Dim maritalStatus As Range
Set maritalStatus = ActiveDocument.Bookmarks("mStatus").Range
maritalStatus.Text = Me.TextBox2.Value
Dim maritalStatus1 As Range
Set maritalStatus1 = ActiveDocument.Bookmarks("mStatus1").Range
maritalStatus1.Text = Me.TextBox2.Value
Dim maritalStatus2 As Range
Set maritalStatus2 = ActiveDocument.Bookmarks("mStatus2").Range
maritalStatus2.Text = Me.TextBox2.Value
Me.Repaint
tpInfo.Hide
Dim amount1 As Integer
If maritalStatus = "single" Then
amount1 = 1200
Else
amount1 = 2400
End If
amount1 = ActiveDocument.Bookmarks("a1").Range
End Sub
I'm trying to check my maritalStatus variable for 'single' and assign amount1 a value of either 1200 or 2400 for the first round of stimulus payments. I then want to insert that value into the Word document at bookmark a1 that I've created. However, I currently get the runtime error 13 on the last line of my code.
My end goal is to take amount1 and add it to a new variable (depAmount1) that would multiply $500 by the number of dependents, which should be stored in numberOfDep1. So a single taxpayer with 1 child would result in a total of $1,700. Then I would repeat the code with minor tweaks for the second round of stimulus payments and finally add the two totals together for the grand total.
Thanks in advance, any help would be greatly appreciated.
If the core of your question is the error on your last line of code, I think you're probably getting it because you're trying to assign a string from your bookmark to the amount1 variable, which is specified as an Integer, and I think you want to do the opposite, put the value into the document. Reversing your line of code should do the trick.
ActiveDocument.Bookmarks("a1").Range = amount1

How to sum specific data grid view cell with criteria?

I created a DataGridView where I am retrieving data by search customer id. I want to sum values in TextBox when I select some specific CheckBox-es of DataGridView.
But the problem is that it is adding all values in all cells of all rows but it should be like that for example; if Column number is 2, then pending value should be shown once in TextBox not after sum both duplicated received cell, and if Column numbers are different like Column number 1 and Column number 2 and both are selected, sum value should be there in TextBox which is named received from data grid view received cell.
I am attaching image and code also what I am trying to do. can someone guide how to do this?
Private Sub Getvalue()
For Each row As DataGridViewRow In DataGridView1.Rows
If DataGridView1.RowCount > 0 Then
Dim isSelected As Boolean = Convert.ToBoolean(row.Cells(0).Value)
If isSelected Then
Dim pending As String = 0
Dim received As String = 0
Dim final amount As String = 0
For index As Integer = 0 To DataGridView1.RowCount - 1
pending += Convert.ToDouble (DataGridView1.Rows(index).Cells(15).Value)
received += Convert.ToDouble(DataGridView1.Rows(index).Cells(14).Value)
finalamount += Convert.ToDouble(DataGridView1.Rows(index).Cells(12).Value)
Next
Label19.Reset Text()
Label19.Text = pending
Label20.Reset Text()
Label20.Text = received
Label24.Reset Text()
Label24.Text = final amount
If Label19.Text <= 0 Then
Label18.Text = ""
Else
Label18.Text = Val(Label 24.Text - Label 19.Text)
End If
End If
End If
Next
End Sub
First, turn on Option Strict as per my comment.
If there are not rows, your For Each row won't run so there is no need to check the RowCount.
Don't declare your accumulation variables inside the loop. They will be a new variable on each iteration. Your inner loop loops through all rows so, of course, you get the sum of all. Eliminate the inner loop.
I have no idea what Reset Text() is. A method can't have a space in its name. Anyway, it you are adding a new value it isn't necessary to clear the old one. If you do need to clear then set to "". Don't update your labels until after the loop. It is useless to update the user interface on each iteration. It will go by too fast for the user to see and it slows down the code.
In general, you need to do arithmetic or numeric comparisons with numeric types and set .Text properties with String type. The Val method has bee replace with several .net methods. .Parse, .TryParse, Convert. and in vb the CInt, CDec, etc.
Private Sub Getvalue()
Dim pending As Double = 0
Dim received As Double = 0
Dim finalAmount As Double = 0
For Each row As DataGridViewRow In DataGridView1.Rows
Dim isSelected As Boolean = CBool(row.Cells(0).Value)
If isSelected Then
pending += CDbl(row.Cells(15).Value)
received += CDbl(row.Cells(14).Value)
finalAmount += CDbl(row.Cells(12).Value)
End If
Next
Label19.Text = pending.ToString
Label20.Text = received.ToString
Label24.Text = finalAmount.ToString
If pending <= 0 Then
Label18.Text = ""
Else
Label18.Text = (finalAmount - pending).ToString
End If
End Sub
EDIT
Normally you would have a purchase. The purchase would have a table in the database with fields like purchase number, date, customer, etc. You would have another table with purchase details. The details table would have fields like details number (primary key), a foreign key purchase number which must match an entry in the purchase table, an item ID and a price.
When a customer wants to return an item or items from a purchase. You would enter the purchase number and fill your grid from the purchase details table.
Select * From PurchaseDetails Where purchaseNumber = #purchaseNumber
Put the check mark by each item returned and sum up the price column.
Purchase Table
PurchaseID | CustomerID | Date
Purchase Details Table
DetailID | PurchaseID | ItemCode | ItemPrice

Find and sum value of a datagridview column in vb.net

I want to find and sum qty value of searched id in data grid view column am using this code
Dim tqty As Double
For Each row As DataGridViewRow In dgv.Rows
If row.Cells.Item(0).Value = cmbItemCode.Text Then
tqty += row.Cells.Item(4).Value
Textbox1.text=tqty
Exit For
End If
Next
The problem is that Textbox1 shows only one top searched row value. For example
id item name qty
1 abc 4
2 xyz 10
1 abc 10
Textbox1 shows the Result only 4.
As soon as you hit the first value, you exit the for statement. Therefore you never get pass the first value. Erase the Exit For it should work.
If DataGridView2.RowCount > 1 Then
Dim tqty As Integer = 0
'if you have the other column to get the result you could add a new one like these above
For index As Integer = 0 To DataGridView2.RowCount - 1
amount += Convert.ToInt32(DataGridView2.Rows(index).Cells(2).Value)
'if you have the other column to get the result you could add a new one like these above (just change Cells(2) to the one you added)
Next
TextBox1.Text = tqty

Use an InputBox to enter prices of 4 items

I'm new to VB. Today I'm working on entering 4 prices for items to purchase using an input box. I need to create a counter in a loop. The only 2 buttons on the form "Enter Prices" and "Exit". So far this is the code I have (see below). I know something is off. When I run it, I'm allowed to enter 4 numbers. But at the end, when the message box comes up to show my total, it just gives me my last number I entered. I know I've got to change a few things, as I need my numbers to be in currency. Any suggestions as to where I need to go from here to get this up and running?
Private Sub btnPrices_Click(sender As Object, e As EventArgs) Handles btnPrices.Click
'Declare a variable as counter and accumulator
Dim intcount As Integer = 1I
Dim intAccumulator As Integer = 0I
'Declare and intialize variable
Dim strInput As String = ""
'Number of Items
Const intNUM_PRICES As Integer = 4
'Pre-test loop will keep iterating as long as the expression is ture.
Do While intcount <= intNUM_PRICES
'Get price of each item purchased
strInput = InputBox("Enter Price " & intcount, "Price Needed")
'Add 1 to the counter
intcount += 1
Loop
'Look at the value placed in the
MessageBox.Show("Your combined Price for all 4 items is: " & strInput)
End Sub
You've only got one variable for the input and each time you call InputBox you replace the previous value each time. If you want a total then you have to add the values, so you need to add the current input to the previous total each time, not replace it. Make sure that you convert the input to a number and use a numeric variable, because adding strings will actually join them, not add them mathematically.

Error code using Linq to add to a variable

I'll start with the problem, and then describe how the procedure works.
I'm getting a an error saying:
Value of type 'System.Collections.Generic.IEnumerable(Of LunchMoneyGame.LunchMoneyMainForm.Group)' cannot be converted to 'LunchMoneyGame.LunchMoneyMainForm.Group'.
The blue underline pinpointing the problem is on Dim obj As LunchMoneyGame.LunchMoneyMainForm.Group = From r In temp Where r.ID = Number Select r on the right side of the operator.
I know it is something to do with explicitness
--
This is for a table top card game i am converting to a text game.
The goal of this sub procedure is to subtract a card from a players hand and add it to the discard pile. Once added to the discard pile I then call the discard pile to move the cards from the discard pile to the card deck.
The problem starts with the number generator.
What I'm doing is randomly picking a card from the deck. by generating a the card id of a card in the deck. Once the ID is generated using linq the number generated then takes a card, then adds the card to the players inventory (quantity integer), and subtracts from the deck.
T represents whose turn it is. Currently for testing purposes I have coded it for only 2 players in terms of the T variable.
Private Sub GrabFromDeckAndDiscard()
Dim CardCheckBoxInteger As Integer
'ReDeclare CheckBox Array for Private sub
Dim CardCheckBoxArray() As CheckBox = {CardCheckBox1, CardCheckBox2, CardCheckBox3, CardCheckBox4, CardCheckBox5}
'Discard
Select Case T
Case 0
Player1HandGroup(NumberArray(Checks)).QuantityInteger -= 1
Case 1
Player1HandGroup(NumberArray(Checks)).QuantityInteger2 -= 1
Case 2
Player1HandGroup(NumberArray(Checks)).QuantityInteger3 -= 1
Case 3
Player1HandGroup(NumberArray(Checks)).QuantityInteger4 -= 1
Case 4
Player1HandGroup(NumberArray(Checks)).QuantityInteger5 -= 1
End Select
'Add Card to Discard Pile
DiscardGroup(NumberArray(Checks)).QuantityInteger += 1
'Shuffle Deck from Discard Pile if Deck is out of cards
Call DiscardPile()
'Reset Number Generator, unless weapon isn't discard
Dim temp As IEnumerable(Of LunchMoneyGame.LunchMoneyMainForm.Group) = From r In DeckGroup Where r.QuantityInteger > 0 Select r
If temp IsNot Nothing AndAlso temp.count > 0 Then
Number = (temp(Rnd.Next(0, temp.Count)).ID)
' ** Edit **: This will give you the actual object to be manipulated
Dim obj As LunchMoneyGame.LunchMoneyMainForm.Group = (From r In temp Where r.ID = Number Select r).Single
Dim PlayerQuantitySubtractionInteger As Integer
For PlayerQuantitySubtractionInteger = ChecksDynamicA To ChecksDynamicB
' ** Edit **
obj.QuantityInteger -= 1
'Select the Player depending value of T
Select Case T
Case 0
Player1HandGroup(Number).QuantityInteger += 1
Case 1
Player1HandGroup(Number).QuantityInteger2 += 1
Case 2
Player1HandGroup(Number).QuantityInteger3 += 1
Case 3
Player1HandGroup(Number).QuantityInteger4 += 1
Case 4
Player1HandGroup(Number).QuantityInteger5 += 1
End Select
CardTypeArray(PlayerQuantitySubtractionInteger) = Player1HandGroup(Number).CardType
CardCheckBoxArray(TextBoxInteger).Text = Player1HandGroup(Number).CardNameString
NumberArray(PlayerQuantitySubtractionInteger) = Number
Next PlayerQuantitySubtractionInteger
End If
'Switch to next player
Select Case T
Case 0
For CardCheckBoxInteger = 0 To 4
CardCheckBoxArray(CardCheckBoxInteger).Text = Player1HandGroup(NumberArray(CardCheckBoxInteger + 5)).CardNameString
Next
T += 1
Case 1
If GameSize = 2 Then
For CardCheckBoxInteger = 0 To 4
CardCheckBoxArray(CardCheckBoxInteger).Text = Player1HandGroup(NumberArray(CardCheckBoxInteger)).CardNameString
Next CardCheckBoxInteger
T -= 1
End If
If GameSize > 2 Then
T += 1
End If
Case 2
Case 3
Case 4
End Select
Label1.Text = T.ToString
'Clear Check Boxes when turn is finished
For CardCheckBoxInteger = 0 To 4
CardCheckBoxArray(CardCheckBoxInteger).Checked = False
Next
'Turn off play button
PlayButton.Enabled = False
End Sub
From r In temp
Where r.ID = Number
Select r
Returns a collection of everything which matches the Where clause (see this for the MSDN documentation). .NET represents this as an IEnumerable, which means a collection of things which can be iterated over (e.g. using a For loop or something like that).
There is no automatic concept that you'll only get one record returned even though your condition is an = (there may also be conditions, broadly, where no elements are returned such as when nothing matches the equality condition or where multiple things match the equality condition).
In order to indicate that you only want one element you can use the First, Single, FirstOrDefault or SingleOrDefault methods.
For example:
Dim obj As LunchMoneyGame.LunchMoneyMainForm.Group = (From r In temp Where r.ID = Number Select r).Single()
Which will give you an object of type LunchMoneyGame.LunchMoneyMainForm.Group, which I think you're looking for in this case.
As an aside, it's not bad to know the difference between the methods I've outlined above. In my lay perspective (as I'm no expert):
First returns the first item in the collection or throws an Exception if the collection is empty
FirstOrDefault returns the first item in the collection or null if empty
Single returns the only item in the collection or throws an Exception if the collection does not have exactly one item
SingleOrDefault returns the first item in the collection, null if the collection is empty and throws an exception if the collection has more than 1 element
So in your case, since you should only match on a single item with the = condition I would suggest using Single or SingleOrDefault
PS. Sorry, when I say null above, that'll be Nothing in VB.NET speak