VBA - TextBox_Exit doesn't work properly when closing with ESC - vba

I have a form with a TextBox1 and a CommandButton1.
The Cancel property of the CommandButton1 is True. So I can close the form with a key press on Esc.
The TextBox1 has an Exit event, so when leaving this element will fire an event. In this event I will print the user input and some static content.
Sub CommandButton1_Click()
Unload Me
End Sub
Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Debug.Print "Textbox1_Exit was fired, content was: " & TextBox1.Value
End Sub
Now I enter some content in the TextBox1, let's say I enter 'foo'.
If I close the form with the CommandButton1 the output will be:
TextBox1_Exit was fired, content was: foo
The problem:
If I leave the form via the Esc key, the output will only be:
TextBox1_Exit was fired, content was:
So only the static part of Debug.Print will be printed.
I would like to get the user input in both cases.

Okay so this was a bit tricky - since you can't grab the TextBox1.Value when using Esc from the Userform, you can use a Public string variable instead which mimics the entries made into the TextBox. So you'll need to declare a Public variable, add a TextBox_Change event, and add a Userform_Initialize event to reset the string each time:
Public mystring As String
Sub CommandButton1_Click()
Unload Me
End Sub
Private Sub TextBox1_Change()
If Not Len(TextBox1.Value) <= Len(mystring) + 1 Then
mystring = mystring & Right(TextBox1.Value, 1)
Else
If TextBox1.Value <> "" Then
mystring = TextBox1.Value
End If
End If
End Sub
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Debug.Print "Textbox_Exit was fired, content was: " & mystring
End Sub
Private Sub UserForm_Initialize()
mystring = ""
End Sub

you could use UserForm_QueryClose event to catch the UserForm exit event and call TextBox1_Exit one:
Option Explicit
Sub CommandButton1_Click()
Unload Me
End Sub
Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Debug.Print "Textbox1_Exit was fired, content was: " & TextBox1.Value
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
Dim myVar As MSForms.ReturnBoolean
Me.TextBox1_Exit myVar
End Sub

Related

How can i pass a variable from userform1 textfield dblclk event to userform2 and then dynamically pass data back to userform1 through cmdbutton click

On userform1 I have a text field that when it is doubleclicked opens a "timebox" Userform 2. The user then can adjust the time and then either cancel or apply. Apply should fill in Userform1 Textbox with the selection from Userform2.
If it was once instance no problem but i'm trying to use the Userform 2 on 28 + fields and can't reference each one separately. I need to pass the textfield.name on Userform1 to give Userform2 the address in which to send the data. But its userform2 cmdbuttom - Apply.
I looked at ByVal and ByRef which seems to work when its a Sub but not when its a cmdbutton.
Userform1 > Field
Public Sub AgStart1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Dim fieldname As String
fieldname = UserForm1.AgStart1.Name
TimeForm1.Show
End Sub
UserForm2
Public Sub TimeApply1_Click()
Dim timeselect
timeselect = Me.txt_Hours.Value & ":" & Me.txt_Mins & " " & Me.txt_AmPm
'I need the value above to be sent back to the field that spawned the Userform2
TimeForm1.Hide
End Sub
OR a better way like activecell for user form fields
Userform1 text field
Useform2 spawned from dblclk
Something like this should work:
UserForm1
Public Sub AgStart1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
PopTime AgStart1
End Sub
Public Sub AgStart2_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
PopTime AgStart2
End Sub
'etc etc
Sub PopTime(ctrl As Object)
Dim frm As New TimeForm1
Set frm.TheControl = ctrl 'pass the control to the second form
frm.Show
End Sub
UserForm2
Public TheControl As Object
Public Sub TimeApply1_Click()
'set the value of the passed control
TheControl.Value = Me.txt_Hours.Value & ":" & Me.txt_Mins & " " & Me.txt_AmPm
Me.Hide
End Sub

How to exit a VBA macro when the form's "X" button is clicked?

