I have a userform with a basic combobox and command button. When the user hits the command button, I want the UserForm to close, and the value of the combobox to be saved in a variable that can be accessed by a subroutine contained within "ThisWorkbook".
In the UserForm code:
Public employee_position As String
Public Sub CommandButton1_Click()
employee_position = Me.ComboBox1.Value
Unload Me
End Sub
In the "ThisWorkbook" Code
Private Sub GetUserFormValue()
Call Userform_Initialize
EmployeePosition.Show
MsgBox employee_position
End Sub
When "GetUserFormValue()" runs, the UserForm comes up, you can select a value in the combobox and press the command button, but when the MsgBox comes up, it displays "" (Nothing)
What am I doing wrong here?
When you Unload Me, I think you lose all information associated with the module (including the global variable). But if you use Me.Hide rather than Me.Unload, then you can access the value of the form after the routine returns. So try this:
-- userform code includes:
Public Sub CommandButton1_Click()
Me.Hide
End Sub
-- main module includes:
Private Sub GetUserFormValue()
Call Userform_Initialize
EmployeePosition.Show
MsgBox EmployeePosition.ComboBox1.Value
Unload EmployeePosition
End Sub
I think that should work.
I had the same problem, and this is how I resolved it:
If the main code is in a worksheet, and the variable is declared as public in that worksheet (e.g. in Microsoft Excel Objects -> Sheet1 (Sheet1)), the result from "Unload Me" cannot be passed from a UserForm to the worksheet code.
So to solve my problem, I inserted a new Module, and declared my public variable there. I didn't even have to move my code from the worksheet to the module... just the declaration of the public variable.
I hope this works for you too!
Andrew
Related
I might miss just a stupid small detail but I don't get a hang on it.
I've created a userform with a listbox where I want the user to select one item. This is working so far as my variable "termin" has the right value before I close the user form
Private Sub OKButton_click()
termin = Eventlist.List(Eventlist.ListIndex)
MsgBox termin 'Just for testing purposes. It gives me the selected item
Unload Eventabfrage
End Sub
And this is a part of what I have in 'ThisOutlookSession':
Option Explicit
Dim termin As String
Public Sub MailMerge()
Eventabfrage.Show
MsgBox termin 'and there it is empty but shouldn't be empty
enter code here
End Sub
What do I have to do to hand over the value to my MailMerge Sub?
It is a macro in Outlook so storing it in any Excel cell is not an option.
Other than using Public variable (which I would only as the last chance since it's prone to many drawbacks), you can use UserForm class Tag property to pass info in and out an instance of a Userform and a more safe Userform instantiating and terminating scheme, as follows:
in the calling module:
Public Sub MailMerge()
Dim termin As String ' declare 'termin' as a Sub scoped variable
With New Eventabfrage ' get a new instance of the wanted userform class and reference it
.Show
termin = .Tag ' retrieve referenced userform 'Tag' property and store it in 'termin' variable
'enter code here
End With ' <-- this will unload the userform instance
End Sub
in the Eventabfrage class module
Private Sub OKButton_Click()
With Me ' reference the Userform class current instance
.Tag = .Eventlist.List(.Eventlist.ListIndex)
.Hide ' hide the userform instead of unloading it, so as to have it "alive", along with its properties (and methods) in its calling sub
End With
End Sub
I am unable to load an userform on opening workbook. Object is Workbook, procedure is Open and have this code in ThisWorkbook.
Private Sub Workbook_Open()
frmWelcome.Show
End Sub
Here's some code that I use, placed in a module called mMain with the form called fForm. I suggest that you start fresh, with something like this, make sure that works, and proceed from there, changing one thing at a time.
Option Explicit
Public dLog As fForm
Sub main()
Set dLog = New fForm
dLog.Show vbModeless 'doesn't have to be modeless
End Sub
There's a lot of information and a lot that you can do with userforms but I can't really find a standard way to use them. Let's say I have a userform with a standard dropdown list that asks someone to choose a fruit. In the userform code I will put the below code after adding a combo box called fruitcombo:
Private Sub UserForm_Initialize()
userform1.fruitcombo.AddItem "Peach"
userform1.fruitcombo.AddItem "Pear"
userform1.fruitcombo.AddItem "Grape"
End Sub
I will also add a commandbutton which will be labeled "Submit" and in that event:
Private Sub Submit_Click()
Me.Hide
End Sub
That's where it starts to get hazy. What's the best way to capture the answer that was selected? One way I can think would be to make a global variable called fruitanswer and then instead of the Me.Hide we can skip straight to Unload Me
Ex:
Private Sub Submit_Click()
fruitanswer = fruitcombo.value
Unload Me
End Sub
Or we can have fruitanswer as a private variable in the module where the userform is called and then unload it in there. There are also multiple ways to initialize the userform. I'm also wondering the best way to initialize it. The Show method will automatically initialize it, but the Hide method WON'T automatically de-initialize it. For that, the Unload statement is necessary. So does anyone initialize it before calling the Show method using the Load statement?
Ex:
Load userform1 'Any point to including this?
userform1.show
'user chooses a fruit and clicks submit button
'userform is hidden by commandbutton but not unloaded yet
fruitanswer = fruitcombo.value
Unload userform1
Out of these options, which is the best method? Is there anything to make it more efficient?
You can wrap the whole thing in a single function call:
strFruit = UserForm1.GetFruit()
Then, in your UserForm, have it do the work of displaying and unloading itself like so:
Private bOK As Boolean
Public Function GetFruit() As String
bOK = False
Me.Show vbModal
If bOK Then GetFruit = ComboBox1.Text
Unload Me
End Function
Private Sub cmdOK_Click()
bOK = True
Me.Hide
End Sub
Private Sub cmdCancel_Click()
Me.Hide
End Sub
This assumes you have buttons named cmdOK and cmdCancel and a combobox named ComboBox1.
Since Show() is being called modally, the code after it won't execute until the form is closed or hidden. When either button is clicked (or the form is closed by other means) then the code continues, the selected text is returned (if OK was clicked), and the form unloads itself.
The beauty of doing it this way is that your calling code doesn't need to worry about instantiating and destroying the form each time it's called. It's just a single statement to load the form and get the return value.
Of course, you'll need to add the code to populate the combobox with whatever items you wish to display.
I kept a userform control button in my worksheet to fire up a macro, which in turn shows a user form, In the form I wish to display the opened files in checkboxes(using the Workbooks collection).I wish to run a macro that performs action for the user selected files only.
So for the button in my worksheet, I have assigned the following macro
Private Sub Button2_Click()
Load MyForm
MyForm.Show
End Sub
At first I kept the below code in the module where my macro sub is there.Since it's not working, I right clicked on user form and selected view code and kept the below code there.But still it's showing the same static designed user form, not the dynamic.I kept breakpoint at both load Myform and MYform.Show() and I stepped through code.It never went into intialize or activate method at all.
Private Sub MyForm_Activate()
'for checking the whether this method is called or not I am trying to change caption
MyForm.LabelSelectFile.Caption = "dhfdfldkfldzjf;zdfkz;d"
Dim mymyWorkBook As Workbook
For Each mymyWorkBook In Workbooks
'code for creating checkbox based on the file name displayed by the workbook collection
Next mymyWorkBook
End Sub
I can't understand why that event is not getting triggered.Please help me to overcome this.Thanks in advance
Even though the name of the form is MyForm, you still need to use userform.
'~~> in your worksheet
Private Sub Button2_Click()
MyForm.Show
End Sub
'~~> In the userform code area
Private Sub UserForm_Initialize()
'~~> Your code here
End Sub
or
Private Sub UserForm_Activate()
End Sub
The best is to always select the event from the drop down, rather than typing it
In a VBA project of mine I am/will be using a series of reasonably complex userforms, many of which are visually identical but have different subroutines attached to the buttons. As a result I'm not overly keen on the idea of duplicating them multiple times in order to get different functionality out of the same layout. Is it possible to have a userform detect which subroutine called it and use this in flow control? I would like to be able to do something like this:
Private Sub UserForm_Initialize()
If [the sub that called the userform is called "foo"] then
Call fooSub
else
Call barSub
End If
End Sub
My backup plan is to have the calling subroutine set a global variable flag and have the userform check that, but that seems like a rather crude and clumsy solution.
Thanks everyone,
Louis
You can use the tag property of the form. Load the form, set the property, then show the form:
Sub PassCallerToForm()
Load UserForm1
UserForm1.Tag = "foo"
UserForm1.Show
End Sub
Now that the property is set, you can determine what to do in the form:
Private Sub UserForm_Activate()
If Me.Tag = "foo" Then
Call fooSub
Else
Call barSub
End If
End Sub
You can also use public variables:
' in userform
Public Caller As String
Private Sub UserForm_Click()
MsgBox Caller
Caller = Now()
Me.Hide
End Sub
' in caller
Sub callUF()
Dim frm As New UserForm1
frm.Caller = "Test Caller"
frm.Show
MsgBox frm.Caller ' valid after Me.Hide
Set frm = Nothing
End Sub
Personally, I would not have one userform doing two disparate activities. The code would get hard to read pretty quickly, I think. Copying the layout of a userform is pretty trivial.
To copy a userform: Open a blank workbook. In the Project Explorer, drag the userform to the new workbook. Rename the userform in the new workbook. Now drag it back to the original workbook. Change the code in the userform copy.
If you absolutely don't want separate userforms, I recommend setting up a property of the userform. Userforms are just classes except they have a user interface component. In the userform module
Private mbIsFoo As Boolean
Public Property Let IsFoo(ByVal bIsFoo As Boolean): mbIsFoo = bIsFoo: End Property
Public Property Get IsFoo() As Boolean: IsFoo = mbIsFoo: End Property
Public Sub Initialize()
If Me.IsFoo Then
FooSub
Else
BarSub
End If
End Sub
I always write my own Initialize procedure. In a standard module:
Sub OpenForm()
Dim ufFooBar As UFooBar
Set ufFooBar = New UFooBar
ufFooBar.IsFoo = True
ufFooBar.Initialize
ufFooBar.Show
End Sub