Preventing debugger when value is deleted from VBA textbox - vba

My user form has several textbox's that can be edited by the user but it was reported to me that it was debugging. After a bit of investigation i found that the user was deleting the value out of the text box and this was causing a run-time error 13. How do i stop the run-time error if the user deletes the value and the servcredit textbox becomes a vbnullstring?
at present the text box has the 2 below pieces of code.
This inputs the numerical value into the excel sheets in the back.
Private Sub ServCredit_Change()
Worksheets("Calculator").Range("L18") = CDec(ServCredit)
End Sub
This ensure the user doesn't input a none numerical figure.
Private Sub ServCredit_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If (KeyAscii > 47 And KeyAscii < 58) Or KeyAscii = 46 Or KeyAscii = 32 Then
KeyAscii = KeyAscii
Else
KeyAscii = 0
MsgBox "Invalid Key Pressed"
End If
End Sub

You could simply test if there is a value:
Private Sub ServCredit_Change()
If Len(ServCredit.Text) <> 0 then
Worksheets("Calculator").Range("L18").Value2 = CDec(ServCredit)
Else
Worksheets("Calculator").Range("L18").Value2 = vbnullstring
end if
End Sub

You first need to check if ServCredit is numeric. CDec cannot cast a vbNullString into a number.
If IsNumeric(ServCredit) then
Worksheets("Calculator").Range("L18") = CDec(ServCredit)
else
Worksheets("Calculator").Range("L18") = 0
End If

Related

How do I check if a value a user is entering in Textbox is a numeric double?

I am trying to check if a user enters a number value in a textbox, decimal places accepted. Any help is highly appreciated.
Private Sub textbox1_AfterUpdate()
If IsNumeric(textbox1.Value) = False Then
Me!textbox1.Undo
MsgBox "only numbers are allowed"
Exit Sub
End If
Exit Sub
using BeforeUpdate event:
Private Sub textbox1_BeforeUpdate(Cancel As Integer)
If IsNumeric(textbox1.Value) = False Then
MsgBox "only numbers are allowed"
Me!textbox1.Undo
Cancel = True
Exit Sub
End If
Exit Sub
My current code does not execute at all. I have also tried it in the textbox1_BeforeUpdate event. Please see code.
New Code:
Public Function IsValidKeyAscii(ByVal keyAscii As Integer, ByVal value As
String) As Boolean
IsValidKeyAscii = (keyAscii = vbKeyDot And InStr(1, value, Chr$(vbKeyDot)) =
0) Or (keyAscii >= vbKey0 And keyAscii <= vbKey9)
End Function
Private Sub textbox1_KeyDown(KeyCode As Integer, Shift As Integer)
If Not IsValidKeyAscii(KeyCode, textbox1.value) Then KeyCode = 0
End Sub
You shouldn't be using VBA for this task at all.
Just set the field format property to General number. That's the built-in way to ensure users can only enter numbers in a field.
Write a validator function (could be in its own KeyInputValidator class or module), so you can reuse this logic everywhere you need it, instead of copy/pasting it for every numeric textbox you need:
Option Explicit
Private Const vbKeyDot As Integer = 46
'#Description("returns true if specified keyAscii is a number, or if it's a dot and value doesn't already contain one")
Public Function IsValidKeyAscii(ByVal keyAscii As Integer, ByVal value As String) As Boolean
IsValidKeyAscii = (keyAscii = vbKeyDot And InStr(1, value, Chr$(vbKeyDot)) = 0) Or (keyAscii >= vbKey0 And keyAscii <= vbKey9)
End Function
Then use it in the textboxes' KeyPress event handler (assuming this is a MSForms textbox control) to determine whether or not to accept the input - since the event provides a MSForms.ReturnInteger object, that object's Value property can be set to 0 to "swallow" a keypress:
Private Sub TextBox1_KeyPress(ByVal keyAscii As MSForms.ReturnInteger)
If Not IsValidKeyAscii(keyAscii.Value, TextBox1.value) Then keyAscii.Value = 0
End Sub
That way you don't need to undo any inputs, or pop any annoying warning or message boxes: the value in the field is guaranteed to be a valid numeric value!
EDIT the above event handler signature is for a MSForms control. Looks like Access uses a different interface:
Private Sub TextBox1_KeyDown(KeyCode As Integer, Shift As Integer)
Here the KeyCode is passed ByRef, so you can alter it directly. In other words, this becomes the logic:
If Not IsValidKeyAscii(KeyCode, TextBox1.value) Then KeyCode = 0
You can try using the lost focus event:
Private Sub TextBox1_LostFocus()
Dim blnNumber As Boolean
Dim strNumber As String
strNumber = TextBox1.Value
blnNumber = IsNumeric(strNumber)
If Not blnNumber Then
Me!TextBox1.Undo
MsgBox "only numbers are allowed"
Else
'And, if you want to force a decimal.
If InStr(strNumber, ".") < 1 Then
Me!TextBox1.Undo
MsgBox "only doubles are allowed"
End If
End If
End Sub
Also, check the Textbox1 element that you have listed in access. Is it's name TextBox1? or something else?
For example, in excel it is represented like the following: =EMBED("Forms.TextBox.1","") even though the name that the code references is TextBox1.