I have an Outlook macro that pops up a form when someone sends an email and asks them to select a classification. Under ThisOutlookSession I have:
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
Dim frm As classificationForm
Dim chosenvalue As String
Set frm = New classificationForm
frm.Show vbModal
Select Case True
Case frm.restrictedButton.Value
chosenvalue = "Restricted"
Case frm.internalButton.Value
chosenvalue = "Internal"
Case frm.publicButton.Value
chosenvalue = "Public"
Case Else
MsgBox "No classification chosen"
Cancel = True
Exit Sub
End Select
If TypeName(Item) = "MailItem" Then
Item.Subject = "[" & chosenvalue & "] " & Item.Subject
End If
End Sub
and under classificationForm I have:
Private Sub okCommand_Click()
Unload Me
End Sub
Private Sub cancelCommand_Click()
Unload Me
End Sub
The form is 3 option buttons (the classifications) and 2 command buttons (OK and Cancel).
The [Internal] option button is selected by default. However, if someone clicks the form's "X" button in the top-right corner or the "Cancel" command button, then the Macro sends the email with the selected classification button when I want it to kick me back to the draft email like it would if there were no options selected.
How would I do this? Thanks.
Unload is a lie. It seems to only work with the form's default instance, and working with forms' default instance is a poisonous place you don't want to go.
Don't unload. Hide instead.
Another problem is that since the calling code is querying the form's controls' state, it doesn't matter how the form was closed: Ok, Cancel, "X" - everything single one of these buttons gets the form unloaded and whatever was selected is acted upon: you have no mechanism in place to determine whether the user okayed the dialog, or wishes to cancel everything.
Add a Cancelled property:
Private IsCancelled As Boolean
Public Property Get Cancelled() As Boolean
Cancelled = IsCancelled
End Property
Handle the QueryClose event, set the Cancel parameter to False when the CloseMode is vbFormControlMenu, and Hide the form - actually, what you want is for that "X" button to do exactly the same thing as your Cancel button, so just do that:
Private Sub OkButton_Click()
Me.Hide
End Sub
Private Sub CancelButton_Click()
OnCancel
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = VbQueryClose.vbFormControlMenu Then
Cancel = True
OnCancel
End If
End Sub
Private Sub OnCancel()
IsCancelled = True
Me.Hide
End Sub
Now your calling code can determine whether the form was cancelled, and act accordingly.
If frm.Cancelled Then
Cancel = True
Else
'user okayed the dialog: determine the selection...
End If
See this article for more in-depth information about user forms: the calling code doesn't need to care about the controls on the form.
use UserForm_QueryClose() event handler to intercept any userform red "X" clicking
then change your UserForm code pane as follows:
Private Sub okCommand_Click()
Me.Hide ' don't unload the Form, just hide it
End Sub
Private Sub cancelCommand_Click()
Me.Tag = "NO" ' signal to the calling sub that it must not send the email
Me.Hide ' don't unload the Form, just hide it
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = 0 Then Me.Tag = "NO" ' if user clicked the red X button signal to the calling sub that it must not send the email
End Sub
and adjust your Application_ItemSend event handler code accordingly:
Set frm = New classificationForm
With frm
.Show vbModal
If .Tag <> "NO" Then ' if userform didn't signal not to send the email
Select Case True
Case frm.restrictedButton.Value
chosenvalue = "Restricted"
Case frm.internalButton.Value
chosenvalue = "Internal"
Case frm.publicButton.Value
chosenvalue = "Public"
Case Else
MsgBox "No classification chosen"
Cancel = True
Exit Sub
End Select
Else ' the userform signaled not to send the email
MsgBox "No classification chosen"
Cancel = True
End If
End With
Unload frm

Formatting Text Boxes in a Userform

I have a Userform that includes Text Boxes with multiple formats. I have the Initialize as blank ("") and then format them using afterupdate(). This all works fine, my issues come from the possibility of the user miss keying the data the first go around or just clicking aimlessly on there screen. After you input a value it formats it correctly when you move from the text box. But if you reselect the text box then move away again, it clears the value. And if you do this with the text box that is formatted as a percent it actually bugs out with a mismatch error.
Here is a slice of my current code:
Private Sub UserForm_Initialize()
ValueAnalysisTextBox.Value = ""
CapRateTextBox.Value = ""
End Sub
Private Sub ValueAnalysisTextBox_AfterUpdate()
ValueAnalysisTextBox.Value = Format(Val(ValueAnalysisTextBox.Value), "$#,###")
End Sub
Private Sub CapRateTextBox_AfterUpdate()
CapRateTextBox.Value = Format(Val(CapRateTextBox.Value) / 100, "Percent")
End Sub
Any thoughts on how to clean this up would be great.
Is this what you are trying?
Private Sub ValueAnalysisTextBox_AfterUpdate()
Dim amt As Double
amt = Val(Replace(ValueAnalysisTextBox.Value, "$", ""))
ValueAnalysisTextBox.Value = Format(amt, "$#,###")
End Sub
Private Sub CapRateTextBox_AfterUpdate()
Dim Perct As Double
Perct = Val(Replace(CapRateTextBox.Value, "%", "")) / 100
CapRateTextBox.Value = Format(Perct, "Percent")
End Sub
Note: I am not doing any other error handling. For example, user typing "Blah Blah" or pasting something else in the textbox. I am sure you can handle that.
I'd store the underlying values in the .Tag property of the TextBox, then use it to change the formatting back and forth in the Enter and Exit events:
Private Sub UserForm_Initialize()
ValueAnalysisTextBox.Value = vbNullString
ValueAnalysisTextBox.Tag = vbNullString
End Sub
Private Sub ValueAnalysisTextBox_Enter()
ValueAnalysisTextBox.Value = ValueAnalysisTextBox.Tag
End Sub
Private Sub ValueAnalysisTextBox_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If IsNumeric(ValueAnalysisTextBox.Value) Then
ValueAnalysisTextBox.Tag = Val(ValueAnalysisTextBox.Value)
ValueAnalysisTextBox.Value = Format$(ValueAnalysisTextBox.Tag, "$#,###")
Else
ValueAnalysisTextBox.Tag = vbNullString
End If
End Sub

