Invalid Cast Expectation Was Unhanded (when checking the contents of a text box) - vb.net

This code is from a subroutine that checks if a text box entry fits the criteria specified (an integer between 1 and 100).
The first IF statement should check if it is not a numerical entry. If it is not numerical then the contents of the text box should be set blank so that a number can be entered.
The second IF statement should check if the number is larger than 100. If it is then the contents of the text box should be set blank so that an appropriate number can be entered.
The Third IF statement should check if the number is smaller than 1. If it is then the contents of the text box should be set blank so that an appropriate number can be entered.
Finally the contents of the box should be set as the variable.
I initially programmed the first IF statement on its own and it worked. But upon adding the others my program would crash when I typed anything into the text box and the error was as stated in my title. I have looked at multiple solutions and have found nothing for almost 2 days that fixed the problem.
Any suggestions would be appreciated.
Public Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles NumQTextBoxInput.TextChanged
'Check if input is numeric
If Not IsNumeric(NumQTextBoxInput.Text) Then NumQTextBoxInput.Text = ""
If (NumQTextBoxInput.Text > 100) Then
NumQTextBoxInput.Text = ""
End If
If (NumQTextBoxInput.Text < 1) Then
NumQTextBoxInput.Text = ""
End If
ArchwayComputingExamCreator.GlobalVariables.NumOfQuestions = NumQTextBoxInput.Text
'Setting the variable to the contense
End Sub

You should always use the appropriate parse function when accepting text for numbers.
Public Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles NumQTextBoxInput.TextChanged
Dim Value as integer
If Not Integer.TryParse(NumQTextBoxInput.text, Value) OrElse Value < 1 OrElse Value > 100 Then NumQTextBoxInput.Text = ""
... no idea if the archway bit is really what you wanted so left that out ....
End Sub

In this operation:
If Not IsNumeric(NumQTextBoxInput.Text) Then NumQTextBoxInput.Text = ""
Any time the input is not numeric, you set it to a value which is still not numeric. So any numeric comparison will fail:
If (NumQTextBoxInput.Text > 100)
Maybe you meant to set the value to some numeric default?:
If Not IsNumeric(NumQTextBoxInput.Text) Then NumQTextBoxInput.Text = "0"
Or just exit the method entirely when it's not numeric?:
If Not IsNumeric(NumQTextBoxInput.Text) Then
NumQTextBoxInput.Text = ""
Return
End If
Or perhaps something else? However you modify your logic, the point is that you can't perform numeric comparisons on non-numeric strings.

Related

Select a specific row from ComboBox and add amount in other Column from same row in DataGridView VB.NET

