check the item in listbox - vb.net - vb.net

I'm trying to do is check first the item in listbox if the value in textbox is already in listbox.
Private Sub txtSS_PreviewKeydown(ByVal sender As Object, ByVal e As System.Windows.Forms.PreviewKeyDownEventArgs) Handles txtSS.PreviewKeyDown
If e.KeyCode = Keys.Tab Then
For Each a As String In String.Join(vbCrLf, ListBox1.Items.Cast(Of String))
If txtSS.Text = a Then
MsgBox("It's already barcoded!")
txtSS.Text = ""
End If
Next
If txtMS.Text = txtSS.Text Then
MsgBox("This is already MAIN SERIAL! kindly check your barcoding serial", MsgBoxStyle.Exclamation)
txtSS.Text = ""
txtSS.Select()
Else
ListBox1.Items.Add(txtSS.Text)
txtSS.Clear()
txtSS.Select()
End If
End If
End Sub
But my code is not working.
the 'a' value of my for each is get only the first char of my listbox.

Think about this expression, used with the For Each loop:
String.Join(vbCrLf, ListBox1.Items.Cast(Of String))
The result of the expression is one string. When you use a string with a For Each loop, it doesn't go line by line. Rather, the loop runs for every character in the string, one character at a time, just as you saw. If you want each item in the ListBox, you don't need to use Join() at all:
For Each a As String In ListBox1.Items.Cast(Of String)()
Or I could refactor the whole method to be MUCH shorter and with less nesting:
Private Sub txtSS_PreviewKeydown(ByVal sender As Object, ByVal e As System.Windows.Forms.PreviewKeyDownEventArgs) Handles txtSS.PreviewKeyDown
If e.KeyCode <> Keys.Tab Then Exit Sub
If ListBox1.Items.Any(Function(a) txtSS.Text = DirectCast(a, String)) Then
MsgBox("It's already barcoded!")
Else If txtMS.Text = txtSS.Text Then
MsgBox("This is already MAIN SERIAL! Kindly check your barcoding serial.", MsgBoxStyle.Exclamation)
Else
ListBox1.Items.Add(txtSS.Text)
End If
txtSS.Clear()
txtSS.Select()
End Sub
This also fixes another bug in the original code, where the "It's already barcoded!" result didn't exit the method. The next If check would still have run, where the empty string isn't likely to match the main serial number, and so the method would still likely add a blank line to the bottom of the ListBox. That will no longer happen.
While I'm here, I see you're looking at the Tab key and using bar codes. Most barcode readers by default will send a return key (Cr/Lf) at the end of the scanned text. You can add code to handle this, as well, and possibly make things much easier and faster for you users to do repeated scans.

txtSS.Text = "a"
In your editor set option strict to on to see what is wrong in code

Related

Cancel EnterCell event of spread farpoint

My program use spread farpoint as a 3rd-party control, it has a TextBox control and a Spread control for showing data. When user change active cell in spread, I want to validate that the TextBox must not empty. If the TextBox is empty, EnterCell event must be cancel and the TextBox must got focus, also active cell of spread must not change. I'm stuck here.
Currently I performed validation in LeaveCell event but it doesn't work. EnterCell event fired and spread still changed the active cell :(
If TextBox1.Text = String.Empty Then
MsgBox ("TextBox1 cannot blank")
TextBox1.Select()
'TextBox1.Focus() 'I have tried this function but still not working
End If
Please support me!
Thanks all.
As far as my knowledge, there's nothing we can do to "cancel" EnterCell event. However, I found out that we could do a little trick to achieve it.
Private Sub spread_LeaveCell(sender as Object, e as LeaveCellEventArgs) Handles sprSheet.LeaveCell
If TextBox1.Text = String.Empty Then
MsgBox ("TextBox1 cannot blank")
'This is the trick
e.NewColumn = e.Column
e.NewRow = e.Row
Exit Sub
End If
'Other leave cell proceses..
End Sub
...
Private Sub spread_EnterCell(sender as Object, e as EnterCellEventArgs) Handles sprSheet.EnterCell
If TextBox1.Text = String.Empty Then
TextBox1.Select()
End If
Exit Sub

Barcode scanning to a listbox checking for duplicates

