Check TextBoxes in Userform to make sure that they are integers - vba

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

Related

VBA check if all userform comboboxes have an option selected

I have a userform with many comboboxes and an "Ok" button. What I need is that when pressing that "Ok" button, VBA to check if there's no empty comboboxes. If all comboboxes have some value selected - close the userform otherwise return a message box and clicking "Ok" on that messagebox returns me to the userform with no filled values lost.
I've tried all the methods I could think of:
If PackageOuterRadius = null Then
if PackageOuterRadius is nothing Then
If PackageOuterRadius.value = 0 Then
If IsNull(PackageOuterRadius) = True Then
If IsNull(PackageOuterRadius.value) Then
What I've been trying to do is:
Private Sub Rigid_Filme_Ok_Button_Click()
If PackageOuterRadius.ListCount = 0 Then
MsgBox "Select a ""Package Outer Radius!"
End If
And absolutelly nothing actually checks if the combobox is empty and keeps returning a positive (That there's a value selected)
What could be the solution to this problem? Could someone, please, help me?
If you have few ComboBoxes only, you may insert lines underneath the OK button to check if all the ComboBoxes are filled but if you have too many ComboBoxes on UserForm, you may achieve this with the help of a Class Module and to do so, follow these steps...
Insert a Class Module and rename it to clsUserForm and the place the following code on Class Module...
Code for Class Module:
Public WithEvents mCMB As msforms.ComboBox
Public Sub CheckComboBoxes()
Dim cCtl As msforms.Control
Dim cntCBX As Long
Dim cnt As Long
For Each cCtl In frmMyUserForm.Controls
If TypeName(cCtl) = "ComboBox" Then
cntCBX = cntCBX + 1
If cCtl.Value <> "" Then
cnt = cnt + 1
End If
End If
Next cCtl
If cnt = cntCBX Then
Unload frmMyUserForm
Else
MsgBox "All the ComboBoxes are mandatory.", vbExclamation
End If
End Sub
Then place the following code on UserForm Module. The code assumes that the name of the userForm is frmMyUserForm and the name of the CommandButton is cmdOK.
Code for UserForm Module:
Dim GroupCBX() As New clsUserForm
Dim frm As New clsUserForm
Private Sub cmdOK_Click()
frm.CheckComboBoxes
End Sub
Private Sub UserForm_Initialize()
Dim i As Long
Dim ctl As Control
For Each ctl In Me.Controls
If TypeName(ctl) = "ComboBox" Then
i = i + 1
ReDim Preserve GroupCBX(1 To i)
Set GroupCBX(i).mCMB = ctl
End If
Next ctl
End Sub
And you will be good to go.

How to prevent sharepoint file checkin from triggering workbook before close?

My sub Workbook_BeforeClose runs twice, because in my Sub CloseWBFromSharePointFolder, I either check in my file, discard it or cancel and do nothing (see code below). Both the check in and the discarding of the file trigger Workbook_BeforeClose to run again.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
CloseWBFromSharePointFolder
End Sub
Both snippets from CloseWBFromSharePointFolder which trigger Workbook_BeforeClose
Check in
ActiveWorkbook.CheckIn SaveChanges:=True, Comments:="Checked-In by " & Application.Username
Discard
Application.ActiveWorkbook.CheckIn False
Any help would be appreciated.
P.s. I also tried to use a public variable to track if it runs again. This does not work because the public variable got reset. The explanation I found is because Workbook_BeforeClose calls CloseWBFromSharePointFolder, which then triggers Workbook_BeforeClose. This resets everything and the public variable becomes empty
P.s.2 for more details.
CloseWBFromSharePointFolder Code
Sub CloseWBFromSharePointFolder()
Dim myForm1 As UserForm1
Set myForm1 = UserForm1
myForm1.Caption = "Choose before closing:"
myForm1.Show
End Sub
UserForm1 Code
Dim Buttons() As New BtnClass
Private Sub UserForm_Initialize()
Dim ButtonCount As Integer
Dim ctl As Control
' Create the Button objects
ButtonCount = 0
For Each ctl In UserForm1.Controls
If TypeName(ctl) = "CommandButton" Then
'Skip the OKButton
If ctl.Name <> "OKButton" Then
ButtonCount = ButtonCount + 1
ReDim Preserve Buttons(1 To ButtonCount)
Set Buttons(ButtonCount).ButtonGroup = ctl
End If
End If
Next ctl
Me.CommandButton1.Caption = "Check in"
Me.CommandButton2.Caption = "Discard check-out"
Me.CommandButton3.Caption = "Keep checked-out"
Me.CommandButton4.Caption = "Cancel"
End Sub
BtnClass Code
Public WithEvents ButtonGroup As MsForms.CommandButton
Private Sub ButtonGroup_Click()
If UserForm1.Visible = True Then
Select Case ButtonGroup.Name
Case "CommandButton1" 'check in
CheckIn
Case "CommandButton2" 'Discard check-out
Discard
Case "CommandButton3" 'Keep checked-out
KeepCheckedOut
Case Else ' Cancel
'Do Nothing
End Select
Unload UserForm1
ElseIf UserForm2.Visible = True Then
Select Case ButtonGroup.Name
Case "CommandButton1" 'check out
CheckOut
Case "CommandButton2" 'Read only
'Do Nothing
Case Else ' Cancel
'Do Nothing
End Select
Unload UserForm2
End If
End Sub
Sub CheckIn()
If ActiveWorkbook.CanCheckIn = True Then
'Check In, Save and Close
ActiveWorkbook.CheckIn SaveChanges:=True, Comments:="Checked-In by " & Application.Username
MsgBox ("File sucessfully checked in")
Else
MsgBox ("File could not be checked in!")
End If
End Sub

How can i make a sub for a keypress event?

I'm working on an excel with macros. I have a userform with textboxes, several of them use a function for only press numbers.
Private Sub quantity1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
Select Case KeyAscii
Case Asc("0") To Asc("9")
Case Else
KeyAscii = 0
End Select
End Sub
How can i put the select case on a procedure or function
and then call it from any keypress event that i need it (in this case, quantity1 quantity2, price1 and price2, but no in buyer)?
I tried making a sub that uses the same parameters like the event e.g:
Sub Only_Numbers(ByVal KeyAscii As MSForms.ReturnInteger)
Here is a quick example that I created for you.
Let's say your userform looks like this
Now place this in a class module
Public WithEvents TextBoxEvents As MSForms.TextBox
Private Sub TextBoxEvents_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
Select Case KeyAscii
Case Asc("0") To Asc("9")
Case Else
KeyAscii = 0
End Select
End Sub
Screenshot
And place this in the userform
Dim myTBs() As New Class1
Private Sub UserForm_Initialize()
Dim i As Integer, objControl As Control
For Each objControl In Me.Controls
If TypeOf objControl Is MSForms.TextBox Then
i = i + 1
ReDim Preserve myTBs(1 To i)
Set myTBs(i).TextBoxEvents = objControl
End If
Next objControl
Set objControl = Nothing
End Sub
Screenshot
Now try entering text/numbers in any of the textboxes :)
EDIT
#SiddharthRout Wow! Awesome Reply! it's almost like that, but i require that certain textboxes (not all) on the userform could have this restriction. I guess that if i do this Set myTBs(i).TextBoxEvents = quantity1 (Considering that quantity1 is a textbox) should work? – fjatp 6 mins ago
If TypeOf objControl Is MSForms.TextBox Then
Select Case objControl.Name
Case "TextBox1", "TextBox3", "TextBox4" '<~~ Include only these
i = i + 1
ReDim Preserve myTBs(1 To i)
Set myTBs(i).TextBoxEvents = objControl
End Select
End If

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