VBA UserForm TextBox Only Allow Numbers and Empty Text

In my userform I want to MsgBox if TextBox not contain Numbers or empty.
This is my code but in another case when the TextBox = "" Empty the MsgBox appear to me, so the issue with me is the empty TextBox.
Private Sub TB1_Change()
If TypeName(Me.TB1) = "TextBox" Then
With Me.ActiveControl
L12.Caption = Val(TB1.Text) * Val(TB2.Text)
If Not IsNumeric(.Value) And .Value <> vbNullString Then
MsgBox "Sorry, only numbers allowed"
.Value = vbNullString
End If
End With
End If
End Sub
Use the Key Press event for this purpose.
Private Sub TB1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If Not IsNumeric(Chr(KeyAscii)) Then KeyAscii = 0
End Sub
This procedure will just ignore anything you enter if it isn't a number, but you can modify both the condition and the output. For example, you might allow a decimal point to be entered, or you might wish to show a message box - perhaps only on the second try.
You may use the AfterUpdate event handler instead of the Change event, might also want to use the Exit event and cancel the exit if the user enters an invalid value:
Option Explicit
Private Sub TB1_AfterUpdate()
'Check whether the value is numeric or empty:
If Not IsValNumeric(Me.TB1.Value) Then
MsgBox "Sorry, only numbers allowed"
Me.TB1.Value = vbNullString
Else:
'Do something...
MsgBox val(TB1.Text) * val(TB2.Text)
End If
End Sub
Private Sub TB1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
'Prevents the user from EXIT the TextBox if value is not numeric/empty
Cancel = Not IsNumeric(Me.TB1.Value)
End Sub
Private Function IsValNumeric(val$) As Boolean
Dim ret As Boolean
'check for numeric value only and allow empty value as a zero value
ret = IsNumeric(val) Or Len(val) = 0
IsValNumeric = ret
End Function
You can wait until the user finishes their input and then test the field.
For usability, the message box should be replaced with a caption and an icon/picture like this "A number must be entered here."
These would be displayed next to the text box when the input is incorrect. Then hidden when the input is corrected. The submission of the form can be blocked until all the errors have been corrected.
This allows the user to enter the request data and then fix any input errors. This is better than stopping them every time they make a mistake.
The event is changed from Change to Exit.
Private Sub TB1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If TypeName(Me.TB1) = "TextBox" Then
With Me.ActiveControl
L12.Caption = Val(TB1.Text) * Val(TB2.Text)
If Not IsNumeric(.Value) Or .Value = vbNullString Then
MsgBox "Sorry, only numbers allowed"
.Value = vbNullString
End If
End With
End If
End Sub
The vbNullString test has also been updated.
Since you are trying to allow only "Numeric" and "Blank" then the code below would deliver your needs.
Private Sub TB1_Change()
if IsNumeric(Me.TB1.Value) = True or Me.TB1.Value = vbNullString then
'Good data, nothing to MSG
Else
MsgBox "Your input data is not valid"
Endif
End Sub

Check TextBoxes in Userform to make sure that they are integers