Good day!
I want to add some strings from a barcode scanner, captured in a text box, to a list box, and, before adding it, to check if the specific string hasn't been already added. So I have a text box called txtWO which captures what the reader scans and a list box called lstScanBOM to which I add the text box string if the item is not already added. The problem is, that whatever I do, only after the specific string is added twice the checking for duplicate entry starts to work. In other words I scan the same string twice, it added it, and then when I scan the third time only it throws the message with the error saying it is a duplicate. I don't understand why is doing this. The code is below:
Private Sub frmValidareFIP_Load(sender As Object, e As EventArgs) Handles MyBase.Load
If txtWO.Focused = False Then
txtWO.Select()
End If
End Sub
Private Sub AddUnique(StringToAdd As String)
If lstScanBom.Items.Contains(StringToAdd) = True Then
MsgBox("Articol duplicat!", vbOKOnly)
Else
'it does not exist, so add it..
lstScanBom.Items.Add(StringToAdd)
End If
End Sub
Private Sub txtWO_KeyDown(ByVal sender As Object,ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtWO.KeyDown
If e.KeyCode = Keys.Enter Then
Dim barcode As String
barcode = txtWO.Text
AddUnique(barcode)
txtWO.Clear()
txtWO.Focus()
End If
End Sub
IMO Try listing the data outside of the ListBox. I can't see why it isn't working, maybe we need a third pair of eyes to see it!?
Try adding a list (of string) as a Private within the form, populate this as your user scans, and check the duplicate there..
This is definately not the best solution, but I'm sure it will help!
Private List_Barcodes As List(Of String)
Private Sub frmValidareFIP_Load(sender As Object, e As EventArgs) Handles MyBase.Load
List_Barcodes = New List(Of String)
'You can also populate this list on load, if you have a stored cahce of previous scanned barcodes?
'List_Barcodes.Add("0123456")
'List_Barcodes.Add("4567890")
'...etc
If txtWO.Focused = False Then
txtWO.Select()
End If
End Sub
Private Sub AddUnique(StringToAdd As String)
If List_Barcodes.Contains(StringToAdd) Then
MsgBox("Articol duplicat!", vbOKOnly)
Else
'Place into dynamic list
List_Barcodes.Add(StringToAdd)
'and Place into your listbox
lstScanBom.Items.Add(StringToAdd)
End If
End Sub
Private Sub txtWO_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtWO.KeyDown
If e.KeyCode = Keys.Enter Then
Dim barcode As String
barcode = txtWO.Text
AddUnique(barcode)
txtWO.Clear()
txtWO.Focus()
End If
End Sub
Your barcode reader is returning <carriage return><line feed> as enter. Your code catches the enter key (carriage return = 13), but leaves the line feed (10) character. So the next time you scan something it will start with a line feed. The two strings in your example are different because the first is "58335001" and the second is "<line feed>58335001". The third one is "<line feed>58335001", which is a duplicate of the second.
One way to fix this is to trim your string.
Private Sub txtWO_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtWO.KeyDown
If e.KeyCode = Keys.Enter Then
Dim barcode As String
'Add the .Trim() to remove the leading <line feed> character
barcode = txtWO.Text.Trim()
AddUnique(barcode)
txtWO.Clear()
txtWO.Focus()
End If
End Sub
The most simple decision is ONLY to make your textBox control txtWO NOT multiline
And that's enough! Your code will work correctly!

Most efficient way to refer to multiple controls. IE: the multi-WITH

I have had a little look around and cannot seem to find an easy way to refer to multiple controls in stuff like an IF statement, or to set a property to multiple controls etc. (IF exists = true!)
The 'shortcut'if you like; would best be described in illegal code such as:
Public Sub BreakCompiler()
if string.IsNullOrEmpty(Textbox1.text, textbox2.text, textbox3.text) Then .....
'As opposed to
If String.IsNullOrEmpty(PartNumTextBox.Text) Or _
String.IsNullOrEmpty(PartNameTextBox.Text) Or _
String.IsNullOrEmpty(PartGRNTextBox.Text) Or_
String.IsNullOrEmpty(SerialNumTextBox.Text) Then
'Warn user
Else
'do nofin.
End If
Or even more outlandish:
WITH Textbox1.text, textbox2.text, textbox3.text
.ReadOnly = true
END WITH
End sub
The idea is to prevent having to run 3 if statements, or whatever, that basicaly do the same thing to 3 different objects...etc.. etc. Similar to a handler for multiple events that can be separated by a ','.
Im aware of looping through controls (IE for each control in groupbox.controls for eg) but that wouldn't quite achieve what I'm after here. (Say you wanted to skip a couple?)
Just thought id check the collective wisdom.
As far as I know, there isn't anything similar to a handler for control properties in if statements.
You either have to do them separately (or add them all into an array), or, as you mentioned, go through a subset within another control.
However, one thing you can do (say you only wanted to change a certain type of control), is this:
For Each tb As TextBox In Me.Controls.OfType(Of TextBox)
'do stuff here
Next
Another option is to create a Sub that will make the changes for you, and then pass each into the Sub.
Private Sub changeTextBox(tBox as TextBox)
'make changes here
End Sub
You want to process a variable length collection of some type of object. One way to do this is to write helper methods that have an argument decorated with ParamArray keyword.
Public Shared Function AnyIsNullOrEmpty(ParamArray controls As Control()) As Boolean
Dim ret As Boolean
For i As Int32 = 0 to controls.GetUpperBound(0)
ret = String.IsNullOrEmpty(controls(i).Text)
If ret then Exit for
Next
Return ret
End Function
Public Shared Sub SetTBReadOnlyProperty(value As Boolean,ParamArray textboxes As TextBox())
For i As Int32 = 0 to textboxes.GetUpperBound(0)
textboxes(i).ReadOnly=value
Next
End Sub
Possible usage:
Private Sub DemoUsage
If AnyIsNullOrEmpty(TextBox1,TextBox3,TextBox4) then
' at least one is empty
Else
' all have value
End If
SetTBReadOnlyProperty(True,TextBox1,TextBox3,TextBox4)
End Sub
The newer versions of .NET allow you to use the .ForEach Linq extension on a List object. If you build a e.g. a List(Of TextBox) you can use .ForEach with an anonymous method to quickly iterate the controls in the List and manipulate properties and so forth. It's still a loop - but in a much more compact form. You can be selective about which controls are in a List, and have multiple Lists etc.
Here's an example:
Public Class Form1
Private _BoxList As New List(Of TextBox)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
_BoxList.ForEach(Sub(tb As TextBox) tb.Enabled = Not (tb.Text = String.Empty))
End Sub
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
_BoxList.Add(Me.TextBox1)
_BoxList.Add(Me.TextBox2)
_BoxList.Add(Me.TextBox3)
End Sub
End Class
That's just 3 TextBoxs and a Button on a vanilla form:
For the particular example I was working on when I thought "There must be a better way" Something like this works perfectly.
It might be easier if trying to do multiple non type specific operations on different things. (Thanks #Sastreen and #the_lotus)
Private Sub Validate_PartDetails() Handles PartNumTextBox.TextChanged, PartNameTextBox.TextChanged, PartGRNTextBox.TextChanged, SerialNumTextBox.TextChanged
For Each tb As TextBox In BasicDetailsCustomGroupBox.Controls.OfType(Of TextBox)
If tb.Tag = "notnull" Then
If String.IsNullOrEmpty(tb.Text) Then
tb.BackColor = Color.MistyRose
Else
tb.BackColor = Control.DefaultBackColor
End If
End If
If tb.Tag = "notnumeric" Then
If not(isnumeric(tb.Text)) Then
tb.BackColor = Color.MistyRose
Else
tb.BackColor = Control.DefaultBackColor
End If
End If
Next
End Sub
Thanks guys.

If else inside a loop in VB.Net

The code below shows the event when a button click is fire
Protected Sub btnFinish_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnFinish.Click
For i As Integer = 0 To Gridview1.Rows.Count - 1 Step i + 1
Dim TextBox1 As TextBox = DirectCast(Me.Gridview1.Rows(i).FindControl("txtAnswer"), TextBox)
If TextBox1.Text = String.Empty Then
'do something
ElseIf TexBox1 <> String.Empty Then
'do something else
End If
Next
End Sub
The problem here is that the only condition being executed is in the If-statement even if it should execute the ElseIf-statement. Can someone explain why and how can I solve this problem? [EDITED]
a couple of things to note when comparing text/string:
String could be NULL, instead of Empty
use String.IsNULLOrEmpty to check NULL/Empty
String could be WhiteSpace too, use String.IsWhiteSpace to check it
User could enter a few spaces in some cases, if you want to make sure it's correct, use String.Trim to eliminate any unwanted spaces.
normally what I do is: (NOT String.IsNULLOrEmpty(givenText)) AndAlso givenText.Trim.Length <> 0

Text box validation

I am using many text boxes in a form.
How do i validate them,
In certain text boxes I have to use only text and in some I have to use only numbers.
Is using ASCII is a right method or is there any easier method to do this. If so please let me know the coding.
Above all other, don’t annoy the user. If I’m typing some text and the application prevents that (regardless of how it does that), I’m rightfully pissed off.
There are multiple values to handle this:
Use a NumericUpDown or a Slider control instead of a text box for numeric values (in other words: use the correct control instead of a general-purpose control).
Allow (more or less) arbitrary input and try to parse the user input in a meaningful way. For example, entering “+33 (0) 6 12-34-56” is an entirely meaningful format for a phone number in France. An application should allow that, and try to parse it correctly.
Granted, this is the hardest way, but it provides the best user experience.
Use the Validating event to validate input. This is automatically triggered whenever the user leaves the input control, i.e. when they have finished their input, and a validation will not annoy the user.
The MSDN documentation of the event gives an example of how this event is used correctly.
But do not use the KeyPress or TextChanged events to do validation. The first will disturb the users when entering text. The second will also annoy them when they try to paste text from somewhere else. Imagine the following: I am trying to copy an number from a website. Unfortunately, the text I have copied includes something else, too, e.g. “eggs: 14.33 EUR” instead of just “14.33”.
Now, the application must give me the chance to paste and correct the text. If I am not allowed to do that, the application is a UX failure. If the application uses the TextChanged event to prevent my pasting this text, I don’t get the chance to delete the offending text.
Text only limited to 40 characters:
<asp:RegularExpressionValidator ID="regexpText" runat="server"
ErrorMessage="Text only!"
ControlToValidate="txtName"
ValidationExpression="^[a-zA-Z]{1,40}$" />
Only Numbers:
<asp:RegularExpressionValidator ID="regexpNumber" runat="server"
ErrorMessage="Numbers only!"
ControlToValidate="txtName"
ValidationExpression="^[0-9]$" />
Wow, this can be a very broad topic...
For numeric textboxes, you should probably restrict input during KeyPress event:
Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
Dim allowedChars As String = "0123456789"
If allowedChars.IndexOf(e.KeyChar) = -1 Then
' Invalid Character
e.Handled = True
End If
End Sub
NOTE: This code sample is assuming WinForms, different approach must be used for web...
Regardless of the plat form, you should look into the validation controls offered by the framework, and that will allow you to validate that there is indeed input, values are in a specified range, and also using regex write more complicated validation rules.
The fastest way for validation is using regular expressions. They are harder to understand but offer better performance.
But you could do it also using string functions. Which is easier if you don't know regex but is less performant. This could be a viable option, depending on how hard the validation is.
Here and here are some posts that will help you with code samples.
Agreed that Regular Expressions might be faster, but ... well, here's how I've done it. Basically, this code is for a UserControl which contains a label, a text box, and an error provider. It also has various other properties, but here's the bit which deals with validation.
I do use this on the TextChanged event, because I don't want the user to continue typing if it's an invalid character; the rule checking "eats" the invalid character.
Public Enum CheckType
ctString = 0
ctReal = 1
ctDecimal = 2
ctInteger = 3
ctByte = 4
End Enum
Private mAllowNegative As Boolean = True
Private mAllowNull As Boolean = True
Private mCheckType As CheckType = CheckType.ctString
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
RuleCheckMe()
End Sub
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub RuleCheckMe()
'// Rule Checking
If Me.TextBox1.TextLength = 0 Then
If mAllowNull = False Then
Me.epMain.SetError(Me.TextBox1, "You are required to provide this value.")
Me.Valid = False
Else
Me.epMain.Clear()
Me.Valid = True
End If
Else
Select Case mCheckType
Case CheckType.ctString
If mInputMask.Length > 0 Then
'TODO: Figure out how to cope with input masks!
Me.Valid = True
Else
Me.Valid = True
End If
Case Else '// right now we're only testing for numbers...
If Not IsNumeric(Me.TextBox1.Text) And Me.TextBox1.Text <> "." And Me.TextBox1.Text <> "-" Then
If Not String.IsNullOrEmpty(Me.TextBox1.Text) Then
Me.TextBox1.Text = Me.TextBox1.Text.Remove(Me.TextBox1.Text.Length - 1, 1)
Me.TextBox1.SelectionStart = Me.TextBox1.Text.Length
End If
Me.epMain.SetError(Me.TextBox1, "This field does not accept non-numeric values.")
Me.Valid = False
ElseIf mAllowNegative = False And Me.TextBox1.Text.StartsWith("-") Then
Me.TextBox1.Text = Me.TextBox1.Text.Remove(Me.TextBox1.Text.Length - 1, 1)
Me.epMain.SetError(Me.TextBox1, "This field does not accept negative values.")
Me.Valid = False
ElseIf mCheckType = CheckType.ctByte And CType(Me.TextBox1.Text, Integer) > 255 Then
Me.epMain.SetError(Me.TextBox1, "This field does not accept values greater than 255.")
Me.Valid = False
Else
Me.epMain.Clear()
Me.Valid = True
End If
End Select
End If
End Sub
<System.ComponentModel.Browsable(True), _
System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Visible), _
System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Always), _
System.ComponentModel.Category("Data")> _
Public Property AllowNegative() As Boolean
<System.Diagnostics.DebuggerStepThrough()> _
Get
Return mAllowNegative
End Get
<System.Diagnostics.DebuggerStepThrough()> _
Set(ByVal value As Boolean)
mAllowNegative = value
End Set
End Property
<System.ComponentModel.Browsable(True), _
System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Visible), _
System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Always), _
System.ComponentModel.Category("Data")> _
Public Property AllowNull() As Boolean
<System.Diagnostics.DebuggerStepThrough()> _
Get
Return mAllowNull
End Get
<System.Diagnostics.DebuggerStepThrough()> _
Set(ByVal value As Boolean)
mAllowNull = value
End Set
End Property
<System.ComponentModel.Browsable(True), _
System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Visible), _
System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Always), _
System.ComponentModel.Category("Data")> _
Public Property DataTypeCheck() As CheckType
<System.Diagnostics.DebuggerStepThrough()> _
Get
Return mCheckType
End Get
<System.Diagnostics.DebuggerStepThrough()> _
Set(ByVal value As CheckType)
mCheckType = value
End Set
End Property
i would like to share my text box validator..
Dim errProvider As New ErrorProvider
' Verify that this field is not blank.
Private Sub txtValidating(sender As Object,
e As System.ComponentModel.CancelEventArgs) Handles _
txtName.Validating, txtStreet.Validating, txtCity.Validating,
txtState.Validating, txtZip.Validating
' Convert sender into a TextBox.
Dim txt As TextBox = DirectCast(sender, TextBox)
' See if it’s blank.
If (txt.Text.Length > 0) Then
' It’s not blank. Clear any error.
errProvider.SetError(txt, “”)
Else
' It’s blank. Show an error.
errProvider.SetError(txt, “This field is required.”)
End If
End Sub
' See if any field is blank.
Private Sub Form1_FormClosing(sender As Object,
e As FormClosingEventArgs) Handles Me.FormClosing
If (txtName.Text.Length = 0) Then e.Cancel = True
If (txtStreet.Text.Length = 0) Then e.Cancel = True
If (txtCity.Text.Length = 0) Then e.Cancel = True
If (txtState.Text.Length = 0) Then e.Cancel = True
If (txtZip.Text.Length = 0) Then e.Cancel = True
End Sub
Private Sub TxtEmployeenumber_KeyPress(sender As Object, e As KeyPressEventArgs) Handles TxtEmployeenumber.KeyPress
Dim c As Char
c = e.KeyChar
If Not (Char.IsDigit(c) Or c = "." Or Char.IsControl(c)) Then
e.Handled = True
MsgBox("numeric texts only")
End If
End Sub
just go to the keyup event of text box and enter the following code
100% it will work
if(Not Char.IsNumber(Chrw(e.Keycode))) Then
Messagebox.show ("only numeric values ")
textbox1.text=""
end if