I'm trying to find a way to only allow a user to input ".32" or "Not Used" into my datagridviewcell. Right now my code stands as below. When I run the code all it does is change everything to "Not Used". Even if I type in ".32" it will change it to "Not Used". Is there anyway to fix this? I appreciate any help or suggestions anyone can give.
If (e.ColumnIndex = 6) Then ' This specifies the column number
Dim cellData = DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value.ToString
If cellData Is Nothing OrElse IsDBNull(cellData) OrElse cellData.ToString = String.Empty Then
MessageBox.Show("Cannot Be Empty") ' This will prevent blank datagridviewcells
DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = "Not Used"
End If
Select Case cellData
Case 0.32
DataGridViewSize.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = 0.32
Case Else
DataGridViewSize.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = "Not Used"
End Select
End If
I think it no necessary to use select string
Better you change to Dim cellData = DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value
Related
I have a form with 3 text boxes, txt_customeracc, txt_customername, txt_customercontact
These 3 text boxes are optional and by default the text boxes will have "N/A" displaying on form load, but if a user enters information into one of them I want them to enter the information in the other two boxes also.
The code I am using is below
If txt_customername.Text <> "" Or txt_customername.Text <> "N/A" Or
txt_customercontact.Text <> "" Or txt_customercontact.Text <> "N/A" And
txt_customeracc.Text = "" Or txt_customeracc.Text = "N/A"
Then error1 += vbNewLine & "Please enter a correct Customer Account Number"
So from the above code I am expecting that if a user enters information in either the txt_customername or the txt_customercontact text boxes but not in the txt_customeracc box the warning should then appear but currently the warning message is displaying regardless of whether information is or isn't entered in any of the boxes. Can anyone tell me what I am doing wrong?
What is operator precedence ?
Your main problem here is that you have an issue with operator precedence. What is that ?
It is exactly the same issue as when doing calcuations, multiplication comes first, then comes addition. Well in VB .NET, And operator comes before Or, so what you have written in your code is evaluated as follow :
If txt_customername.Text <> "" Or
txt_customername.Text <> "N/A" Or
txt_customercontact.Text <> "" Or
(txt_customercontact.Text <> "N/A" And txt_customeracc.Text = "") Or
txt_customeracc.Text = "N/A"
Then
error1 += vbNewLine & "Please enter a correct Customer Account Number"
End If
Since this is not really what you want, let's build this together :
if customername OR customercontact is filled up
AND
customeracc is empty
That would give us :
if (
(txt_customername.Text <> "" Or txt_customername.Text <> "N/A") 'CustomerName is filled up
Or
(txt_customercontact.Text <> "" Or txt_customercontact.Text <> "N/A") 'Customer Contact is filled up
)
And
(txt_customeracc.Text = "" Or txt_customeracc.Text = "N/A") 'Customer account is empty
Then
'Do whatever
End If
Make it better, call a function
Another problem here is readability, this code may have errors because it's hard to read, so hard to debug.
What we can do is build a function that will check if a textbox is empty :
Private Function IsEmpty(Tb As Textbox) As Boolean
'Here we return true if tb.Text is empty or contains "N/A"
Return Tb.Text = "" Or Tb.Text = "N/A"
End Function
So that would make this a bit more readable :
if (Not IsEmpty(txt_customername) Or Not IsEmpty(txt_customercontact)) 'CustomerName or Customer Contact is filled up
And IsEmpty(txt_customeracc) 'Customer account is empty
Then
'Do whatever
End If
Make it better (2), Compare the strings
As stated by zaggler in his comment, here we don't use String Comparison. What if a user starts typing, then decides to put it back to N/A and writes it lowercase ("n/a") ? Well, we will make a mistake, believing that he did fill up the Textbox and you will end up searching for user "n/a" in your database, which is not a very good idea...
So let's compare the String, make our function even better :
Private Function IsEmpty(Tb As Textbox) As Boolean
'Here we return true if tb.Text is empty or contains "N/A" (or "n/a")
Return Tb.Text = "" Or (String.Compare(Tb.Text, "N/A", True) = 0)
End Function
Note
You can see here the advantage of functions. I wrote it because I didn't want to change to String.Compare() six times... Whenever you have the same code twice, it should be a function...
If you want to give the user a proper error message telling him what he has missed to fill out you have to split the if statement into several parts.
First check if all text boxes contain any valid data.
If not you can skip further checks directly.
If one textbox contains data check each and set error accordingly.
If (txt_customername.Text = "" OrElse txt_customername.Text = "N/A") AndAlso
(txt_customercontact.Text = "" OrElse txt_customercontact.Text = "N/A") AndAlso
(txt_customeracc.Text = "" OrElse txt_customeracc.Text = "N/A") Then
'No Error exit sub
Exit Sub
End If
'This part is only reached if one textbox contains data
If (txt_customername.Text = "" OrElse txt_customername.Text = "N/A") Then
error1 += vbNewLine & "Please enter a correct Customer Name"
End If
If (txt_customercontact.Text = "" OrElse txt_customercontact.Text = "N/A") Then
error1 += vbNewLine & "Please enter a correct Customer Contact"
End If
If (txt_customeracc.Text = "" OrElse txt_customeracc.Text = "N/A") Then
error1 += vbNewLine & "Please enter a correct Customer Account Number"
End If
As you can see I also recommend using short circuit OrElse and AndAlso which gives a littttttttle performance.
You could count the number of filled fields.
Dim numberFilled As Integer = 0
If txt_customername.Text <> "" And txt_customername.Text <> "N/A" Then
numberFilled += 1
End If
If txt_customercontact.Text <> "" And txt_customercontact.Text <> "N/A" Then
numberFilled += 1
End If
If txt_customeracc.Text <> "" And txt_customeracc.Text <> "N/A" Then
numberFilled += 1
End If
If numberFilled = 1 Or numberFilled = 2 Then
error1 += vbNewLine & "Please enter a correct Customer Account Number"
End If
Personally I would have a function IsValueEmpty that would check:
Function IsValueEmpty(ByVal value As String) As Boolean
If String.IsNullOrEmpty(value) Or value = "N/A" Then
Return True
End If
Return False
End Function
Could also Trim.
You could have the relevant message part stored in the Tag property of each textbox and use Linq :
Dim customerTextBoxes = {txt_customeracc, txt_customername, txt_customercontact}
Dim messages = Aggregate customerTextBox In customerTextBoxes
Where customerTextBox.Text = "" OrElse customerTextBox.Text = "N/A"
Select $"Please enter a correct {customerTextBox.Tag}")
Into ToArray
Then just check it's length against the initial one and if they're not equal aggregate the message for display
If customerTextBoxes.Length <> messages.Length Then error1 = String.Join(Environment.NewLine, messages)
I'm basically running through rows in a table. I'm checking each row to see if at least 1 of the columns im interested is = "pass" and that the rest = either "pass" or "N/A".
But im getting an error:
"An exception of type 'System.InvalidCastException' occurred in Microsoft.VisualBasic.dll but was not handled in user code
Additional information: Conversion from string "FAIL" to type 'Long' is not valid."
The statuses can either be "PASS", "FAIL", OR "N/A" in the DB is you're wondering where the FAIL came from.
Here's the code:
Private Function HasAuditPassed(activeLotId As String) As Boolean
Dim sql = String.Format("SELECT STEPID, CAVITYPAIRASTATUS,CAVITYPAIRBSTATUS,CAVITYPAIRCSTATUS,CAVITYPAIRDSTATUS FROM " & _
"TB_BL_AMMSSTEPSTATUS WHERE AUDITLOT = '{0}'", activeLotId)
Dim dynaset = DB.CreateDynaset(sql, DBWrapper.DynasetOptions.ORADYN_READONLY)
Do Until dynaset.EOF
Dim cavityPairAStatus = dynaset.GetFieldData(Of String)("CAVITYPAIRASTATUS")
Dim cavityPairBStatus = dynaset.GetFieldData(Of String)("CAVITYPAIRBSTATUS")
Dim cavityPairCStatus = dynaset.GetFieldData(Of String)("CAVITYPAIRCSTATUS")
Dim cavityPairDStatus = dynaset.GetFieldData(Of String)("CAVITYPAIRDSTATUS")
If (cavityPairAStatus Or cavityPairBStatus Or cavityPairCStatus Or cavityPairDStatus) = "PASS" And
(cavityPairAStatus And cavityPairBStatus And cavityPairCStatus And cavityPairDStatus) = ("PASS" Or "N/A") Then
Return True
End If
Loop
Return False
End Function
Sadly, you can't do if statements that way. You have to write the entire statement out because VB .Net does not handle string comparison that way. So a statement that would be the equivalent and work would be much longer and look like this:
If (cavityPairAStatus = "PASS" OrElse cavityPairBStatus = "PASS" OrElse
cavityPairCStatus = "PASS" OrElse cavityPairDStatus = "PASS")
And (cavityPairAStatus = "PASS" OrElse cavityPairAStatus = "N/A" AndAlso
cavityPairBStatus = "PASS" OrElse cavityPairBStatus = "N/A" AndAlso
cavityPairCStatus = "PASS" OrElse cavityPairCStatus = "N/A" AndAlso
cavityPairDStatus = "PASS" OrElse cavityPairDStatus = "N/A") Then
Return True
End If
A few more elegant solutions with creating lists are below, and can be used to help out readability some if you have to write statements like this repeatedly.
There are a couple of issues here. You can't write a If stytement in this style and you can't use binary operators (And and Or) with String.
Your If statement should be something like this:
If (cavityPairAStatus = "PASS" OrElse cavityPairBStatus = "PASS" OrElse …
If you want something a little more elegant you may consider something like this:
Dim values = {cavityPairAStatus, cavityPairBStatus, cavityPairCStatus, cavityPairDStatus}
If values.Any(Function(v) v.Equals("PASS")) AndAlso values.All(Function(v) v.Equals("PASS") OrElse v.Equals("N/A")) Then
…
End If
The way IF statement you have used is incorrect.
To compare so many conditions you need to write them separately.
Instead of using IF condition here I would suggest you to use a list.
Here's the sample code
Dim cavityPairStatus As New List(Of String)
cavityPairStatus.Add(dynaset.GetFieldData(Of String)("CAVITYPAIRASTATUS"))
cavityPairStatus.Add(dynaset.GetFieldData(Of String)("CAVITYPAIRBSTATUS"))
cavityPairStatus.Add(dynaset.GetFieldData(Of String)("CAVITYPAIRCSTATUS"))
cavityPairStatus.Add(dynaset.GetFieldData(Of String)("CAVITYPAIRDSTATUS"))
If cavityPairStatus.Contains("PASS") OrElse cavityPairStatus.Contains("N/A") Then
Return True
End If
I have multiple textboxes in a groupbox, and can successfully cycle through them all. However the checkNumbers sub fails to recognise blank/null entries, and also non-numeric characters. The correctValidation boolean should return true if all the criteria are met (no blanks/nulls, and must be a number between 1-20). Any thoughts on how to solve this would be appreciated.
Private Sub checkNumbers()
Try
For Each txt As TextBox In Me.gbTechnical.Controls.OfType(Of TextBox)()
If txt.Text <> "" And IsNumeric(txt.Text) And (Integer.Parse(txt.Text) >= 1 And Integer.Parse(txt.Text) <= 20) Then
correctValidation = True
Else
correctValidation = False
MsgBox("Please ensure all numbers are between 1 and 20")
Exit Sub
End If
Next
Catch ex As Exception
MessageBox.Show("General: Please ensure all numbers are between 1 and 20")
End Try
End Sub
I would use Integer.TryParse and then >= 1 AndAlso <= 20. You could use this LINQ query:
Dim number As Int32
Dim invalidTextBoxes =
From txt In gbTechnical.Controls.OfType(Of TextBox)()
Where Not Integer.TryParse(txt.Text, number) OrElse number < 1 OrElse number > 20
Dim correctValidation = Not invalidTextBoxes.Any()
Note that you should almost always use AndAlso instead of And and OrElse instead of Or since those operators are Is short-circuiting boolean operators. This can be more efficient and - more important - can prevent errors. Consider this:
Dim text = ""
If txt IsNot Nothing And txt.Text.Length <> 0 Then text = txt.Text
This fails if txt is nothing since the second condition is evaluated even if the first already was evaluated to false which causes a NullReferenceException at txt.Text.
if you only want a number value, why don't you try to use NumericUpDown. You can also set the Minimum and Maximum in property or use
NumericUpDown1.Maximum = 20
so, there won't be a need to do checkNumbers.
Or is there any reason that you have to use textbox??
I'm trying to allow only alphanumeric input in my datagridview column. Is there a way to allow alphanumeric input and also prevent the user from entering negative numbers or leaving the cell blank? If anyone has any suggestions or answers I would greatly appreciate it! :) Here is my code below. I already have the negative and blank cell validation working, but its not allowing me to input non-numeric input.
If (e.ColumnIndex = 0) Then 'checking value for column 1 only
Dim cellData = DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value
If cellData Is Nothing OrElse IsDBNull(cellData) OrElse cellData.ToString = String.Empty Then ' This will prevent any blank cells
MessageBox.Show("Name Cannot Be Empty")
DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = "Object" ' This is a default value that I want to supply after the message box
ElseIf cellData < 0 Then
MessageBox.Show("Negative Numbers Not Allowed") 'This prevents negative numbers
DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = "Object"
Exit Sub ' Again this a default value I want supplied back to the datagridivewcell
End If
End If
So my code works, except when I enter any type of non-numeric character the program stops and exits.
Try using TryParse like this:
If (e.ColumnIndex = 0) Then 'checking value for column 1 only
Dim cellValue As Integer
If (Int32.TryParse(DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value, cellValue)) Then
If cellValue < 0 Then
MessageBox.Show("Negative Numbers Not Allowed") 'This prevents negative numbers
DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = "Object"
Exit Sub ' Again this a default value I want supplied back to the datagridivewcell
End If
Else
Dim testValue As String = DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value
If (String.IsNullOrEmpty(testValue)) Then
MessageBox.Show("Name Cannot Be Empty")
DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = "Object" ' This is a default value that I want to supply after the message box
End If
End If
End If
Please take a look at the following code:
Try
Dim Reader As New System.IO.StreamReader(PositionsFileName)
Do While Reader.Peek() <> -1
Dim Positions() As String = Reader.ReadLine().Split("|")
If (Positions(0) Is Nothing) Or (Positions(1) Is Nothing) Or (Positions(2) Is Nothing) Then
' something
End If
Loop
Catch ex As Exception
ex.Source = Nothing
End Try
I am reading a file and expecting format something|something1|something2. I am trying to make it set "Nothing" to the array index which does not exists (the file format is broken), so that the If statement goes smoothly, but it seem I am doing it wrong. Can you give me some hints?
If you do Split("|") and there are only 2 items (for example, something|something1), Positions(2) will not be Nothing, it will just not be there. So your code will raise an exception, something about index out of bounds of the array.
If you need Positions(2) contain Nothing in this case, you code can look like this:
Dim Positions(2) As String
Dim tmpArray() As String = Reader.ReadLine().Split("|")
For i = 0 To UBound(Positions)
If i <= UBound(tmpArray) Then
Positions(i) = tmpArray(i)
Else
Positions(i) = Nothing
End If
Next
I assume that you only have three "Somethings" per valid line. If so, try writing your Positions() assignment like this:
Dim Positions() As String = Reader _
.ReadLine() _
.Split("|") _
.Concat(Enumerable.Repeat("Nothing", 3)) _
.Take(3) _
.ToArray()
This will ensure that you have three items every time. No need to check for nothings.
Just check positions.length after the split. Also, if you want to check for cases like "||Something2|Something3", the first position will be "" not Nothing. The orelse is a shortcircuit that will keep the latter condtitions from being evaulated if an earlier condition is met.
If Positions.length < 3 OrElse Positions(0) = "" OrElse Positions(1) = "" OrElse Positions(2) = "" Then
' something
End If