I'm using VB.NET for a small project. I have a DataGridView with some rows and columns.
I want to send amounts inside a specific row & column. For this purpose I'm using a ComboBox to select the receiver, but I cant manage to select the specific row & column for the amount.
Here is a photo of the form:
[
I managed to add the receivers inside the ComboBox and to add an amount, but in all rows.
This is code (it auto generates the rows for now).
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim rowId As Integer = Me.DataGridView1.Rows.Add()
Dim row As DataGridViewRow = Me.DataGridView1.Rows(rowId)
row.Cells("Column1").Value = "UNITED BANK"
row.Cells("Column2").Value = "1000"
row.Cells("Column3").Value = "ExampleInfo"
Dim rowId2 As Integer = Me.DataGridView1.Rows.Add()
Dim row2 As DataGridViewRow = Me.DataGridView1.Rows(rowId2)
row2.Cells("Column1").Value = "FREE BANK"
row2.Cells("Column2").Value = "2000"
row2.Cells("Column3").Value = "ExampleInfo"
Dim bolAdd As Boolean = False
Dim strValue As String
For Each myRow As DataGridViewRow In Me.DataGridView1.Rows
bolAdd = True
strValue = myRow.Cells("Column1").Value
For Each myItem As String In Me.ComboBox1.Items
If myItem = strValue Then bolAdd = False
Next
If bolAdd AndAlso Not (strValue Is Nothing) Then Me.ComboBox1.Items.Add(strValue)
Next
If Me.ComboBox1.SelectedIndex = -1 Then
Me.ComboBox1.SelectedIndex = 0
End If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For Each rowX As DataGridViewRow In Me.DataGridView1.Rows
rowX.Cells(1).Value = Val(rowX.Cells(1).Value) + Val(TextBox1.Text)
Next
End Sub
End Class
With this code, I'm able to add an amount, but to all rows.
I want to add an amount only to the row I selected in the ComboBox.
Your current code in the Button1_Click event is adding the amount from the text box to ALL the rows in the grid regardless of “what” value is selected in the combo box.
From what you describe, you want the amount from the text box to be added to rows that “match” the value in the combo box. The current code is never checking this, so the value from the text box is added to all the rows in the grid.
Therefore, the code needs to check to see if the value in Column1 "Receiver" “matches” the value in the combo box. If it DOES match, then add the value from the text box to the current value in Column2 "USD."
It is unclear if there may be more rows in the grid that have the same Column1 "Receiver" value and if you want to update those values also. I am assuming that there will only be ONE row in the grid that “matches” the value in the combo box. Therefore, once we find this value and add the amount, then we are done and the code will return without looping through the rest of the rows in the grid.
So is what you need to do is alter the code in the button click event to do this checking as described above.
There are a lot of checks we need to make. We need to check that the combo box has a value to compare to. Also, before we check ANY cell value, we need to make sure the cells value is not null BEFORE we try and call the cell's Value ToString method.
In addition, the cell MAY have a value, however, it may not be a number, so we have to check and make sure the value in the cell is an actual number and the same would apply to the text box.
So, walking through the code below would go something like…
If (Int32.TryParse(TextBox1.Text, addedValue)) … checks to see if
the text box amount is a valid number.
If (Not String.IsNullOrEmpty(targetComboValue)) … checks to make
sure the combo box value is not empty.
Then we start the loop through all the rows in the grid.
If (Not rowX.IsNewRow) … checks to see if the row is the “new” row
which we will ignore this “new” row.
If (rowX.Cells("Column1").Value IsNot Nothing) … checks to make
sure the “Receiver” cell is not null
If (rowX.Cells("Column1").Value.ToString() = targetComboValue) …
checks to see if the “Receiver” cells value matches the value in the
combo box.
If (rowX.Cells("Column2").Value IsNot Nothing) … check to make sure
the “USD” cell is not null.
And Finally,…
If (Int32.TryParse(rowX.Cells("Column2").Value.ToString(), currentValue)) … check to see if the value in the “USD” cell is a valid number.
If all these checks succeed then add the value from the text box to the current value in the “USD” cell.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim targetComboValue = ComboBox1.SelectedItem
Dim addedValue As Int32
Dim currentValue As Int32
If (Int32.TryParse(TextBox1.Text, addedValue)) Then
If (Not String.IsNullOrEmpty(targetComboValue)) Then
For Each rowX As DataGridViewRow In Me.DataGridView1.Rows
If (Not rowX.IsNewRow) Then
If (rowX.Cells("Column1").Value IsNot Nothing) Then
If (rowX.Cells("Column1").Value.ToString() = targetComboValue) Then
If (rowX.Cells("Column2").Value IsNot Nothing) Then
If (Int32.TryParse(rowX.Cells("Column2").Value.ToString(), currentValue)) Then
rowX.Cells("Column2").Value = currentValue + addedValue
Return
End If
End If
End If
End If
End If
Next
End If
End If
End Sub
I hope this makes sense.
You can edit the desired row just by using a syntax as follow:
Me.DataGridView1.Rows(1).Cells(2).Value = "your string"
So if you want to select corresponding to your combo index :
Dim myId As Integer = Me.ComboBox1.SelectedIndex
Me.DataGridView1.Rows(myId).Cells(2).Value = "your string"
But this assuming that the count of combo and DataGridView are same.
If not you should think about to add an id Column in your DataGridView ...
If you mean something else please explain, I will edit.

VB Text Box accepting Non numeric Data

I have a text box in VB which is set up to only accept only numeric data, and it works, except in TWO specific cases.
If the user provides a NON NUMERIC CHAR the text box self clears,
However, if the user first provides a number, then provides either '-' or '+'
The text box will accept this as a valid input.
When the user types one more char of ANY TYPE, i.e. number or char
Then the text box 'realises' and will self clear.
I was wondering if this is due to the way VB stores the chars '-' and '+'?
Is the best way around this to just add in the two exceptions, i.e. if '-' or '+' are input then self clear?
Or is there a more elegant solution?
Thank you.
Code:
Private Sub TextBox1_Change()
'Textval used as variable from user input
'Numval becomes textval providing the user input is numerical
Dim textval As String
Dim numval As String
textval = TextBox1.Text
If IsNumeric(textval) Then
numval = textval
Else
TextBox1.Text = CStr(numval)
End If
End Sub
code vb.net :
If Asc(e.KeyChar) <> 13 AndAlso Asc(e.KeyChar) <> 8 AndAlso Not IsNumeric(e.KeyChar) Then
' your code here
e.Handled = True
End If
and you can Replace text :
code :
Text = Text.Replace("string", "replace_by_this_string")
If the program requires the user to type only numeric data to the textbox, you should enforce the restriction when the user pressed a key
Use the textbox's KeyDown event:
'Omitting the parameters and Handles keyword
Private Sub textbox_KeyDown()
'Set the keys you would want to allow in this array
Dim allowedkeys As Keys() = {Keys.D1, Keys.D2, Keys.D3, Keys.D4, Keys.D5, Keys.D6, Keys.D7, Keys.D8, Keys.D9, Keys.D0, Keys.Back}
For i = 0 To allowedkeys.Length - 1 'Iterate through the allowed keys array
If e.KeyCode = allowedkeys(i) Then 'If the key pressed is present in the array...
Exit Sub 'The check returned a success. Exit and accept the key
End If
Next
e.SuppressKeyPress = True 'Supress all keys that failed the check
End Sub
Don't forget to add more keys that you need! The Space key, the numpad keys, the dot (point) keys?
This way you can remove the check in the Changed event and go directly to numval = textval
Or for those lazy programmers, numval = TextBox1.Text and numval = Val(TextBox1.Text) worked as well

Check if a Range in Datagridview contains an "," if yes change it to ":"

My application contains a Datagridview, the user has the possibility to enter values like: Day, Time, how many hours did he work etc. The problem is that my second application calculates with this data. It has to be in a certain format.
Like time should be "09:15", but i noticed that some users are using "09,15" instead. Can you help me guys, I need a code that can check if a Range in Datagridview contains some " blacklisted char" and if yes, replaces it with the right one.
Thanks for all.
Do not save values as a string.
Validate input string straight in the needed type.
Then validated values pass to the second application.
In this case you don't need "blacklisted chars"
Private Sub DataGridView_CellValidating(sender As Object,
e As DataGridViewCellValidatingEventArgs)
If e.RowIndex < 0 Then Exit sub
Dim dgv As DataGridView = DirectCast(sender, DataGridView)
Dim columnIndexWithInteger As Integer = 2
Dim columnIndexWithDate As Integer = 3
Select Case e.ColumnIndex
Case columnIndexWithInteger
Dim temp As Integer
If Integer.TryParse(e.FormattedValue, temp) = False Then
e.Cancel = True
End If
Case columnIndexWithDate
Dim temp As Date
If Date.TryParse(e.FormattedValue, temp) = False Then
e.Cancel = True
End If
End Select
End Sub
In DataGridView, you have one handle that allows you to check the validity of an edited cell : CellValueValidating. It is called before the user change is taken into account (CellValueChanged event).
You can find example and explanation here :
- https://msdn.microsoft.com/en-us/library/ykdxa0bc(v=vs.110).aspx
- https://msdn.microsoft.com/en-us/library/7ehy30d4(v=vs.110).aspx
You can also have a look at CellValueChanged, CellValueValidated and CellEndEdit events.

VBA 2012 - Need to return an error when a user enters text instead of a numbers

I am taking a VBA class and am completely stuck on this problem. We CANNOT use the masked text box, which would solve this problem. Instead the professor actually wants me to learn the code, can you imagine?
All kidding aside, the user needs to enter a gas price into a text box, then hit calculate to receive the total cost of the trip. There is much more to the interface but will spare you the details. If a user enters anything else number than a positive number with one decimal place, it should return an error. I have figured out 0 or 0000 as well as a negative number such as -3.45. Now I have to get any text or special characters to give me an error as well as something like 34.56.12.45. You never know, a user may feel the need to type in their IP address. The key to the assignment is that I catch all probable user errors.
Here is what I've written for the calculation as well as catch the errors. I have tried the Try/Catch statements as well. Nothing worked but I got the first two parts of the IF statement to work yet always failing on the last IF part until it gets to the calculation.
Private Sub btnCalc_Click(sender As Object, e As EventArgs) Handles btnCalc.Click
Dim Mileage As Decimal
Dim Miles As Decimal
Dim GasPrice As Decimal
Dim Cost As Decimal
If CDec(txtbxGasPrice.Text) = 0 Then
MessageBox.Show("Please enter a positive dollar amount")
txtbxGasPrice.Text = String.Empty
End If
If CDec(txtbxGasPrice.Text) < 0 Then
MessageBox.Show("Please enter a positive dollar amount")
txtbxGasPrice.Text = String.Empty
End If
If Cost = CDec((Miles / Mileage) * GasPrice) Then
Miles = CDec(lblTMiles.Text)
Mileage = CDec(lblMileage.Text)
GasPrice = CDec(txtbxGasPrice.Text)
lblTotalCost.Text = Cost.ToString("C2")
End If
If CBool(txtbxGasPrice.Text = "") Then
MsgBox("You must enter a dollar amount")
End If
*If Not IsNumeric(txtbxGasPrice.Text) Then
MessageBox.Show("Please enter a positive dollar amount")
txtbxGasPrice.Text = String.Empty*
End If
End Sub
'I have placed this at the top, in the middle, at the bottom but no luck. What am I missing?
Appreciate your thoughts - Lauren
This one seems to meet your criteria and pass David's tests:
Function IsValid(txt As String) As Boolean
If Not IsNumeric(txt) Then
Exit Function
End If
If Len(txt) < 2 Then
Exit Function
End If
If Not Mid(txt, Len(txt) - 1, 1) = "." Then
Exit Function
End If
If Not txt > 0 Then
Exit Function
End If
IsValid = True
End Function
This seems like a perfect application of regular expressions, but could be out of scope for this problem, maybe even better though vb has a Decimal.TryParse(or parse) that will take a string and try to parse it to a decimal.
http://msdn.microsoft.com/en-us/library/system.decimal.tryparse.aspx
on a side not I'm not 100% sure how it acts with xx.xx.xx but I'm betting it will fail and help your problem
I'm going to expand on CSgoose's idea to use RegEx, it seems a lot more reliable. I am very, very green when it comes to using RegEx but I try to work on Q's here at SO, so this may not be the optimal pattern to match, but a function like this seems to do the trick when I test a few value.
0/0.0/0.00 = False
-1.5 = False
1.5 = True
5.45 = False
Steve = False
Steve.6 = False
Steve6.58 = False
6.574.2 = False
A value that evaluates to 0 will return false. Negative values return false. Value must have a decimal component, be comprised of any # of digits (this can be tweaked if you want to limit it, eg., to ##.# format, etc.). Matches full text only, so things like IP addresses won't return true, etc.
NOTE This is VBA, but should be easily adaptable for your purposes)
Sub YourSub()
If Not IsMatch(CStr(txtbxGasPrice.Text)) Then
MsgBox "Please ensure that the value you enter is a positive dollar amount, to 1 decimal place!", vbCritical, "Invalid Gas Price Value!"
End IF
End Sub
This function requires enabling reference to Microsoft VBScript Regular Expressions 5.5, or you could use late-binding.
Function IsMatch(str As String) As Boolean
'Tests for a positive numeric value, formatted 0.0 with a mandatory decimal component
' exact match only
Dim re As RegExp
Dim allMatches As MatchCollection
Dim retVal As Boolean
retVal = False 'by default
If Not IsNumeric(str) Then GoTo EarlyExit 'ignore any non-numeric value
Set re = New RegExp
re.Pattern = "\d*\.[0-9]"
Set allMatches = re.Execute(str)
If allMatches.Count = 1 Then
'If there are multiple matches, then I think safe to say it's not a match,
' make sure it's a full string match
If str > 0 Then
retVal = (allMatches(0) = str)
End If
End If
EarlyExit:
Set re = Nothing
IsMatch = retVal
End Function
Update to force, for example, ##.# format, you could do
re.Pattern = "[1-9]?\d\.\d"