I'm trying to check my Userform when a command button is clicked to ensure that all the values entered in textboxes are integers. However, right now it's popping up with the message box even if I enter an integer value (i.e. 1 for all the textboxes).
Here's my code right now:
'Store inputs when clicking Continue
Private Sub Continue1_Click()
'Define variables
Dim Ctl As Control
For Each Ctl In CategoriesForm.Controls
If TypeName(Ctl) = "TextBox" Then
If IsNumeric(Ctl.Value) = True Then
If Int(Ctl.Value) <> Ctl.Value Then
MsgBox ("All inputs need to be integers for calculations to work. Please check the values."), vbCritical, "Error: Not All Inputs are Integers"
Exit Sub
End If
Else
MsgBox ("All inputs need to be integers for calculations to work. Please check the values."), vbCritical, "Error: Not All Inputs are Integers"
Exit Sub
End If
End If
Next
NumberClamps = Number_Clamps.Value
NumberBrackets = Number_Brackets.Value
NumberWashers = Number_Washers.Value
NumberScrews = Number_Screws.Value
NumberNuts = Number_Nuts.Value
NumberUNuts = Number_UNuts.Value
NumberRivets = Number_Rivets.Value
NumberStuds = Number_Studs.Value
Unload CategoriesForm
End Sub
Thanks
this is a sub that only allows user to enter numeric keys
Private Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
Select Case KeyAscii
Case vbKey0 To vbKey9
Case Else
KeyAscii = 0
Beep
End Select
End Sub
In conjunction with Doug Coats Solution
Create Class Module called "CTextboxes"
Option Explicit
Public WithEvents TextGroup As MSForms.TextBox
'Sub to allow users to only enter integer values
Private Sub TextGroup_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
Select Case KeyAscii
Case vbKey0 To vbKey9
Case Else
KeyAscii = 0
Beep
MsgBox ("All inputs need to be integers for calculations to work. Please check the values."), vbCritical, "Error: All Inputs must be Integers"
End Select
End Sub
Put this code in the UserForm code module for when the USerForm initializes
Private Sub UserForm_Initialize()
'Stop user from entering non-integer values
Dim Ctl As MSForms.Control
Dim i As Long
i = 1
For Each Ctl In Me.Controls
If TypeName(Ctl) = "TextBox" Then
ReDim Preserve TextBoxes(1 To i)
Set TextBoxes(i).TextGroup = Ctl
i = i + 1
End If
Next Ctl
End Sub
Finally define this variable at the top of the UserForm Code
Option Explicit
Dim TextBoxes() As New CTextboxes

Making VBA Form TextBox accept Numbers only (including +, - and .)

I have simple textBox and I want to validate its input including "+" , "-" and "." here is what I have tried
Private Sub DisplayValue_TextBox_Change()
If Not IsNumeric(DisplayValue_TextBox.Value) Then
MsgBox "Only numbers allowed"
End If
End Sub
But this only accepts numbers 0-9 no negative, positive value or float value..
Further to my comment:
Consider a sample Userform1 with a Textbox1 and a CommandButton1
when you enter anything in the TextBox1 the change event fires - ie. typing one character fires the Change() event and passes the current value so even when you type in the negative sign your current logic fails.
What you need is to use another event like _AfterUpdate() or _Exit() with an amphasis on the second one because your can cancel the event :)
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If Not IsNumeric(TextBox1.Value) Then
MsgBox "only numbers allowed"
Cancel = True
End If
End Sub
You can find events here:
use the KeyPress event, and discard any non-numeric entry:
Private Sub txtShift1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
Debug.Print KeyAscii
If KeyAscii >= 48 And KeyAscii <= 57 Then
Debug.Print "number"
Else
Debug.Print "other"
KeyAscii = 0
End If
End Sub
Having relied up till now on string parsing to do this job, I'm glad I decided to check and see how other people do it and found this Q.
I've refined Ruben Alvarez's excellent answer. The below will allow numerical entries only, and only one decimal point.
Private Sub txtShift1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
Select Case KeyAscii
Case 46
If InStr(1, txtShift1, ".") > 0 Then KeyAscii = 0
Case 48 To 57
Case Else
KeyAscii = 0
End Select
End Sub
This could be further refined to allow only a single "+", "-" etc. as necessary.
I use this. It will allow only numbers with decimals.
Private Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
Select Case KeyAscii
Case vbKey0 To vbKey9, vbKeyBack, vbKeyClear, vbKeyDelete, _
vbKeyLeft, vbKeyRight, vbKeyUp, vbKeyDown, vbKeyTab
If KeyAscii = 46 Then If InStr(1, TextBox1.Text, ".") Then KeyAscii = 0
Case Else
KeyAscii = 0
Beep
End Select
End Sub
Im using that:
Private Sub txtGiaNet_Change()
If IsNumeric(txtGiaNet.Value) Then
//if number do sth
Else
//if not, delete this character
txtGiaNet.Value = Left(txtGiaNet.Value, Len(txtGiaNet.Value) - 1)
End If
End Sub
If TextBox1.Value <> "" Then
Dim N As Boolean
N = True
Do While N
If Not IsNumeric(TextBox1.Value) Then
TextBox1.Value = Left(TextBox1.Value, Len(TextBox1.Value) - 1)
Else
N = False
End If
Loop
End If
Private Sub TbCout_D_Edlp_Change()
Dim NotNumeric As Boolean
Dim TempValue As String
If Not IsNumeric(TbCout_D_Edlp.Value) Then
If TbCout_D_Edlp.Value <> "" Then
NotNumeric = True
MsgBox "Only numbers allowed"
TempValue = Left(Me.TbCout_D_Edlp.Value, Len(Me.TbCout_D_Edlp.Value) - 1)
While NotNumeric = True And TempValue <> ""
If Not IsNumeric(TempValue) Then
TempValue = Left(TempValue, Len(TempValue) - 1)
Else
NotNumeric = False
End If
Wend
Me.TbCout_D_Edlp.Value = TempValue
End If
End If
End Sub

