Alternative Process - vb.net

I have 2 buttons and a DataGridView with 2 Columns (0 & 1).
The 1st button transfers a randomized cell from the Column(1) to a TextBox. Then, it stores that Cell in variable (a), plus the cell that opposites it in variable (b).
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim rnd As New Random
Dim x As Integer = rnd.Next(0, Form1.DataGridView1.Rows.Count)
Dim y As Integer = 1
Dim a As String = Form1.DataGridView1.Rows(x).Cells(y).Value
Dim b As String = Form1.DataGridView1.Rows(x).Cells(y - 1).Value
TextBox3.Text = a
End Sub
The 2nd button, however, is supposed to compare if another TextBox's text has the same string variable (b) has as Strings. Now, if so, then it has to display a certain message and so on...
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
If TextBox4.Text = b Then '<<< ISSUE HERE!
MsgBox("Correct! ^_^")
ElseIf TextBox4.Text = "" Then
MsgBox("You have to enter something first! O_o")
Else
MsgBox("Wrong! >,<")
End If
End Sub
The problem is that the variable (b) is surely not shared across the two "private" subs. And so, there is NOTHING to compare to in the 2nd button's sub! I presume that the solution here is to split the "randomization process" into a separate function, then execute it directly when the 1st button gets activated. Furthermore, that function's variables have to be SHARED somehow, and I certainly don't know how!
Thanks for Mr. Olivier, the code has been improved significantly! Yet, I still encounter a "wrong" comparison issue, somehow!
Dim RND As New Random
Dim x As Integer
Private Function GetCell(ByVal rowIndex As Integer, ByVal cellIndex As Integer) As String
Return Form1.DataGridView1.Rows(rowIndex).Cells(cellIndex).Value
End Function
Private Sub btnRoll_Click(sender As Object, e As EventArgs) Handles btnRoll.Click
x = RND.Next(0, Form1.DataGridView1.Rows.Count)
tbxRoll.Text = GetCell(x, 1)
End Sub
Private Sub btnSubmit_Click(sender As Object, e As EventArgs) Handles btnSubmit.Click
If tbxSubmit.Text = GetCell(x, 0) Then
MsgBox("Correct! ^_^")
ElseIf tbxSubmit.Text = "" Then
MsgBox("You have to enter something first! O_o")
Else
MsgBox("Wrong! >,<")
End If
End Sub</code>
Well, unbelievably, I read a guide about "comparison operations" in VB.net and tried out the first yet the most primal method to compare equality - which was to use .Equals() command - and worked like a charm! Thank God, everything works just fine now. ^_^
If tbxSubmit.Text.Equals(GetCell(x, 0)) Then
Alright now... This is going to sound weird! But, following Mr. Olivier's advise to investigate "debug" the code, I rapped the string I'm trying to compare with brackets and realized that it's been outputted after a break-line space! So, I used the following function to remove the "white-space" from both of the comparison strings! And it bloody worked! This time for sure, though. ^_^
Function RemoveWhitespace(fullString As String) As String
Return New String(fullString.Where(Function(x) Not Char.IsWhiteSpace(x)).ToArray())
End Function
If RemoveWhitespace(tbxSubmit.Text) = RemoveWhitespace(GetCell(x, 0)) Then

Turn the local variables into class fields.
Dim rnd As New Random
Dim x As Integer
Dim y As Integer
Dim a As String
Dim b As String
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
x = rnd.Next(0, Form1.DataGridView1.Rows.Count)
y = 1
a = Form1.DataGridView1.Rows(x).Cells(y).Value
b = Form1.DataGridView1.Rows(x).Cells(y - 1).Value
TextBox3.Text = a
End Sub
These fields can now be accessed from every Sub, Function and Property.
Of course Button3_Click must be called before Button2_Click because the fields are initialized in the first method. If this is not the case then you should consider another approach.
Create a function for the Cell access
Private Function GetCell(ByVal rowIndex As Integer, ByVal cellIndex As Integer) _
As String
Return Form1.DataGridView1.Rows(rowIndex).Cells(cellIndex).Value
End Function
And then compare
If TextBox4.Text = GetCell(x, y - 1) Then
...
And don't store the values in a and b anymore. If y is always 1 then use the numbers directly.
If TextBox4.Text = GetCell(x, 0) Then
...
One more thing: give speaking names to your buttons in the properties grid before creating the Click event handlers (like e.g. btnRandomize). Then you will get speaking names for those routines as well (e.g. btnRandomize_Click).
See:
- VB.NET Class Examples
- Visual Basic .NET/Classes: Fields

Related

Calculate cost of several items with tax and a discount

