textbox input only numbers and a decimal

I have a textbox used for input only. I want the input to be only numbers and a decimal if required. I have this but...there's a problem. The way I have it allows for multiple decimal points and this throws out an error. The numbers are used in a formula and say if someone accidently puts .002. then error city. Is there a way to prevent this??? Example please!!!
seeshelleAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

tirupur_selvaCommented:
Hi,
  In that case, you can use the Masked Edit control. In that control, you can set the 'Mask' property as "###.##"(or something like this) in design time. Or if you are using VB6.0, you can validate the input in the Validate() Event of the text box to the specified input format you need and if the data is not correct, you can set the cancel=true in that event. If you set Cancel = True, the control will not leave focus of the textbox. So, only if right input is given, you can move to next control.

Another method of validating is by using 'Microsoft VBScript Regular Expressions' in VB. All you have to do is search for the above topic in 'References' and select it. Then, in the form, you can create such as the following:
Dim MyValidity as New RegExp

you can set the followings:
MyValidity.Pattern = "someformat"
In the Text Box's Validate() Event

cancel = not (MyValidity.Test Text1.Text)

Hope any of these method would be helpful to you. If you are not clear with any of these method, I'll help you out.
Regs
Selva
Hope this would be helpful.
0
Éric MoreauSenior .Net ConsultantCommented:
I use this class for numeric text box:

Create a new project.

To this project add a class (that you will name clsNumeric) and copy this code to it:

Option Explicit

Public WithEvents gctlTextBox As TextBox

Private mblnNegatif As Boolean
Private mbytNumericLongueur As Byte
Private mbytNumericDecimal As Byte

'Convertit en majuscule au besoin
Private Sub gctlTextBox_KeyPress(KeyAscii As Integer)
    Call ValiderChampNombre(KeyAscii)
End Sub

'S'assure que le format est respecté
Private Sub gctlTextBox_Validate(Cancel As Boolean)
Dim blnNegatif As Boolean
Dim intPosSepDec As Integer

    '===============================================================
    'Recherche la position du séparateur de décimales
    '===============================================================
    intPosSepDec = InStr(gctlTextBox.Text, ".")

    '===============================================================
    'Détecte le symbole négatif
    '===============================================================
    blnNegatif = InStr(gctlTextBox.Text, "-")

    'Si pas de séparateur de décimales
    If intPosSepDec = 0 Then
        If Len(gctlTextBox.Text) - IIf(blnNegatif, 1, 0) > mbytNumericLongueur Then GoTo Invalide
    'Si séparateur de décimales
    Else
        If Len(gctlTextBox.Text) - intPosSepDec > mbytNumericDecimal Then GoTo Invalide
        If Len(gctlTextBox.Text) - Len(Mid$(gctlTextBox.Text, intPosSepDec)) - IIf(blnNegatif, 1, 0) > mbytNumericLongueur Then GoTo Invalide
    End If

    Exit Sub

Invalide:
    Cancel = True
    Beep
End Sub

'Initialise la longueur d'un champ numérique
Public Sub InitChampNombre(ByVal pbytLong As Byte, _
                           ByVal pbytDec As Byte, _
                           Optional ByVal pblnNegatif As Boolean = False)
    mbytNumericLongueur = pbytLong
    mbytNumericDecimal = pbytDec
    mblnNegatif = pblnNegatif
End Sub