Input Validation for an integer in DataGridView

I'm able to use the code below to check whether or not a user inputs a string in a datagridview cell. If the user inputs a string a message pops up to tell them "only numeric entries are allowed". This is exactly what I want my code to do. However if I try to use this code in a column of data populated with numbers I get an error message that says "error happened, parsing commit". If anyone is able to figure out what the issue is here I would greatly appreciate it!
If (e.ColumnIndex = 3) Then 'checking numeric value for column 3 only
Dim value As String = DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value
For Each c As Char In value
If Not Char.IsDigit(c) Then
MessageBox.Show("Please Enter numeric Value")
DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = 3 'This will set the defaultvalue of the datagrid cell in question to the value of "3"
Exit Sub
End If
Next
End If
This solution not only checks for non-integer values it also works for every column populated with numbers for the entire datagridview. Also if the user inputs a non-integer if will supply a default value for the datagridviewcell, this default value is the previous number.
Private Sub DataGridView1_DataError(ByVal sender As Object, _
ByVal e As DataGridViewDataErrorEventArgs) _
Handles DataGridView1.DataError
If StrComp(e.Exception.Message, "Input string was not in a correct format.") = 0 Then
MessageBox.Show("Please Enter a numeric Value")
'This will change the number back to original
DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = " "
End If
End Sub
Do this in cellvalidating event ...
If (e.ColumnIndex = 3) Then 'checking numeric value for column 3 only
If Not Isnumeric(e.Formatted.Value) Then
MessageBox.Show("Please Enter numeric Value")
DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = 3 'This will set the defaultvalue of the datagrid cell in question to the value of "3"
Exit Sub
End If
End If