userform textbox required field-accept only a pattern of numbers - excel

I need help trying to make an excel userform textbox to accept only a pattern of numbers. My pattern of numbers are 12 digits.00.4 digits or 8 digits so the textbox should only accept a number similar to 772344456566.00.0001 or 77186238.
I have searched for clues to similar issues but none give me any direction.
My current code is this but not close to my target goal:
Private Sub Textbox3_Exit(ByVal Cancel As MsForms.ReturnBoolean)
IF TextBox3.Value <>"" Or TextBox3.Value < 0 Then
MsgBox "Invalid sales order number"
TextBox3.SetFocus
End If
End Sub

Try this:
Private Sub Textbox3_Exit(ByVal Cancel As MsForms.ReturnBoolean)
If Not TextBox3.Value Like "########" Or _
Not TextBox3.Value Like "############.00.####" Then
MsgBox "Invalid sales order number"
TextBox3.SetFocus
End If
End Sub
and/or have a look at This. Basically, when used with the Like operator, # checks for any digit, so ## checks for a 2 digit number and so on.

Use the next function, please:
Function textOK(strText As String) As Boolean
If strText Like "############.00.####" Or strText Like "########" Then
textOK = True
End If
End Function
It can be used in your code in this way:
If textOK(TextBox3.Text) Then
'do whatever you need
Else
'send a warning message... or do something else.
End If
Edited:
You can test the above function in this relevant way:
Sub testTextOK()
Dim x As String
x = "123456787812.00.0014"
'x = "12345678"
'x = "123457j8"
'x = "123456789"
Debug.Print textOK(x)
'or use MsgBox and comment the above code line
MsgBox textOK(x)
End Sub
Please, un-comment from bottom to the top the x lines allocating values and see the return in Immediate Window (being in VBE: `Ctrl + G)...
Does it look now a little easier to understand how to use it?

Your code seems to be trying to reject values that are anything other than blank or negative.
Below is a selection of questions to review regarding validation of textbox forms in VBA.
Validating the format of a userform textbox entry
Validate textbox input
Making VBA Form TextBox accept Numbers only (including +, - and .)
Validating textbox entry on Userform (Excel VBA)
Userform entry validation

Firstly, check the length of the value. Then, just break the value into separate parts and check each of them. Something like this (cannot check it as on Linux now):
val = CStr(TextBox3.Value)
len_val = Len(val)
If len_val = 8 Then
If Not IsNumeric(val) Then
MsgBox "Error"
End If
ElseIf len_val = 20 Then
If (Not IsNumeric(CInt(Left(val, 12)))) Or _
Mid(val, 13, 4) <> ".00." Or _
(Not IsNumeric(CInt(Right(val, 4)))) Then
MsgBox "Error"
End If
Else
MsgBox "Error"
End If

Related

Why am I getting a type mismatch error when trying to pass a variable of type boolean into a txtBox_Exit() event?

I am messing around with userforms in Excel and have hit the first obstacle that I can't resolve either with my own offline resources, or by googling it.
I am trying to handle user input to a selection of textboxes. I have a set of events for those textboxes for the keydown event, and was happy with this until I realised that a lot of end users will try to use their mouse to navigate forms, and turning off the mouse click was a somewhat barbaric fix to the problem.
As a result, I have tried to capture the mouse click event using the keycode method of the keydown, but quickly realised that as they were technically leaving the textbox during the click, an event handling the exit of the textbox currently in use would be more elegant.
Here-in lies my problem.
Due to the two events being largely similar, I have attempted to capture the keypress, and if it is one of a set list of keys, I want to call the exit sub's code. The reason for this is simply to streamline my code. I would use a method for the execution, but there are some variations depending on the textbox.
The keypress capture works. However, the SECOND I put in the line
Call txtCurrentValue_Exit(cancel)
I get a type mismatch error with the cancel variable highlighted.
I can not for the life of me get my head around why I cannot parse a boolean value to a msforms.returnsboolean sub. I am aware this could well be due to a fundamental lack of understanding, but if someone could direct me to the correct way that would be a huge help. I am not necessarily looking for an answer, but more the thought process required to get me there.
Code in question below.
Keydown event as it currently stands:
Private Sub txtCurrentValue_KeyDown(ByVal Keycode As MSForms.ReturnInteger, ByVal Shift As Integer)
If Keycode = vbKeyTab Or Keycode = vbKeyReturn Or Keycode = vbKeyUp Or Keycode = vbKeyDown Then
Dim cancel As Boolean
cancel = False
Call txtCurrentValue_Exit(cancel)
End Sub
Exit event as it currently stands:
Private Sub txtCurrentValue_Exit(ByVal cancel As MSForms.ReturnBoolean)
'Storage variable for later calculations before punctuation added to variable value
'Checks to see if the textbox is empty after losing focus
If txtCurrentValue.TextLength > 0 Then
'If the value is not numeric, throw an error and reset the value
If IsNumeric(txtCurrentValue) = False Then
MsgBox ("Please ensure you only enter numeric values into this box.Punctuation such as £ or % signs will be added automatically.")
txtCurrentValue.Value = ""
Exit Sub
End If
'value confirmed as numeric, store in storage variable for later calculations
storedCurrentValue = txtCurrentValue.Value
'If the user has not elected to use decimal places, put a ".00" on the end of the string value for ease of reading. Also put a £ sign in front of the text.
If InStr(txtCurrentValue, ".") = False Then
txtCurrentValue.Value = txtCurrentValue + ".00"
End If
If InStr(txtCurrentValue, "£") = False Then
txtCurrentValue.Value = "£" + txtCurrentValue
End If
txtBridgeOffer.SetFocus
End If
End Sub
The variable storedCurrentValue and the method IsNumeric work in isolation.
But for validation you only need the _exit event. No keydown event needed. The exit event is called whenever the user tries to exit the textbox no matter by mouse or keyboard.
If you set Cancel = True in that event that means the exit action of the text box will be canceled and the cursor will stay in that textbox.
Option Explicit
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Dim ValidInput As Boolean
'do some validation here
If TextBox1 = "aa" Then
ValidInput = True
End If
If ValidInput = False Then
MsgBox "Only 'aa' is a valid input."
Cancel = True 'this line will cancel the exit of the textbox and the cursor will set back to that box
End If
End Sub
For example you cannot leave/exit this textbox if it does not contain aa. This is the only event you need.
Additional notes:
You were probably looking for something like this:
Option Explicit
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
With TextBox1 '<-- Your textbox name here
If .TextLength > 0 Then
If Not IsNumeric(.Value) Then
MsgBox ("Please ensure you only enter numeric values into this box.Punctuation such as £ or % signs will be added automatically.")
.Value = ""
Cancel = True
Exit Sub
End If
If InStr(.Value, ".") = 0 Then
.Value = .Value & ".00"
End If
If InStr(.Value, "£") = 0 Then
.Value = "£" & .Value
End If
End If
End With
End Sub
Note that the InStr function does not return a boolean True/False but the position of the first find. So you need to test If InStr(.Value, ".") = 0 because 0 means not found.
Also note that if you change the numeric input value eg 12 into £12.00 and then the user goes back to change it to eg £13.00 it will not be accepted as valid because it is not numeric. So you have to allow that too. Have a look how to check patterns with Regular Expressions the can be very handy for validation.
Here is an example for a RegEx Pattern to check if a text looks like £12.00.
The pattern ^£[0-9]+\.[0-9]{2}$ will match all text that …
^£ - Begins with £
[0-9]+ - followed by one or more digits of 0-9
\. - followed by a dot .
[0-9]{2}$ - end with 2 digits of 0-9

How to verify 2 variables are Integer type?

I would like to let user enter two integers (two text boxes)
While this condition is not satisfied, i want to let user fill again the text boxes.
Here is what I've tried but it's not the right answer:
Sub verif_type(n1, n2)
If TypeName(n1) = "Integer" And TypeName(n2) = "Integer" Then
MsgBox ("C'est bon !")
Else
MsgBox ("C'est pas bon, recommencez !")
Unload UserForm1
Call verif_type(n1, n2)
End If
End Sub
Thanks in advance.
Reading from a text box would most probably return a string every time. Thus, for an integer check, make sure that the number is numeric and has no , or . in it. To make sure it is a VBA integer, you may also see whether it is in the boundaries of one -32768 to 32767.
Option Explicit
Sub TestMe()
verifType InputBox("Please enter value")
End Sub
Sub verifType(n1)
If IsNumeric(n1) _
And InStr(1, n1, ",") = 0 _
And InStr(1, n1, ".") = 0 Then
Debug.Print "Numeric!"
Else
Debug.Print "Not Numeric!"
TestMe
End If
End Sub
The code above is called through TestMe() and gets only one variable (easier to write than 2). If it is not Integer then it is called again. Follow some similar logic to build up your case.
you could check for the length of the string before and after conversion to a Long:
Function IsInteger(n1 As Variant)
If IsNumeric(n1) Then IsInteger = Len(n1) = Len(CStr(CLng(n1)))
End Function
so your UserForm1 button click event code could be:
Private Sub CommandButton1_Click() ' change "CommandButton1" to your actual command button name
If IsInteger(Me.TextBox1) And IsInteger(Me.TextBox2) Then
MsgBox ("C'est bon !")
Me.Hide
Else
MsgBox ("C'est pas bon, recommencez !")
End If
End Sub
while your "main" calling code could be:
Sub main()
...
With New UserForm1
...
(possible code to pre-set UserForm1 controls to show to user)
...
.Show
...
(code to exploit UserForm1 controls values after user interaction)
...
End With
...
End Sub
First, check the contents of the textbox can be interpreted as a number using IsNumeric
Second, check that the value of those contents is equal to the rounded value of those contents
if IsNumeric(n1) then
if val(n1) = floor(val(n1)) then
' number is good, take appropriate action
else
' Inform user and take appropriate action
end if
else
'Inform user and take appropriate action
end if
From experience, I would recommend placing the validity check inside the change event on the textbox, and feed back to the user using a textbox or label containing a status message.
Your code calls itself recursively if the inputted variables are not the right type. This will create an endless loop.
Logically, any verification function should return a simple "Yes" or "No". Either it is verified or it is not. This means returning a simple Boolean - which in turn means that it should be a Function instead of a Sub.
And always use Option Explicit.
Function verif_type(n1 as Variant, n2 as Variant) as Boolean
If TypeName(n1) = "Integer" And TypeName(n2) = "Integer" Then
verif_type = True
'MsgBox ("C'est bon !")
Else
verif_type = False
'MsgBox ("C'est pas bon, recommencez !")
'Unload UserForm1
'Call verif_type(n1, n2)
End If
End Function
But that, in itself, can be further simplified as
Function verif_type(n1 as Variant, n2 as Variant) as Boolean
verif_type = TypeName(n1) = "Integer" And TypeName(n2) = "Integer"
End Function
Now all your response logic is in your main code (I assume in your UserForm).
If verif_type(a,b) then
' Do something
Else
' Do something else
End If

set value for other userform controls on userform close

really struggling with this one, found a solution for the time being but it's not really a satisfactory one.
I have a workbook with two user forms, one to input data and one to search for previously entered data and a third user form designed as a date picker form which is set to activate on entry of a designated date text box.
Individually I have no problem, the user clicks the text box and the date picker form appears, they make their selection which closes the date picker form and adds the date to the text box. On the "input data" form I have a multi page with a single date selection text box on each of the two pages, on the "find data" form I have an option to search a single date or a range, 3 date selection text boxes in total.
now I am noticing that userform1 (input data) is prompting a run time error 91 - object variable or With block variable not set and is flagging the first line for userform2 in the code whenever I select a date from the date picker form.
what I did notice however was that the correct date was still being entered into the textbox so as a fix I added an 'On error goto' line above the highlighted line which is allowing the action to take place without interruption. What I did notice was that now if I enter a date anywhere on userform2 (find data) and then close the form and decide I want to enter data instead, the text box on userform1 will contain whatever the previous selection was on userform2. What is especially puzzlng about this to me is that the initialize event for UF1 enters the current date in the date text box.
see code below, is there a much better way to write this? I hope I explained well enough, please let me know if I can provide additional details to help.
Sub CloseDatePicker(save As Boolean)
If UserForm1.MultiPage1.Value = 0 Then
UserForm1.tbDate.Text = Calendar1.Value
UserForm1.cbMember.SetFocus
ElseIf UserForm1.MultiPage1.Value = 1 Then
UserForm1.tbDate2.Text = Calendar1.Value
UserForm1.cbMember2.SetFocus
End If
On Error GoTo dpexit
If UserForm2.ActiveControl.Name = "TextBox1" Then
UserForm2.TextBox1.Text = Calendar1.Value
End If
If UserForm2.ActiveControl.Name = "TextBox2" Then
UserForm2.TextBox2.Text = Calendar1.Value
ElseIf UserForm2.ActiveControl.Name = "TextBox3" Then
UserForm2.TextBox3.Text = Calendar1.Value
End If
dpexit:
Me.Hide
End Sub
Right out the gate, the first problem I see with your code is you're trying to change the value of a text box with the .Text property. I've personally never had luck with using .Text to set value as it consitently throws Err:91. Instead I've found it's better to use .Value.
Sub CloseDatePicker(save As Boolean)
If UserForm1.MultiPage1.Value = 0 Then
UserForm1.tbDate.Value = Calendar1.Value
UserForm1.cbMember.SetFocus
ElseIf UserForm1.MultiPage1.Value = 1 Then
UserForm1.tbDate2.Value = Calendar1.Value
UserForm1.cbMember2.SetFocus
End If
' On Error GoTo dpexit 'disabled this for you to test your code
If UserForm2.ActiveControl.Name = "TextBox1" Then
UserForm2.TextBox1.Value = Calendar1.Value
End If
If UserForm2.ActiveControl.Name = "TextBox2" Then
UserForm2.TextBox2.Value = Calendar1.Value
ElseIf UserForm2.ActiveControl.Name = "TextBox3" Then
UserForm2.TextBox3.Value = Calendar1.Value
End If
dpexit:
Me.Hide
End Sub

Excel Combo Box Refresh Dropdown?

Is there a way to refresh a combobox?
I have the following VBA code. The dropdown is populated, until the If statement where the list is cleared and populated with the matched items.
At this point, the dropdown list only shows a single item with a scroll bar. But If I close the pulldown and reopen, it's fully populated correctly.
Private Sub ComboBox_SiteName_Change()
ComboBox_SiteName.DropDown
Dim v As Variant, i As Long
With Me.ComboBox_SiteName
.Value = UCase(.Value)
If .Value <> "" And .ListIndex = -1 Then
v = Worksheets("Address").Range("Table5[[#All],[SITE NAME]]").Value
.Clear ' Clear all items
' Repopulate with matched items
For i = LBound(v, 1) To UBound(v, 1)
If LCase(v(i, 1)) Like "*" & LCase(.Value) & "*" Then
.AddItem v(i, 1)
End If
Next i
Else
' Repopulate with all items
.List = Worksheets("Address").Range("Table5[[#All],[SITE NAME]]").Value
End If
End With
End Sub
The ComboBox_Change function gets called as the user types in the combo box.. the dropdown box turns from a list into a single line with Up/Down arrows after the Clear and Repopulate matched items..
but if I close the dropdown portion and reopen it lists all the items without Up/Down arrows.
The .ListRows value = 8 by the way.
I would like a way for the dropdown potion to either close and reopen.. or a VBA function to refresh the dropdown portion, Without external buttons or controls Please
Getting the list to ONLY show values that matched the text typed by the user so far, was a nightmare. Below is what I wrote which works (but took me a while!)
Note that the MacthEntry Property of the combo box MUST be set to "2 - frmMatchEntryNone" for the code to work. (Other values cause the combo box .value property store the text of the first value that matches what the user typed, and the code relies on it storing what they typed.)
Also note, the trick to get around the behaviour you observed, ie the combo boxes list of values not being sized correctly, was to use the code lines:
LastActiveCell.Activate
ComboBox_SiteName.Activate
Also, the code will pick up any items on the list that have the letters typed by the user ANYWHERE in their text.
Anyway, here's my code:
Private Sub ComboBox_SiteName_GotFocus()
' When it first gets the focus ALWAYS refresh the list
' taking into acocunt what has been typed so far by the user
RePopulateList FilterString:=Me.ComboBox_SiteName.Value
Me.ComboBox_SiteName.DropDown
End Sub
' #4 Private Sub ComboBox_SiteName_Change()
Private Sub ComboBox_SiteName_Enter()
Dim LastActiveCell As Range
On Error GoTo err_Handler
Set LastActiveCell = ActiveCell
Application.ScreenUpdating = False
With Me.ComboBox_SiteName
If .Value = "" Then
' Used cleared the combo
' Repopulate will all values
RePopulateList
.DropDown
Else
' #4 reducdant
' LastActiveCell.Select
' .Activate
' ===========================================
' #4 new code
' CheckBox1 is another control on the form
' which can receive the focus and loose it without event firing
CheckBox1.SetFocus
' This will trigger the GotFocus event handler
' which will do a refresnh of the list
.SetFocus
' ===========================================
End If
End With
Application.ScreenUpdating = True
Exit Sub
err_Handler:
Application.ScreenUpdating = True
Err.Raise Err.Number, "", Err.Description
Exit Sub
Resume
End Sub
Private Sub RePopulateList(Optional FilterString As String = "")
Dim i As Long
Dim ValidValues() As Variant
' #2 range now refers to just the data cells
ValidValues = Worksheets("Address").Range("Table5[SITE NAME]").Value
With Me.ComboBox_SiteName
If FilterString = "" Then
' All all values
.List = ValidValues
Else
' #2: .List cannot be set to have no items.
' so remove all but one
.List = Array("Dummy Value")
' Only add values that match the FilterString parameter
For i = LBound(ValidValues, 1) To UBound(ValidValues, 1)
If LCase(ValidValues(i, 1)) Like "*" & LCase(FilterString) & "*" Then
.AddItem ValidValues(i, 1)
End If
Next i
' #2 add this line to remove the dummy item
.RemoveItem (0)
End If
End With
End Sub
Private Sub ComboBox_SiteName_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Application.ScreenUpdating = False
End Sub
======================================================================
You could: Replace all your code with this which should give acceptable functionality (as long a the data source is in alpha order), and it's easy! However, it doesn't quite do what you wanted.
Private Sub ComboBox_SiteName_GotFocus()
With Me.ComboBox_SiteName
.List = Worksheets("Address").Range("Table5[[#All],[SITE NAME]]").Value
End With
ComboBox_SiteName.DropDown
End Sub
Combo boxes can be set up to "filter as the user types" - so long as the data is in alphabetical order.
======================================================================
Note that in your code the following two lines cause the ComboBox_SiteName_Change event to start again. I suspect you need to add break points and debug you code more.
.Value = UCase(.Value)
.Clear ' Clear all items
Anyway, I hope this is job done.
this will be my first bounty if I get it, so please let me know if you need any more help. (I think it may be worth more than 50 points)
Harvey
================================================
PART 2:
To answer you comment issues:
(See the #2 tag in my code above)
To refer to a table column's data, excluding the header use:
=Table5[SITE NAME]
(This will be autogenerated when entering a formula if you click and drag over the data cells in a column).
The code has been altered accordlingly.
I used excel 2013 and 2010 and found that the .Activate event works in both.
See #3 for a minor change.
Please recopy all the code.
note that I introduced code to try and stop flickering using Application.ScreenUpdating, but it didn;t have any effect - I don't know why. I've left the code in so you can do further experiments should you need to.
NOTE the new procedure ComboBox_SiteName_KeyDown
================================================
PART 3:
To answer you comment issues:
It's a combo on a form ! - so make the change tagged with #4 above.
Harvey
Solved!
https://trumpexcel.com/excel-drop-down-list-with-search-suggestions/
You can do what is in the link with some modifications:
"ListFillRange" in combobox properties should be the last column (the one that is changing). If it is a userform the range will go under "RowSource".
And add this code:
Private Sub ComboBox1_Change()
Sheets("Where the data is").Range("B3") = Me.ComboBox1.Value
End Sub
Try changing the command from Change to DropButtonClick
This refreshes the list on a click of the drop down

OptionButton determines value then use in macro

A basic simple VBA question that I havent been able to work out even though there are numerous tutorials about it.
I want a Userform to pop-up, give you two options (OptionButton1 and OptionButton2). You choose one, click ok. And depending on what Option is chosen a certain value is used (in an email, for which I DID finish the macro). For simplifying purposes i now just want the variable 'contents' to be printed in cell A1.
I have these parts so far:
Sub MailOption()
UserForm1.Show
End Sub
Private Sub OptionButton1_Click()
If OptionButton1.Value = True Then Var1 = "Text example 1"
End Sub
Private Sub OptionButton2_Click()
If OptionButton2.Value = True Then Var1 = "Text example 2"
End Sub
Private Sub SendEmail_Click()
Cells(1, 1).Value = Var1
End Sub
There are multiple problems: the variable is not shown in Cell A1 and when i press Send Email the Form is not closed. I am probably doing lots of stuff wrong but its the first time im using a userform. Ty very much
I would simply use this one without handling OptionButton_Click:
Private Sub SendEmail_Click()
Dim res As String
If OptionButton1.Value Then
res = "Text example 1"
ElseIf OptionButton2.Value Then
res = "Text example 2"
Else
res = "Nothing is selected"
End If
'write result in cell
ThisWorkbook.Worksheets("Sheet1").Range("A1").Value = res
'close form
Unload Me
End Sub

Resources