Private Sub ValiderChampNombre(ByRef KeyAscii As Integer)
Dim blnNegatif As Boolean
Dim intPosSepDec As Integer

    '===============================================================
    'Si BackSpace = OK
    '===============================================================
    If KeyAscii = 8 Then Exit Sub

    '===============================================================
    'Valide si le caractère est légal (séparateur de décimales, -, 0 à 9)
    '===============================================================
    If Not (Chr$(KeyAscii) = "." Or _
       Chr$(KeyAscii) = "-" Or _
       IsNumeric(Chr$(KeyAscii)) Or _
       KeyAscii = 0) _
    Then GoTo Invalide
     
    '===============================================================
    'Si c'est le signe négatif
    '===============================================================
    If Chr$(KeyAscii) = "-" Then
        'Si ce n'est pas permis
        If Not mblnNegatif Then GoTo Invalide
         
        'Si ce n'est pas au début
        If gctlTextBox.SelStart > 0 Then GoTo Invalide
        'If Len(gctlTextBox.Text) <> 0 Then GoTo Invalide
    End If
     
    '===============================================================
    'Recherche la position du séparateur de décimales
    '===============================================================
    intPosSepDec = InStr(gctlTextBox.Text, ".")
     
    '===============================================================
    'Détecte le symbole négatif
    '===============================================================
    blnNegatif = InStr(gctlTextBox.Text, "-")
     
    '===============================================================
    'Si séparateur de décimales
    '===============================================================
    If Chr$(KeyAscii) = "." Then
        'Si ce n'est pas permis
        If mbytNumericDecimal = 0 Then GoTo Invalide
     
        'Si il y a déjà un séparateur de décimales
        If intPosSepDec <> 0 Then GoTo Invalide
         
        'Ne pas dépasser le nombre de décimales
        If Len(gctlTextBox.Text) - gctlTextBox.SelStart > mbytNumericDecimal Then GoTo Invalide
     
        'Ne pas dépasser le nombre d'entiers
        If gctlTextBox.SelStart - IIf(blnNegatif, 1, 0) > mbytNumericLongueur Then GoTo Invalide
    End If

    '===============================================================
    ' Le reste
    '===============================================================
    'Si pas de séparateur de décimales
    If intPosSepDec = 0 Then
        If Len(gctlTextBox.Text) - gctlTextBox.SelLength - IIf(blnNegatif, 1, 0) >= mbytNumericLongueur Then
            If Not (Chr$(KeyAscii) = "." Or Chr$(KeyAscii) = "-") Then GoTo Invalide
        End If
    'Si séparateur de décimales
    Else
        If intPosSepDec > 0 And gctlTextBox.SelStart >= intPosSepDec Then
            If Len(gctlTextBox.Text) - intPosSepDec >= mbytNumericDecimal Then GoTo Invalide
        Else
            If Len(gctlTextBox.Text) - Len(Mid$(gctlTextBox.Text, intPosSepDec)) - IIf(blnNegatif, 1, 0) >= mbytNumericLongueur Then
                If Not (Chr$(KeyAscii) = ".") Then GoTo Invalide
            End If
        End If
    End If
     
    Exit Sub
     
Invalide:
    KeyAscii = 0
    Beep
End Sub


Then, on the form, place a textbox (without changing any properties) and copy this code:

Option Explicit

Private MyNumericTextBox As clsNumeric

Private Sub Form_Load()
    Text1.Text = "" 
    Set MyNumericTextBox = New clsNumeric
    With MyNumericTextBox
        Set .gctlTextBox = Text1
        .InitChampNombre 5, 2
    End With
End Sub


0
seeshelleAuthor Commented:
I think you're getting to what I want. Let me show you what I have and see if you can throw an example my way using the validate event. It appears to be what I am looking for.

Private Sub txtChkSi_KeyPress(KeyAscii As Integer)
    cValid = "0123456789."
     If InStr(cValid, Chr(KeyAscii)) = 0 _
        And KeyAscii <> 32 Then
            KeyAscii = 0
    End If

thanks!
0
Big Business Goals? Which KPIs Will Help You

The most successful MSPs rely on metrics – known as key performance indicators (KPIs) – for making informed decisions that help their businesses thrive, rather than just survive. This eBook provides an overview of the most important KPIs used by top MSPs.

seeshelleAuthor Commented:
I meant that last remark for tirupur_selva.
emoreau - I can't even read most of yours. Sorry!

0
Éric MoreauSenior .Net ConsultantCommented:
Why don't change your code this way:

Private Sub txtChkSi_KeyPress(KeyAscii As Integer)
    cValid = "0123456789."
     If InStr(cValid, Chr(KeyAscii)) = 0 _
        And KeyAscii <> 32 Then
            KeyAscii = 0
    End If

    if chr(keyascii) = "." and (instr(txtchksi.text,".") > 0 ) then
       keyascii = 0
    end if
end sub
0
seeshelleAuthor Commented:
That didn't work emoreau. It still let there be more than one (.)
0
vbWayneCommented:
'here's one solution

Option Explicit

Public iOneTime As Integer


Private Sub Text1_KeyPress(KeyAscii As Integer)
If IsNumeric(Chr(KeyAscii)) Or KeyAscii = 46 Then
            KeyAscii = KeyAscii
       If KeyAscii = 46 Then
                 iOneTime = iOneTime + 1
         If iOneTime > 1 And KeyAscii = 46 Then
         KeyAscii = 13
        End If
             End If

    Else
        KeyAscii = 13
       
    End If
End Sub
0
seeshelleAuthor Commented:
this one only lets me have the decimal point in the first position!!
0
alokanantCommented:
Hi seeshelle,

Try the following code on a form, I think it does the job. Note that
1. it won't allow decimal in the first position. fractions have to start with 0
2. +/- can be placed only in the first position.

Private Function CheckForNumber(ByVal KeyAscii As Integer) As Integer
    Dim strValid As String
    Dim intDecPos As Integer
   
    strValid = "-+.0123456789" + Chr(vbKeyBack)
    If InStr(strValid, Chr(KeyAscii)) <= 0 Then
        CheckForNumber = 0
        Exit Function
    End If
    If InStr("+-", Chr(KeyAscii)) > 0 And Len(Text1) > 0 Then
        CheckForNumber = 0
        Exit Function
    End If
    intDecPos = InStr(Text1 & Chr(KeyAscii), ".")
    If intDecPos > 1 Then
        If (InStr("0123456789", Mid(Text1, intDecPos - 1, 1)) <= 0) Then
            CheckForNumber = 0
            Exit Function
        End If
    Else
        If intDecPos = 1 Then
            CheckForNumber = 0
            Exit Function
        End If
    End If
    If intDecPos > 1 Then
        intDecPos = InStr(Mid(Text1 & Chr(KeyAscii), intDecPos + 1, Len(Text1 & Chr(KeyAscii))), ".")
        If intDecPos > 0 Then
            KeyAscii = 0
        End If
    End If
        CheckForNumber = KeyAscii
End Function



Private Sub Form_Load()
    Text1 = ""
End Sub

Private Sub Text1_KeyPress(KeyAscii As Integer)
    KeyAscii = CheckForNumber(KeyAscii)
End Sub

hth
alok.
0
VBGuruCommented:
check this out.

Option Explicit
Private strValue As String
Private intCurPos As Integer  'To restore the previous cursor position if the user types in wrong value
Private blThrCode As Boolean   'To allow the manuplation only through code

Private Sub Form_Load()
'Initializations can be done in design window.
Text1 = 0
strValue = 0
intCurPos = 0
blThrCode = False
End Sub

Private Sub Text1_Change()
If blThrCode Then Exit Sub
If Text1 = "" Or Text1 = "." Then   'Allows the user to empty the text box even, he can start the number with a period
    strValue = Text1
    Exit Sub
End If
If Not IsNumeric(Text1) Then   'Check for the validity of the number entered. If wrong data detected revert back to the previous state.
    blThrCode = True
    Text1 = strValue
    Text1.SelStart = intCurPos
    blThrCode = False
    Exit Sub
End If
'Update the state when the user types in the right data.
intCurPos = Text1.SelStart
strValue = Text1
End Sub

Private Sub Text1_KeyPress(KeyAscii As Integer)
'Allow only numeric characters and backspace and del key to be used.
If Not (KeyAscii >= vbKey0 And KeyAscii <= vbKey9) And KeyAscii <> vbKeyBack And KeyAscii <> 46 Then
    KeyAscii = 0
End If
End Sub
0
James_stillmanCommented:
This might be a little simpler than using a class and plus it lets you delete a decimal point and then re-enter the decimal point. If you want to reset the textBox you will have to make blDecimal Global to the form and reset it's value to false once the textbox is cleared.