Can anyone help with this school task I have
The task is to ask the user for items and the cost of the items until they chose to stop. Then combine all the costs and take 20% VAT and 10% off from 2 randomly selected items.
Here is the code I have so far (I have 2 buttons and a listbox)
Public Class Form1
Dim CurrentA As Integer
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim Items(CurrentA) As String
Dim Coins(CurrentA) As Single
Dim Stay As String
CurrentA = 0
Do Until CurrentA = 20
Items(CurrentA) = InputBox("Please Enter The Item")
Coins(CurrentA) = InputBox("Please Enter The Cost Of The Item")
Stay = InputBox("Type Yes If More Items or Type No if no More")
Stay = Stay.ToLower
If Stay = "yes" Then
End If
If Stay = "no" Then
Exit Do
End If
ListBox1.Items.Add(Items(CurrentA) & " " & Coins(CurrentA))
CurrentA += 1
Loop
End Sub
End Class
First, a few comments on the code you presented.
Dim CurrentA As Integer
'An Integers default value is zero, I don't see why this is a class level variable
'always declare variables with as narrow a scope as possible
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim Items(CurrentA) As String 'Declares an Array of Type String with an Upper Bound of 0
'Upper Bound is the highest index in the array
'Arrays start with index 0
'So your array will have 1 element at index 0
Dim Coins(CurrentA) As Single
Dim Stay As String
CurrentA = 0 'unnecessary because the default of CurrentA is already 0, but OK for clarity because it could have been changed elsewhere
'This is behaving like a console application with the code repeating in a loop.
'In Windows Forms it would be more likely to do this in a button click event (btnAddItem)
Do Until CurrentA = 20
'On the first iteration CurrentA = 0
'On the second iteration CurrentA = 1 - this exceeds the size of your array
'and will cause an index out of range error
Items(CurrentA) = InputBox("Please Enter The Item")
'With Option Strict on you must change the input to a Single
Coins(CurrentA) = CSng(InputBox("Please Enter The Cost Of The Item"))
Stay = InputBox("Type Yes If More Items or Type No if no More")
Stay = Stay.ToLower 'Good! The user might no follow directions exactly
If Stay = "yes" Then
'This is kind of silly because it does nothing
End If
'Lets say I say no on the first iteration
'This avoids the index out of range error but
'nothing is added to the list because you Exit the loop
'before adding the item to the ListBox
If Stay = "no" Then
Exit Do
End If
ListBox2.Items.Add(Items(CurrentA) & " " & Coins(CurrentA))
CurrentA += 1
Loop
End Sub
We could use arrays but not knowing how many items will be added means either making the array bigger than needed or using Redim Preserve on every addition. A much better choice is a List(Of T). They work a bit like arrays but we can just add items without the ReDim stuff.
Private lstCost As New List(Of Single)
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
'Pretend this button is called btnAdd, and you have 2 test boxes
lstCost.Add(CSng(TextBox2.Text))
'The $ introduces an interpolated string. It is a step up form String.Format
ListBox2.Items.Add($"{TextBox1.Text} - {CSng(TextBox2.Text):C}") 'The C stands for currency
TextBox1.Clear()
TextBox2.Clear()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
'Pretend this button is called btnTotal
'Dim total As Single = (From cost In lstCost
' Select cost).Sum
Dim total As Single = lstCost.Sum
Label1.Text = total.ToString("C") 'C for Currency
End Sub

Case Statement not working with String Literals

