Excel VBA: Highlight textbox value after error occurs - similar - excel

All,
I have a simple userform with two textboxes. I'm attempting to trap an error and send the user back to TextBox1 if the entry is > 1,000. I found code on this site which gets close under the same Title as above.
The code below traps the error and highlights the number >1,000 entered in Textbox1 (without an error message box). However, if I "uncomment" and enter the
MsgBox ("Value is Greater than 1,000")
after the Cancel = True the error will trap, the msg box displays, but the number greater than 1,000 will not highlight.
I've pulled most of what remains of my hair trying to see why this doesn't work and the example I'm following does. Help!!
Thanks
Stan
Private SkipIT As Boolean
'------------------------------------------------------
Private Sub TextBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
If SkipIT Then Exit Sub
With Me.TextBox1
If Val(Me.TextBox1.Value) > 1000 Then
Cancel = True
'MsgBox ("Value is Greater than 1,000") 'Will highlight if this line is commented, but no error message box
.SetFocus
.SelStart = 0
.SelLength = Len(.Text)
End If
End With
End Sub
'--------------------------------------------------------------------
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
SkipIT = True
End Sub

Related

Run-time error '380' when changing combobox value (using userforms and VBA in Excel)

This is a very simplified example to demonstrate my problem.
Create a userform with a combobox and commandbutton.
Set the style property of the combobox to "fmStyleDropDownList".
Add the code
Private Sub CommandButton1_Click()
ComboBox1.Value = "But then it errors sometimes if I change it here"
End Sub
Private Sub UserForm_Initialize()
ComboBox1.Value = "I can initialize to any value I choose"
End Sub
When I run the userform I can click the command button all day long without getting any errors.
But, when I click on the drop-down arrow of the combobox and the text in the box gets highlighted, then the next time I click the command button I get "Run-time error '380': Could not set the Value property. Invalid property value"
Using style="fmStyleDropDownCombo" is not an option I want to consider. I tried using ComboBox1.ListIndex = -1 to clear the selection but that did not work.
Any ideas on how I can reliably avoid this error?
When you use fmStyleDropDownList style, your ComboBox value must match one of the item in the list but because you did not add any item, your list is currently Null.
To test this, make another ComboBox in your Userform and put this in your Userform:
Private Sub CommandButton1_Click()
Debug.Print "=== Click ==="
Debug.Print "ComboBox1 Type: " & TypeName(ComboBox1.List)
Debug.Print "ComboBox2 Type: " & TypeName(ComboBox2.List)
ComboBox1.Value = "But then it errors sometimes if I change it here"
On Error Resume Next
ComboBox2.Value = "But then it errors sometimes if I change it here"
If Err.Number <> 0 Then Debug.Print "ComboBox2 - Error"
Debug.Print "============="
End Sub
Private Sub UserForm_Initialize()
ComboBox1.AddItem "I can initialize to any value I choose"
ComboBox1.AddItem "But then it errors sometimes if I change it here"
ComboBox1.Value = "I can initialize to any value I choose"
ComboBox2.Value = "I can initialize to any value I choose"
Debug.Print "ComboBox1 Type: " & TypeName(ComboBox1.List)
Debug.Print "ComboBox2 Type: " & TypeName(ComboBox2.List)
End Sub
When you run the Userform, you should see this in the immediate window:
ComboBox1 Type: Variant()
ComboBox2 Type: Null
Clicking the button (as many times as you like) before clicking ComboBox2 and you will notice that the output will still be the same. (and no error too because the List is still Null)
Now click ComboBox2 and click the button again, you will see that the type for ComboBox2.List has now changed from Null to Variant and will actually trigger the error.
===============
So, to avoid this, you need to populate the List first, below shows the AddItem method:
Private Sub CommandButton1_Click()
ComboBox1.Value = "But then it errors sometimes if I change it here"
End Sub
Private Sub UserForm_Initialize()
ComboBox1.AddItem "I can initialize to any value I choose"
ComboBox1.AddItem "But then it errors sometimes if I change it here"
ComboBox1.Value = "I can initialize to any value I choose"
End Sub
As far as I know, the preferred way to set a ComboBox value with such style is to loop through the ComboBox List property, check its value and change the ListIndex once found:
Private Sub CommandButton1_Click()
Dim i As Long
For i = 0 To ComboBox1.ListCount - 1
If ComboBox1.List(i) = "But then it errors sometimes if I change it here" Then
ComboBox1.ListIndex = i
Exit For
End If
Next i
End Sub

Setting minimum value to a textbox