Private Sub Text1_KeyPress(KeyAscii As Integer)
Static blDecimal As Boolean
Dim cValid As String
cValid = "0123456789"
If InStr(cValid, Chr(KeyAscii)) = 0 _
    And KeyAscii <> 32 And KeyAscii <> 8 Then
        If KeyAscii = 46 And blDecimal = False Then  'Check to see if the flag is set to true
            blDecimal = True
        Else
            KeyAscii = 0
        End If
Else
    If Len(Text1.Text) > 0 Then _
    If KeyAscii = 8 And blDecimal = True And Asc(Mid(Text1.Text, Len(Text1.Text))) = 46 Then blDecimal = False
End If
End Sub



'The extra check for char (8) is to look for the delete key Because your users may want to delete the decimal point they have inserted you can delete this if you wish.


I've tested this and it works.

Hope this is of some help

Cheers

James
0
James_stillmanCommented:
Sorry I meant to post that as an Ansewer.
0
caraf_gCommented:
Check out my SmartBox example.

http://homepage.eircom.net/~carafa/VBSamples/VB6/SmartBox.zip

Create a new folder and extract the contents into this new folder. Open Group1.zip

The example is coded so the SmartBox does not allow the letter "A" to be typed. You want to check for numeric values. Simply change the SmartBox1_CheckValue procedure in Project1 as follows:

Private Sub SmartBox1_CheckValue(ByVal strValue As String, blnValid As Boolean)

blnValid = ((strValue = "") Or IsNumeric(strValue))

End Sub
0
VBGuruCommented:
James_stillman, thats a good piece of code. Only problem I see is that, if the user copy and paste some data, it won't take care of validating the data and it allows spaces is that required?
0
amebaCommented:
seeshelle wrote:
>it allows for multiple decimal points and this throws out an error
I think you have problem with handling errors, not with input.

My suggestion:
Use simple filtering of keyboard input.
Use Change event or LostFocus event to check values - if value does not pass your validation test (e.g. it is not numeric, or number is too big), then you can warn the user and in your formula result field put message:
"error city", "N/A", "Value 1???"
You will find this aproach is more user friendly:
- e.g. user can paste numeric value "1,000,000.00" from other documents

This is what I use for filtering in my cwNumeric and cwCurrency class (similar to emoreau's clsNumeric)

Private Sub TextBox_KeyPress(KeyAscii As Integer)
    ' filter keyboard input:
    ' allow control characters, digits, few symbols and letters DE
    If KeyAscii > 32 And Not (Chr(KeyAscii) Like "[()+,-.0123456789DdEe]") Then
        KeyAscii = 0
        Beep
    End If
End Sub

------------------------------------------------------
If you don't like this (being user friendly), but you prefer being 'restrictive', maybe you can use something like MS uses for entering time:
[  ]:[  ]÷
textbox, label, textbox, scrollbar/updown

[       ].[  ]÷
4 controls, but to users it looks like *one* textbox
[        .    ÷]

Thanks for reading :)
0
vbWayneCommented:
the code I gave allows you only one decimal point IN ANY POSITION...

vbWayne
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
caraf_gCommented:
..and the SmartBox allows you to very quickly and easily implement any input validation you could think of.
0
seeshelleAuthor Commented:
I must have done something wrong the first time I tried it...sorry.
I was wondering, would it be real tough to add backspace to this???
0
caraf_gCommented:
seeshelle.... have you actually tried the SmartBox example I posted? It has ALL this stuff already built in ready for you to use...
0
vbWayneCommented:
shouldn't be a problem..If IsNumeric(Chr(KeyAscii)) Or KeyAscii = 46 or keyascii = [backspace asciicode] Then

I don't know the ascii character for backspace off hand but go to your msdn disk and look up ascii charts. then use the number in place or [backspace ascii code]
no brackets.

that should do it.

Wayne

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic Classic

From novice to tech pro — start learning today.