Link to home
Start Free TrialLog in
Avatar of Altaf Patni
Altaf PatniFlag for India

asked on

valid keyascii after numeric char

value from text18.text is
18.5x2.75
3.50X3.50
1.75X10.25

how can i fix only one x ( it doesn't matter lower x or upper X ) but only one after number (like i mentioned above)

please check attached code


Private Sub Text18_KeyPress(KeyAscii As Integer)
'    MsgBox KeyAscii
'    KeyAscii = Asc(UCase$(Chr$(KeyAscii)))
    Call Check_Numeric_Multiply(KeyAscii)
    If KeyAscii = 13 Then KeyAscii = 0
    
End Sub


Public Sub Check_Numeric_Multiply(ByRef code As Integer)
    Select Case code
        Case 13
        Case 120, 88   ' This is a x and X
        Case 48 To 57  ' This is a digit.
        Case Else      ' Reject any other key.
        
             code = 0  ' Reject any other key.
    End Select
End Sub

Open in new window

Avatar of Mike McCracken
Mike McCracken

I assume this code is part of a form.

Add a form variable
Dim HasX as Boolean

Private Sub Text18_KeyPress(KeyAscii As Integer)
'    MsgBox KeyAscii
'    KeyAscii = Asc(UCase$(Chr$(KeyAscii)))
    If (KeyAscii = 88 OR KeyAscii = 120)  AND HasX then
        KeyAscii = 0
    Else
        HasX = True
    EndIf
       
    Call Check_Numeric_Multiply(KeyAscii)
    If KeyAscii = 13 Then KeyAscii = 0
   
End Sub

mlmcc
How about?

        Case 120, 88   ' This is a x and X
            If Not IsNumeric(Text18.Text) Then
                code = 0
            End If
Use the Split() function with text comparison parameter (non-case-sensitive comparison)

This will result in an array (actually a vector).

example:
Text18.Text = "18.5x2.75"

Private Sub Text18_LostFocus()
  Dim strParsed() As String
  strParsed = Split(Text18.Text, "x", vbTextCompare)
  Debug.Print "First Number: " & strParsed(0)
  Debug.Print "Second Number: " & strParsed(1)
End Sub

Open in new window

Note that you do not allow the decimal point (ASCII 46) to be typed in.

A full, final validation could be
Function Validate(strText As String) As Boolean
    Dim strNumbers() As String
    
    strNumbers = Split(Replace(strText, "x", "X"), "X")
    If UBound(strNumbers) = 1 Then
       If IsNumeric(strNumbers(0)) Then
           If IsNumeric(strNumbers(1)) Then
               Validate = True
           End If
       End If
    End If
End Function

Open in new window

Avatar of Altaf Patni

ASKER

i want only one x or X between  number
if user press x or X before first number, then keyascci = 0 but after first number only one x or X allow if another x or X pressed then keyascii = 0
after second number any key not allowed  keyascci = 0
so how can i do this

might these numbers be negative, or are they always positive?
always positive
Since all new (KeyAscii) characters will be placed at a specific location in a textbox (upon exit from the KeyPress event), we have to use the SetStart property to mimic a post-exit textbox string for our validation.

This should be close to what you need.
Private Sub Text18_KeyPress(KeyAscii As Integer)
    Dim strParsed() As String
    Dim strPostKeyValue As String
    If SelStart = 0 Then
        strPostKeyValue = Chr(KeyAscii) & Text18.Text
    Else
        strPostKeyValue = Left$(Text18.Text, Text18.SelStart) & Chr(KeyAscii) & Mid$(Text18.Text, SelStart + 1)
    End If
    strParsed = Split(strPostKeyValue, "x", , vbTextCompare)
    If (UBound(strParsed) >= 0) And (UBound(strParsed) < 2) Then
        If IsNumeric(strParsed(LBound(strParsed))) And (IsNumeric(strParsed(UBound(strParsed))) Or Len(strParsed(UBound(strParsed))) = 0) Then
        Else
            KeyAscii = 0
        End If
    Else
        If IsNumeric(Chr(KeyAscii)) Then
        Else
            KeyAscii = 0
        End If
    End If

End Sub

Open in new window

your floating point numbers will need to start with a digit, not a decimal point.
You might also package the code for use with other textbox controls.

Example:
Private Sub Text18_KeyPress(KeyAscii As Integer)
    If KeyIsValid(Text18, KeyAscii) Then
    Else
        KeyAscii =  0
    End If

End Sub

Public Function KeyIsValid(parmTxtBox As TextBox, parmKeyAscii As Integer) As Boolean
    Dim strParsed() As String
    Dim strPostKeyValue As String
    If SelStart = 0 Then
        strPostKeyValue = Chr(parmKeyAscii) & parmTxtBox.Text
    Else
        strPostKeyValue = Left$(parmTxtBox.Text, parmTxtBox.SelStart) & Chr(parmKeyAscii) & Mid$(parmTxtBox.Text, SelStart + 1)
    End If
    strParsed = Split(strPostKeyValue, "x", , vbTextCompare)
    KeyIsValid =  True
    If (UBound(strParsed) >= 0) And (UBound(strParsed) < 2) Then
        If IsNumeric(strParsed(LBound(strParsed))) And (IsNumeric(strParsed(UBound(strParsed))) Or Len(strParsed(UBound(strParsed))) = 0) Then
        Else
            KeyIsValid = False
        End If
    Else
        If IsNumeric(Chr(KeyAscii)) Then
        Else
            KeyIsValid = False
        End If
    End If
End Sub

Open in new window

Try this code

mlmcc
If (KeyAscii = 88 Or KeyAscii = 120) And HasX Then
        KeyAscii = 0
    ElseIf (KeyAscii = 88 Or KeyAscii = 120) And HasNum Then
        HasX = True
        HasNum = False
        HasDecimal = False
    ElseIf (KeyAscii = 88 Or KeyAscii = 120) Then
        KeyAscii = 0
    ElseIf KeyAscii >= 48 And KeyAscii <= 57 Then
        HasNum = True
    ElseIf KeyAscii = Asc(".") And HasDecimal Then
        KeyAscii = 0
    ElseIf KeyAscii = Asc(".") Then
        HasDecimal = True
    Else
        KeyAscii = 0
    End If

Open in new window

This one ensures format has a digit before and after the decimal

mlmcc
If (KeyAscii = 88 Or KeyAscii = 120) And HasX Then
        KeyAscii = 0
    ElseIf (KeyAscii = 88 Or KeyAscii = 120) And HasNum Then
        HasX = True
        HasNum = False
        HasDecimal = False
    ElseIf (KeyAscii = 88 Or KeyAscii = 120) Then
        KeyAscii = 0
    ElseIf KeyAscii >= 48 And KeyAscii <= 57 Then
        HasNum = True
    ElseIf KeyAscii = Asc(".") And HasDecimal Then
        KeyAscii = 0
    ElseIf KeyAscii = Asc(".") And HasNum Then
        HasDecimal = True
        HasNum = False
    Else
        KeyAscii = 0
    End If

Open in new window


@ aikimark: tried your code , but i can not pressed x or X after first number.

@ mlmcc: tried your code , but also i can not pressed x or X after first number.
I added this to the form load

   HasX = False
   HasNum = False
   HasDecimal = False

It works on my machine

mlmcc


>>i can not pressed x or X after first number.

This works for me.  What does your textbox look like before you press the X key?

Where is the cursor?
@ mlmcc  
 
Private Sub Text18_KeyPress(KeyAscii As Integer)
    
Dim HasX, HasNum, HasDecimal As Boolean
HasX = False
   HasNum = False
   HasDecimal = False

If (KeyAscii = 88 Or KeyAscii = 120) And HasX Then
        KeyAscii = 0
    ElseIf (KeyAscii = 88 Or KeyAscii = 120) And HasNum Then
        HasX = True
        HasNum = False
        HasDecimal = False
    ElseIf (KeyAscii = 88 Or KeyAscii = 120) Then
        KeyAscii = 0
    ElseIf KeyAscii >= 48 And KeyAscii <= 57 Then
        HasNum = True
    ElseIf KeyAscii = Asc(".") And HasDecimal Then
        KeyAscii = 0
    ElseIf KeyAscii = Asc(".") And HasNum Then
        HasDecimal = True
        HasNum = False
    Else
        KeyAscii = 0
    End If
End Sub

Open in new window


@ aikimark:
after 153 i pressed X but it wont, on debug i found that here
strPostKeyValue is "X153"
is all the text in the textbox selected?
I see the problem.  I was working entirely in code (formless) and had created a SelStart variable.  I failed to change it when I posted it.  It should be the SelStart property of the textbox.

Private Sub Text18_KeyPress(KeyAscii As Integer)
    Dim strParsed() As String
    Dim strPostKeyValue As String
    If Text18.SelStart = 0 Then
        strPostKeyValue = Chr(KeyAscii) & Text18.Text
    Else
        strPostKeyValue = Left$(Text18.Text, Text18.SelStart) & Chr(KeyAscii) & Mid$(Text18.Text, SelStart + 1)
    End If
    strParsed = Split(strPostKeyValue, "x", , vbTextCompare)
    If (UBound(strParsed) >= 0) And (UBound(strParsed) < 2) Then
        If IsNumeric(strParsed(LBound(strParsed))) And (IsNumeric(strParsed(UBound(strParsed))) Or Len(strParsed(UBound(strParsed))) = 0) Then
        Else
            KeyAscii = 0
        End If
    Else
        If IsNumeric(Chr(KeyAscii)) Then
        Else
            KeyAscii = 0
        End If
    End If

End Sub

Open in new window


Likewise, the packaged code must be changed as well.
Private Sub Text18_KeyPress(KeyAscii As Integer)
    If KeyIsValid(Text18, KeyAscii) Then
    Else
        KeyAscii =  0
    End If

End Sub

Public Function KeyIsValid(parmTxtBox As TextBox, parmKeyAscii As Integer) As Boolean
    Dim strParsed() As String
    Dim strPostKeyValue As String
    If parmTxtBox.SelStart = 0 Then
        strPostKeyValue = Chr(parmKeyAscii) & parmTxtBox.Text
    Else
        strPostKeyValue = Left$(parmTxtBox.Text, parmTxtBox.SelStart) & Chr(parmKeyAscii) & Mid$(parmTxtBox.Text, SelStart + 1)
    End If
    strParsed = Split(strPostKeyValue, "x", , vbTextCompare)
    KeyIsValid =  True
    If (UBound(strParsed) >= 0) And (UBound(strParsed) < 2) Then
        If IsNumeric(strParsed(LBound(strParsed))) And (IsNumeric(strParsed(UBound(strParsed))) Or Len(strParsed(UBound(strParsed))) = 0) Then
        Else
            KeyIsValid = False
        End If
    Else
        If IsNumeric(Chr(KeyAscii)) Then
        Else
            KeyIsValid = False
        End If
    End If
End Sub

Open in new window


========================
The fact that the code didn't give you a compile error indicates that you lack an
Option Explicit
statement in your General Declarations section.
In my code
Form Code
Dim HasX, HasNum, HasDecimal As Boolean

Sub Form1_Load()
   HasX = False
   HasNum = False
   HasDecimal = False
End Sub

Private Sub Text18_KeyPress(KeyAscii As Integer)
    If (KeyAscii = 88 Or KeyAscii = 120) And HasX Then
        KeyAscii = 0
    ElseIf (KeyAscii = 88 Or KeyAscii = 120) And HasNum Then
        HasX = True
        HasNum = False
        HasDecimal = False
    ElseIf (KeyAscii = 88 Or KeyAscii = 120) Then
        KeyAscii = 0
    ElseIf KeyAscii >= 48 And KeyAscii <= 57 Then
        HasNum = True
    ElseIf KeyAscii = Asc(".") And HasDecimal Then
        KeyAscii = 0
    ElseIf KeyAscii = Asc(".") And HasNum Then
        HasDecimal = True
        HasNum = False
    Else
        KeyAscii = 0
    End If
End Sub

@aikimark
compile error
Variable not defined

Highlighted on
SelStart
& Mid$(Text18.Text, SelStart + 1)
ASKER CERTIFIED SOLUTION
Avatar of aikimark
aikimark
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
@ aikimark : Thanks aikimark, your code is working

@ mlmcc : your code is also working mlmcc, but when user make mistake than need to be reload form,
like by mistake if user removed x or decimal point then need to be reload form.
my code should facilitate the insertion of digits as well as the insertion of an x between two numbers as long as the number on the right of the X is an integer