Hi all I am trying to learn VB and am having trouble with some code I am using. I would like my program to output a specific number based on if a check box is checked using case statements but my code is not working.
Public Class frmBTPW
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles btncalc.Click
Dim dblhdr As Double
Dim dblfdr As Double
Dim dbltdr As Double
dblhdr = 24
dblfdr = 35
dbltdr = 50
Select Case "Power Wash Rental"
Case "Half Day Rental"
If chkhd.Checked = True Then
txtrc.Text = "poop"
End If
Case "Full Day Rental"
If chkFD.Checked = True Then
txtrc.Text = dblfdr
End If
End Select
End Sub
Private Function Button1_Click() As CheckBox
Throw New NotImplementedException
End Function
End Class
Help would be greatly appreciated.My code isn't outputting anything in the text-box.
Beyond case statements, respectfully I think you should read up on the distinction between a literal value and a variable. "Power Wash Rental" is nothing more than a series of characters, AKA a string: (In this case "P" followed by "o" etc.) Likewise, "Half Day Rental" is a series of characters, "H" followed by "a" etc.)
"Power Wash Rental" is a literal string. So is ""Half Day Rental" and of course they will never match.
Whereas:
Dim A as string
A = TextBox1.text
Now, A is a variable. It is a string which contains whatever series of characters (text) is typed into the textbox.
This is a simple way to do it.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
chkhd.tag = 24 ' store values in the check boxes
chkfd.tag = 35 ' using the tag property
chktd.tag = 50 ' and later add up the values
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles btncalc.Click
dim total as double = 0
total += IF(chkhd.checked, cdbl(chkhd.tag), 0)
total += IF(chkfd.checked, cdbl(chkfd.tag), 0)
total += IF(chktd.checked, cdbl(chktd.tag), 0)
msgbox(total)
End Sub
However, I think you might want radio buttons instead of checkboxes.
Checkboxes can all be checked. Radio buttons can only have one at a time.
This solution allows you to keep your price with the checkbox -- you could do this in the form designer instead of form load.
I would recommend reading up on Case Statements. Currently you will never get anywhere as your using a string to what, nothing. You also do not need a case for this... Also if the first condition is true and the last one is as well, the last one win's for setting the text, didn't know if you had this there for a reason or not?
If chkhd.Checked = True Then
txtrc.Text = "poop"
End If
If chkFD.Checked = True Then
txtrc.Text = dblfdr
End If
As others have stated your Case statement isn't working because you are using string literals to compare "Power Wash Rental" to "Half Day Rental" which will always be false. Plutonix was also correct in saying that a ComboBox for the rental duration should be used. The only reason not to be is if you were calculating cumulative rental days/amounts; however in that situation you should be using some sort of NumericUpDown for your multiplier against a time duration.
Here is an example that should help you get started. You could make the structure into a type of keyed collection or make it a wrapper class for a dictionary object which would make be easier to use in code. The following may not be exactly plug-and-play with your project, however it should help give you some ideas on how to handle the situation.
Option Strict On
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.ComboBox1.Items.AddRange({PowerWashRentals.halfDayText, PowerWashRentals.FullDayText, PowerWashRentals.TwoDayText})
AddHandler ComboBox1.SelectedValueChanged, AddressOf Me.ComboBox1_SelectedChanged
End Sub
Private Sub ComboBox1_SelectedChanged(sender As Object, e As EventArgs)
Dim cBox As ComboBox = DirectCast(sender, ComboBox)
Select Case cBox.SelectedItem.ToString
Case PowerWashRentals.halfDayText
Label1.Text = PowerWashRentals.HalfDayPrice.ToString
Case PowerWashRentals.FullDayText
Label1.Text = PowerWashRentals.FullDayPrice.ToString
Case PowerWashRentals.TwoDayText
Label1.Text = PowerWashRentals.TwoDayPrice.ToString
End Select
End Sub
End Class
Public Structure PowerWashRentals
Public Const HalfDayPrice As Double = 24
Public Const FullDayPrice As Double = 35
Public Const TwoDayPrice As Double = 50
Public Const halfDayText As String = "Half Day Rental"
Public Const FullDayText As String = "Full Day Rental"
Public Const TwoDayText As String = "Two Day Rental"
End Structure

How can I essentially stop my VB program until a valid value is entered via Text Box?