I am using a userform with multiple textbox. I was wondering if there is a way of forcing the user to input a minimum value or higher before moving to the next textbox.
Thanks a lot,
Assuming one of your textboxes is named TextBox1 you can place this code in your userform:
Option Explicit
Dim blnClosing As Boolean
Private Sub TextBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
If blnClosing = False Then
Dim iVal As Integer
Dim minVal As Integer
minVal = 10 'Change to your needs
'Test for numeric characters
On Error Resume Next
iVal = CInt(Me.TextBox1.Value)
'If characters are not numeric
If Err.Number = 13 Then
MsgBox "Value must be numeric!", vbCritical, "Incorrect Value"
Me.TextBox1.Text = vbNullString
Cancel = True 'Retain focus on the textbox
Exit Sub
End If
'Reset error handling to normal
On Error GoTo 0
'Check if textbox value is less than the minimum
If Me.TextBox1.Value < minVal Then
MsgBox "Value must be greater than " & minVal & "", vbCritical, "Incorrect Value"
Me.TextBox1.Value = vbNullString
Cancel = True 'Retain focus on the textbox
End If
End If
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
blnClosing = True
End Sub
I took the liberty of checking for a numeric value as well, since you are asking if the value in the textbox appears to be required to be numeric. If that's not the case remove the lines of code from the 'Test for numeric characters comment down to the On ErrorGoTo 0 line.
The global variable blnClosing allows us to skip over the code when the form is closing. If this wasn't included and the user pressed 'X' on the upper right hand corner of the form with invalid data (blank, less than the minimum, or non-numeric) then the messageboxes would show.

Excel VBA: Highlight textbox value after error occurs

I am trying to highlight entered value in TextBox. TextBox value is representing date value in date forma DD-MM-YYYY. I wrote some code to validate if inserted date is ok (in example 31 of April).
Hightlight itself is not a problem, however I want to do this right after an error occurs. So when I insert 31-04-2014, I should get the message "You have inserted wrong date" and the date value should hightlighted. For now it shows me message, highlights value and focus is set to another CommandButton
So far I made something like this:
Private Sub data_faktury_AfterUpdate()
Dim dzien As Byte, miesiac As Byte
Dim rok As Integer
On Error GoTo blad:
dzien = Mid(data_faktury.Value, 1, 2)
miesiac = Mid(data_faktury.Value, 4, 2)
rok = Right(data_faktury.Value, 4)
Call spr_date(dzien, miesiac, rok)
Exit Sub
blad:
If Err.Number = 13 Then
If data_faktury <> "" Then
If Len(data_faktury) < 10 Then: MsgBox ("Źle wpisana data faktury.")
End If
End If
End Sub
And code for 2nd procedure:
Sub zle()
MsgBox ("Wybrałeś zły dzień")
With Faktura.data_faktury
.SetFocus
.SelStart = 0
.SelLength = Len(.Text)
End With
End Sub
This is a bit long for a comment so here goes. The basic principle is to use the exit event and cancel when necessary. To prevent this being fired when you close the form, you need to use a flag variable - example userform code:
Private bSkipEvents As Boolean
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If bSkipEvents Then Exit Sub
With TextBox1
If Not IsValidDate(.Text) Then
Cancel = True
MsgBox "Invalid date"
.SelStart = 0
.SelLength = Len(.Text)
End If
End With
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
bSkipEvents = True
End Sub

Excel Userform Textbox Behavior

I have a textbox on a userform. It is the only textbox on the form. There are three labels and two buttons in addition to this textbox. Basically, I want the focus to remain on this textbox under all scenarios, other than the moment that one of the buttons would be clicked, but then I want the focus to come right back to the text box. Both buttons have "TakeFocusOnClick" and "TabStop" set to False. I was having problems with getting the focus set to the textbox, which is why I changed these two settings.
Once I changed these settings, the Enter key in the textbox stopped having any effect. I have events written for _AfterUpdate and _KeyPress for the textbox, but they don't fire. As you can see in the code, I have commented out the lines to set the focus to this textbox. Since it is now the only object that can take focus, these lines are not needed (theoretically). When I allowed the other objects to take focus, these lines weren't having any effect (focus was switching to the buttons despite these SetFocus lines).
Here is the code. It is very simple, except that the Enter key isn't triggering the event. Can anyone see why? Thanks.
Private Sub btnDone_Click()
Application.Calculation = xlCalculationAutomatic
formMath.Hide
'Clear statistics
Range("attempts").Value = 0
Range("correct").Value = 0
Sheet5.Range("A2:W500").ClearContents
End Sub
Private Sub btnSubmit_Click()
recordAnswer
'formMath.txtAnswer.SetFocus
End Sub
Private Sub txtAnswer_AfterUpdate()
recordAnswer
'formMath.txtAnswer.SetFocus
End Sub
Private Sub txtAnswer_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If KeyAscii = 13 Then
recordAnswer
End If
End Sub
Private Sub UserForm_Initialize()
'Initialize manual calculation
Application.Calculation = xlCalculationManual
Application.Calculate
'Initialize statistics
Range("attempts").Value = 0
Range("correct").Value = 0
Sheet5.Range("A2:W500").ClearContents
'Initialize first problem
newProblem
End Sub
Sub recordAnswer()
'Update statistics
Dim attempts, correct As Integer
attempts = Range("attempts").Value
correct = Range("correct").Value
Range("results").Offset(attempts, 0).Value = attempts + 1
Range("results").Offset(attempts, 1).Value = lblTopNum.Caption
Range("results").Offset(attempts, 2).Value = lblBotNum.Caption
Range("results").Offset(attempts, 3).Value = lblBop.Caption
Range("results").Offset(attempts, 4).Value = Range("Answer").Value
Range("results").Offset(attempts, 5).Value = txtAnswer.Text
If (Range("Answer").Value = txtAnswer.Text) Then
Range("results").Offset(attempts, 6).Value = 1
Else
Range("results").Offset(attempts, 6).Value = 0
End If
'Update attempts and success
Range("attempts").Value = attempts + 1
Range("correct").Value = correct + 1
newProblem
End Sub
Sub newProblem()
Application.Calculate
formMath.lblTopNum.Caption = Range("TopNum").Value
formMath.lblBotNum.Caption = Range("BotNum").Value
formMath.lblBop.Caption = Range("ProbType").Value
formMath.txtAnswer.Value = ""
'formMath.txtAnswer.SetFocus
End Sub
To start off
You can either in the design mode, set the TabIndex property of the Textbox to 0 or you can set the focus on the textbox in the UserForm_Initialize()
Private Sub UserForm_Initialize()
TextBox1.SetFocus
End Sub
Similarly after any operation that you perform, simply call the TextBox1.SetFocus to revert to the textbox.
Option Explicit
Private Sub UserForm_Initialize()
TextBox1.SetFocus
End Sub
Private Sub CommandButton1_Click()
MsgBox "Hello from Button 1"
TextBox1.SetFocus
End Sub
Private Sub CommandButton2_Click()
MsgBox "Hello from Button 2"
TextBox1.SetFocus
End Sub
Let me know if this is not what you want?
I found a way to accomplish this. In the code above I took out the _KeyPress and _AfterUpdate events and replaced them with:
Private Sub txtAnswer_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Select Case KeyCode
Case 13: recordAnswer
End Select
End Sub
Not sure why the other methods didn't work, but this does.
Also not sure why simply setting the focus directly didn't work. I suspect that the focus was being set, but then something else was happening subsequently that was changing the focus off of the textbox. Just a guess.
Thanks for the help. I appreciate it.