Do seaching in excel on typing

I am dealing with data input. Every time before I input one record, I need to search and locate one cell in about 5000 rows. I am thinking if it is possible to do the search while typing instead of using the search function in excel. My idea is to capture the keypress event of a spreadsheet, if it is a character (letter 'A' to 'Z' or 'a' to 'z'), append it to a string called searchVal do the search immediate with a function. When the user press ESC, it will clean up the searchVal. First of all, I got the following code from online, trying to capture the ESC keydown
Private searchVal As String
Private Sub Workbook_Activate()
Application.OnKey "ESC", "CleanSearchKey"
End Sub
Private Sub Workbook_Deactivate()
Application.OnKey "ESC"
End Sub
Sub CleanSearchKey()
searchVal = ""
MsgBox "CleanSearchKey"
End Sub
But his code doesn't work, it seems that the CleanSearchKey never triggered. As for capturing the key down for 'A' to 'Z' and 'a' to 'z', I don't want know how to capture it in a sheet so I add an inputbox on sheet1, assigned the following macro to the inputbox
Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If (KeyAscii >= 65 And KeyAscii <= 90) Or (KeyAscii >= 97 And KeyAscii <= 122) Then
searchVal = searchVal & KeyAscii
Else
KeyAscii = 0
End If
End Sub
But it then said "Compile error: User-defined type not defined". So what is the right way to capture the key on a sheet? Thanks.
The code you added for a TextBox is only applicable to a TextBox which appears on a UserForm object. I don't think text boxes on worksheets respond to events like KeyPress.
That said, you could easily configure a simple userform to do this.
I modified your code a little bit. I think this should get you started. In a normal code module, do a procedure like this which will launch the UserForm. This will allow you to show the form from the Macros ribbon menu. Otherwise, you will have to invoke it manually from the Immediate Window or by pressing F5 in the VBE.
Sub ShowForm()
UserForm1.Show vbModeless
End Sub
Create a UserForm, and add a textbox. Its default name should be TextBox1, if it is not, then make sure to change it. In the userForm's code module, do this:
Option Explicit
Dim searchVal As String
Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
searchVal = TextBox1.Value
If (KeyAscii >= 65 And KeyAscii <= 90) Or (KeyAscii >= 97 And KeyAscii <= 122) Then
searchVal = searchVal & Chr(KeyAscii)
TextBox1.Value = searchVal
Call FindValue
End If
If KeyAscii = 27 Then 'ESC
searchVal = vbNullString
TextBox1.Value = vbNullString
Else:
KeyAscii = 0
End If
End Sub
Sub FindValue()
Dim rngFound as Range
With ActiveSheet
set rngFound = .Cells.Find(searchVal)
End With
If rngFound Is Nothing Then
MsgBox searchVal & " not found!"
Else
MsgBox searchVal & " found at " & rngFound.Address
End If
End Sub