Close UserForm if All Data Captured

Say you have aUserForm with TextBox1, TextBox3, TextBox3 and an OK Button.
To only allow the UserForm to close if all three TextBox have data I would use the following script assigned to the OK Button:
Private Sub CommandButton1_Click()
If Len(TextBox1.Value) >= 1 And _
Len(TextBox2.Value) >= 1 And _
Len(TextBox3.Value) >= 1 Then
Me.Hide
Else
MsgBox "Please Complete All Fields!"
End If
End Sub
Is there another way to do this besides an If statement?
Direct User Before Errors Are Made
Preferable to informing a user after an invalid action has been made is to prevent the user from performing that invalid action in the first place[1]. One way to do this is to use the Textbox_AfterUpdate event to call a shared validation routine that controls the Enabled property of your OK button, and also controls the display of a status label. The result is a more informative interface that only allows valid actions, thereby limiting the nuisance of msgbox popups. Here's some example code and screenshots.
Private Sub TextBox1_AfterUpdate()
RunValidation
End Sub
Private Sub TextBox2_AfterUpdate()
RunValidation
End Sub
Private Sub TextBox3_AfterUpdate()
RunValidation
End Sub
Private Sub RunValidation()
If Len(TextBox1.Value) = 0 Or Len(TextBox2.Value) = 0 Or Len(TextBox3.Value) = 0 Then
CommandButton1.Enabled = False
Label1.Visible = True
Else
CommandButton1.Enabled = True
Label1.Visible = False
End If
End Sub
Private Sub CommandButton1_Click()
Me.Hide
End Sub
The If Statement
As far as the If statement is concerned, there are a ton of ways that can be done, but I think anything other than directly evaluating TextBox.Value leads to unnecessary plumbing and code complexity, so I think it's hard to argue for anything other than the If statement in the OP. That being said, this particular If statement can be slightly condensed by capitalizing on its numeric nature, which allows for
Len(TextBox1.Value) = 0 Or Len(TextBox2.Value) = 0 Or Len(TextBox3.Value) = 0
to be replaced with
Len(TextBox1.Value) * Len(TextBox2.Value) * Len(TextBox3.Value) = 0
Although that doesn't gain you much and is arguably less readable code, it does allow for a condensed one liner, especially if the textboxes are renamed...
If Len(TB1.Value) * Len(TB2.Value) * Len(TB3.Value) = 0 Then
.Value vs .Text
Lastly, in this case, I think .Value should be used instead of .Text. .Text is more suited for validating a textbox entry while its being typed, but in this case, you're looking to validate a textbox's saved data, which is what you get from .Value.
More User feedback - Colorization
I almost forgot, I wanted to include this example of how to include even more user feedback. There is a balance between providing useful feedback and overwhelming with too much. This is especially true if the overall form is complicated, or if the intended user has preferences, but color indication for key fields is usually beneficial. A lot of applications may present the form without color at first and then colorize it if the user is having trouble.
Private InvalidColor
Private ValidColor
Private Sub UserForm_Initialize()
InvalidColor = RGB(255, 180, 180)
ValidColor = RGB(180, 255, 180)
TextBox1.BackColor = InvalidColor
TextBox2.BackColor = InvalidColor
TextBox3.BackColor = InvalidColor
End Sub
Private Sub TextBox1_AfterUpdate()
RunValidation Me.ActiveControl
End Sub
Private Sub TextBox2_AfterUpdate()
RunValidation Me.ActiveControl
End Sub
Private Sub TextBox3_AfterUpdate()
RunValidation Me.ActiveControl
End Sub
Private Sub RunValidation(ByRef tb As MSForms.TextBox)
If Len(tb.Value) > 0 Then
tb.BackColor = ValidColor
Else
tb.BackColor = InvalidColor
End If
If Len(TextBox1.Value) * Len(TextBox2.Value) * Len(TextBox3.Value) = 0 Then
CommandButton1.Enabled = False
Label1.Visible = True
Else
CommandButton1.Enabled = True
Label1.Visible = False
End If
End Sub
Private Sub CommandButton1_Click()
Me.Hide
End Sub
As I said in my comment, that is an ok way to do it. But i'll post this just so you have an example of another way. This would allow you to evaluate what is going into the text boxes as they are set.
Option Explicit
Dim bBox1Value As Boolean
Dim bBox2Value As Boolean
Dim bBox3Value As Boolean
Private Sub TextBox1_Change()
If Trim(TextBox1.Text) <> "" Then
bBox1Value = True
End If
End Sub
Private Sub TextBox2_Change()
If Trim(TextBox2.Text) <> "" Then
bBox2Value = True
End If
End Sub
Private Sub TextBox3_Change()
If Trim(TextBox3.Text) <> "" Then
bBox3Value = True
End If
End Sub
Private Sub CommandButton1_Click()
If bBox1Value = True And bBox2Value = True And bBox3Value = True Then
Me.Hide
Else
MsgBox "Please Complete All Fields!"
End If
End Sub
You can use a loop:
Private Sub CommandButton1_Click()
Dim n as long
For n = 1 to 3
If Len(Trim(Me.Controls("TextBox" & n).Value)) = 0 Then
MsgBox "Please Complete All Fields!"
Exit Sub
End If
Next n
Me.Hide
End Sub
You can use the below code
Private Sub CommandButton1_Click()
If Trim(TextBox1.Value & vbNullString) = vbNullString And _
Trim(TextBox2.Value & vbNullString) = vbNullString And _
Trim(TextBox3.Value & vbNullString) = vbNullString Then
Me.Hide
Else
MsgBox "Please Complete All Fields!"
End If
End Sub
I got the answer from this question
VBA to verify if text exists in a textbox, then check if date is in the correct format