Userform Cancel Button _Intermittently_ Unresponsive?

The attached VBA procedures are for a progress bar userform. Everything works as expected, except that the cancel button is intermittently unresponsive.
I say intermittently because, 95% of the time I have to click the cancel button numerous times before the procedure stops. I can see the button click event being animated, but the procedure isn't being interrupted. It looks as though something is stealing focus from the cancel button before the button down event can occur.
The escape and window close buttons respond as expected with one click.
What do I need to do to make the cancel button respond correctly? Thanks!
Update: I noticed that when I click and hold down on the cancel button, instead of the button staying "down" it gets kicked back up. So apparently something is resetting the button state to up, fast enough that the procedure is not catching the down state to fire the click event.
Here is the code in the userform module (named UserForm1):
Private mbooUserCancel As Boolean
Public Property Get UserCancel() As Boolean
UserCancel = mbooUserCancel
End Property
Private Property Let UserCancel(ByVal booUserCancel As Boolean)
mbooUserCancel = booUserCancel
End Property
Public Sub UpdateProgress(CountTotal As Long, CountProgress As Long)
On Error GoTo Error_Handler
ProgressBar1.Value = CountProgress / CountTotal * 100
DoEvents
Error_Handler:
If Err.Number = 18 Then CommandButton1_Click
End Sub
Private Sub CommandButton1_Click()
Hide
UserCancel = True
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
Cancel = True
CommandButton1_Click
End Sub
Private Sub UserForm_Activate()
With Application
.Interactive = False
.EnableCancelKey = xlErrorHandler
End With
End Sub
Private Sub UserForm_Terminate()
Application.Interactive = True
End Sub
Here is the code for the module (named Module1) that calls the UserForm1:
Sub TestProgress()
On Error GoTo Error_Handler
Dim objUserForm As New UserForm1
Dim lngCounter As Long
Dim lngSubCounter As Long
With objUserForm
.Show vbModeless
DoEvents
For lngCounter = 1 To 5
If .UserCancel Then GoTo Exit_Sub
For lngSubCounter = 1 To 100000000
Next lngSubCounter
.UpdateProgress 5, lngCounter
Next lngCounter
Application.Wait Now + TimeValue("0:00:02")
.Hide
End With
Exit_Sub:
If objUserForm.UserCancel Then
MsgBox "User Cancelled from UserForm1"
End If
Exit Sub
Error_Handler:
If Err.Number = 18 Then
Unload objUserForm
MsgBox "User Cancelled from Module1"
End If
End Sub
Works for me on the first click every time. Try unloading any add-ins or any other code that could be running inside the container app and see if that helps.
If people are still in need of the answer, well I researched & cracked it!
For the click on cancel button, code should be;
Private Sub CommandButton1_Click()
Unload Me
'this bit ends all macros
End
End Sub
The answer is to use modal userforms for progress bars so that the button click event can fire without getting obscured by processing in the calling procedure.

Resources