How can I work around an invalid/null value entered into a text box?
Basically I have a simple program I need to develop to solve a simple quadratic equation:
Public Class Main
Private Sub btnHelp_Click(sender As System.Object, e As System.EventArgs) Handles btnHelp.Click
UserGD.Show()
End Sub
Private Sub btnClear_Click(sender As System.Object, e As System.EventArgs) Handles btnClear.Click
txtStepX.Text = ""
lstResult.Items.Clear()
End Sub
Private Sub cmdGo_Click(sender As System.Object, e As System.EventArgs) Handles cmdGo.Click
Do
txtStepX.Text = InputBox("Please enter a valid value for x!", "Oops!", "")
Loop While String.IsNullOrEmpty(txtStepX.Text)
Dim stepx As Single
Dim X As Single
Dim y As Single
stepx = txtStepX.Text
Dim result As String
For X = -5 To 5 Step stepx
y = (3 * (X) ^ 2) + 4
result = ("x = " & X & " >>>>>>>>>> y = " & y)
lstResult.Items.Add(result)
Next
End Sub
End Class
This is the part I want to focus on:
Do
txtStepX.Text = InputBox("Please enter a valid value for x!", "Oops!", "")
Loop While String.IsNullOrEmpty(txtStepX.Text)
Dim stepx As Single
Dim X As Single
Dim y As Single
stepx = txtStepX.Text
Dim result As String
The above manages to check the text box (after its text value is changed by the Input Box) and loops fine, as long as it is empty... However, say I put a letter in, say, "l", it crashes and Visual Studio gives me the error "Conversion from string 'l' to type 'Single' is not valid." - which is fair enough. Although, I assumed the Null in isNullorEmpty meant it would catch invalid values, such as strings when it's supposed to be single.
I've tried quite a few things, and even my Computing teacher has been trying to get a solution.
I can't remember most of the things I've tried thus far so if I'll give whatever you guys come up with a go just to be on the safe side!
Update
Although not the clearest of code - here is what I found works the best for my needs:
'Written by a very tired and frustrated Conner Whiteside
'With his own blood.
'And sweat.
'And tears.
'Lots of tears.
'28/10/2014
Public Class Main
Private Sub btnHelp_Click(sender As System.Object, e As System.EventArgs) Handles btnHelp.Click
UserGD.Show()
End Sub
Private Sub btnClear_Click(sender As System.Object, e As System.EventArgs) Handles btnClear.Click
txtStepX.Text = ""
lstResult.Items.Clear()
End Sub
' On Go button click
Private Sub cmdGo_Click(sender As System.Object, e As System.EventArgs) Handles cmdGo.Click
'Checks if Text Box value is a number
If IsNumeric(txtStepX.Text) Then
'Declares variables if Text Box value is in fact a number
Dim result As String
Dim stepx As Double
Dim X As Double
Dim y As Double
'Displays error message with a re-input opportunity if previously entered number is out of range.
Do While txtStepX.Text <= 0 Or txtStepX.Text > 10
'InputBox simply changed the value of the TextBox's Text. MUST be an InputBox or there will be nothing to break the loop.
txtStepX.Text = InputBox("The step size for the x values must not be a negative number or above 10." & vbCrLf & "Please enter another number for the step size of the x values.", "Oops!")
'Covers an Empty input given that IsNumeric does not. This can also prevent crashing if the 'Cancel' or 'X' is pressed on InputBox.
If txtStepX.Text = "" Then
'Exits Sub Class in order to avoid running mathematical operations (below) with a string "". Effectively allows a 'reset'.
Exit Sub
End If
Loop
'After all checks, sets Text Boxvalue to variable stepx
stepx = txtStepX.Text
'Loops the solving of the equation from x = -5 to x = 5 with the specified step size.
For X = -5 To 5 Step stepx
'sets the answer of the equation (y) to variable y.
y = (3 * (X) ^ 2) + 4
'concatenates a string in the required format.
result = ("x = " & X & " >>>>>>>>>> y = " & y)
'Adds the result to the List Box before repeating the process for the next value of x.
lstResult.Items.Add(result)
Next
'Catches any non numeric inputs in the Text Box or the Input Box e.g "l".
ElseIf Not IsNumeric(txtStepX.Text) Then
'Displays error message before ending If statement and Sub Class, allowing the user to return to the start and try another input. - No Input Box or Exit Sub needed.
MsgBox("Please enter a valid number for the step size of the values of x.", 64, "Oops!")
End If
End Sub
End Class
Honestly wouldn't have gotten anywhere if it weren't for your efforts!
I would simply check if the input is numeric.
If IsNumeric(txtStepX.text) then
// Your statements
Else
// MsgBox("Please enter a number")
End if
However, it will accept something like 3.5.4
A more complicated solution would be to limit the characters from being entered by checking on each keypress,
Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
If e.KeyChar <> ChrW(Keys.Back) Then
If Char.IsNumber(e.KeyChar) Then
//Statements here
Else
e.Handled = True
End If
End If
End Sub
First, I recommend that you use the Double type instead of Single - it won't make any difference to how fast your program runs, but it will reduce rounding errors a lot.
Second, you can use Double.TryParse to check if a string can be parsed as a Double value. IsNumeric has some quirks which you do not want to find out about.
I took the liberty of adjusting the text which is shown to the user, as an "Oops!" before they have even tried to enter a value might be confusing, and it is better to tell them a number is needed than "a valid value":
Dim stepx As Double
Dim inp As String = ""
Dim inputTitle As String = "Number required"
Do
inp = InputBox("Please enter a number for x:", inputTitle)
' change the input box title to indicate something is wrong - if it is shown again.
inputTitle = "Oops!"
Loop While Not Double.TryParse(inp, stepx)
txtStepX.Text = stepx.ToString()

Dynamically moving a control for each character in a Textbox