Determine which command button was clicked to open userform

I have two command buttons (cmd1 and cmd2) on userform1, when clicked each show the same userform (userform2). Within the initialize or load sub is it possible to determine which command button was clicked on userform1 and therefore show the form differently? I imagine the code in either the initialize or load sub on userform2 to have the following skeleton:
if (cmd1 was clicked)
' do stuff relating to 1
elseif (cmd2 was clicked)
' do stuff relating to 2
else
' error handling
End if
The respective "stuff" could be moved into the event handler for cmd1 and cmd2 however, if the method described above can be used it will be a lot simpler and cleaner.
Use a Public Variable in UserForm1 and then test it in UserForm2_Initialize Event.
Something like this in UserForm1:
Public whatsclicked As String
Private Sub CommandButton1_Click()
whatsclicked = "CommandButton1"
UserForm2.Show
End Sub
Private Sub CommandButton2_Click()
whatsclicked = "CommandButton2"
UserForm2.Show
End Sub
And then in UserForm2:
Private Sub UserForm_Initialize()
Select Case UserForm1.whatsclicked
Case "CommandButton1": MsgBox "CommandButton1 loaded form."
Case "CommandButton2": MsgBox "CommandButton2 loaded form."
Case Else 'Do something else
End Select
End Sub
you can do it also without public variable.
i won't show an example where you can simply write something in a cell or hidden sheet, instead i just pass the wanted info directly .
this time whatsclicked is the name of a label in userform2,
in userform1, before calling userform2:
Private Sub CommandButton1_Click()
load UserForm2
with UserForm2
.whatsclicked.caption= "CommandButton1"
.Show
end with
End Sub
Private Sub CommandButton2_Click()
load UserForm2
with UserForm2
.whatsclicked.caption= "CommandButton2"
.Show
end with
End Sub
Of course, you will have to hide the text of whatsclicked to the user (same color as font or background...)
You can use ActiveControl for this as when you click a control it becomes active/focussed:
Private Sub CommandButton1_Click()
Debug.Print Me.ActiveControl.Name
End Sub
Private Sub CommandButton2_Click()
Debug.Print Me.ActiveControl.Name
End Sub
So more in line with your example:
Private Sub CommandButton1_Click()
Call DoStuff
End Sub
Private Sub CommandButton2_Click()
Call DoStuff
End Sub
Private Sub DoStuff()
select case Me.ActiveControl.Name
case "CommandButton1"
' do stuff relating to 1
case "CommandButton2"
' do stuff relating to 2
case else
'error etc.
end select
End Sub

Global Variable in Userform

I search about this in the forum and found some answers but did not work for me.
I have two UserForms.
In the first one, I give a value to a variable called Word.
In the second one, I have a Label that I need the caption to become the variable Word.
Example:
Public Word as String
Private Sub Userform1_Activate
Word = "Today Is Saturday"
End Sub
Private Sub Userform2_Activate
Label1.Caption = Word
End Sub
But this does not work. The Label caption gets Zero for value.
Could anybody help me on this?
Thanks.
First Form
Private Sub CommandButton5_Click()
Db = "C:\Users\Desktop\db.txt"
Set File1 = CreateObject("Scripting.FileSystemObject")
Set File2 = File1.OpenTextFile(Db, 1)
Do Until File2.AtEndOfStream
If (File2.Readline = TextBox1) Then Exit Do
If File2.AtEndOfStream Then WordNotFound.Show
If File2.AtEndOfStream Then TextBox1.Value = ""
If File2.AtEndOfStream Then Exit Sub
Loop
Word = File2.Readline
MsgBox Word
TextBox1.Value = ""
End Sub
Second Form
Private Sub UserForm_Click()
Label1.Caption = Word
End Sub
As I said in my comment, that your method should work. Here is the test code that I tried
1- In Module1
Public Word As String
2- Create 2 user forms - UserForm1 and UserForm2
2a- In UserForm1
Private Sub UserForm_Activate()
Word = "This is Saturday"
End Sub
2b- In UserForm2
Private Sub UserForm_Activate()
Label1.Caption = Word
End Sub
3- Then in ThisWorkbook
Private Sub Workbook_Open()
UserForm1.Show
UserForm2.Show
End Sub
So when you close UserForm1, the UserForm2 would be displayed as below