Basically I'm trying to make a CheckBox move to the right using:
chk_ShowPassword.Location = New Point(X, Y)
Now the way I'm trying to do this is by checking for each character in the textbox and depending on the amount of characters there is, the checkbox will move to the right. I'm using:
For Each chr As Char In tb1.Text
chk_ShowPassword.Location = New Point(++85, 95)
Next
I need help with 2 things, I'm not sure why but it seems to be not moving to the right. It's meant to be moving to the right by 85 for each character. The other thing is that is 85 a good increment method for each character, is it too much, too little,
Can someone help me with this. Please if it's not clear you can ask me where to expand on and I'll do my best.
I think its important to save the starting point and do the movements from there. "Orgchk_ShowPasswordLocation"
So you can always go back to the starting point.
Do a count for the chars and then use "Orgchk_ShowPasswordLocation.X + Count * 10"
Then it will move forward or backwards if you add or delete chars in the text box.
Dim Orgchk_ShowPasswordLocation As Point
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Orgchk_ShowPasswordLocation = chk_ShowPassword.Location
End Sub
Dim cby As Integer
Dim cbx As Integer
Dim Count As Integer
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles tb1.TextChanged
cby = chk_ShowPassword.Location.Y
cbx = chk_ShowPassword.Location.X
Count = Nothing
For Each chr As Char In tb1.Text
Count = Count + 1
Next
cbx = Orgchk_ShowPasswordLocation.X + Count * 10
chk_ShowPassword.Location = New Point(cbx, cby)
End Sub

Passing arguments to methods in VB

I'm hoping you guys can help with a problem that should be simple to solve, I've just had issues finding a solution. In the program that I'm writing some of the textbox's have to be numeric between 1 and 10, and others just have to be numeric. Instead of coding each textbox to verify these parameters I decided to write methods for each of them. I'm having problems passing the arguments and getting it to function correctly. Included is some of my code that shows what I'm trying to accomplish.
Public Shared Sub checkforonetoten(ByVal onetoten As Double)
If (onetoten > 1 & onetoten < 10) Then
Else
MessageBox.Show("Please enter a Number between 1-10", "Error")
End If
End Sub
Public Shared Sub checkfornumber(numCheck As Double)
Dim numericCheck As Boolean
numericCheck = IsNumeric(numCheck)
If (numericCheck = False) Then
MessageBox.Show("Please enter a number", "Error")
End If
End Sub
Private Sub textboxS_TextChanged(sender As Object, e As EventArgs) Handles textboxS.TextChanged
Dim S As Double
S = textboxS.Text
checkfornumber(S)
checkforonetoten(S)
End Sub
One of your main problems is you're converting your text without validating it. You're also programming without the Options On to warn you of bad conversion techniques like you're using in the event handler.
The TryParse method would come in handy here:
Private Sub textboxS_TextChanged(sender As Object, e As EventArgs) Handles textboxS.TextChanged
Dim S As Double
If Double.TryParse(textboxS.Text, S) Then
checkforonetoten(S)
End If
End Sub
Since the TryParse method validates your text and sets the value to 'S', you only need to check the range.
Of course using NumericUpDown controls would make all this moot, since the values will always only be numbers and you can set the range on each one.
one way to structure it is to have one event procedure process the similar TB types:
Private Sub textboxS_TextChanged(sender As Object, e As EventArgs) _
Handles textbox1.TextChanged, textbox12.TextChanged, _
Handles textbox16.TextChanged
Dim S As Double
If Double.TryParse(Ctype(sender, TextBox).Text, S) Then
' or place the Check code here for all the TextBoxes listed above
checkforonetoten(S)
End If
End Sub
The plain numeric kind:
Private Sub textboxQ_TextChanged(sender As Object, e As EventArgs) _
Handles textbox2.TextChanged, textbox6.TextChanged
Dim S As Double
If Double.TryParse(Ctype(sender, TextBox).Text, S) = False Then
MessageBox.Show("Please enter a number", "Error")
End If
End Sub
Rather than calling a function and passing the current TextBox from events (which is fine), have 2 or 3 events process them all. The point is adding/moving the Handles clause to a common event procedure (be sure to delete the old ones).
If you do decide to call a common function, dont do anything in the events (you still have one per TB) and do it all in the common proc:
Private Sub textboxS_TextChanged(sender As Object, e As EventArgs) _
Handles textboxS.TextChanged
checkforonetoten(Sender)
End Sub
private Sub checkforonetoten(tb As Textbox)
Dim S As Double
If Double.TryParse(tb.Text, S) Then
' your check for 1 - 10 on var S
else
' error: not a valid number
End If
end sub
Also:
If (onetoten > 1 & onetoten < 10) Then
should be:
If (onetoten > 1) AndAlso (onetoten < 10) Then