Refresh Combobox using listbox from second Userform
"It seems that before passing the MyVal to the ComboBox1, the program is running the "Sub UserForm1_Initialize()" again."
Apart from some typos (regarding both UserForm_Initiate
syntaxes) your main issue is that by invoking the default instance of a(n existing) userform you get it reinstanciated. Especially trying to assign a value by referencing another userform's default instance (see UserForm2's code module) via
UserForm1.ComboBox1 = MyVal
... re-initializes the default instance of UserForm1 and destroys any changes before.
Modified example to understand the way (see code below)
So delete the code line above in the 2nd Userform code module and call an instance of UserForm2 via function YourChoice()
in the 1st one returning the found value MyVal
as function result in order to stick as close as possible to your post using a "global" variable MyVal
. This would allow you to use instances of a UserForm and to get what you wanted.
Further possible steps - (Not)tl;tr
It's good use, however
- not only to instantiate a ("New") UserForm object instead of calling the form's default instance,
but
- to handle its
QueryClose
event to prevent rash termination,
- to decide upon a UserForm's life time by the calling code (regular or class module),
- to separate model logic (i.e.the data), view (i.e. the form) and presentation, aka MVP design pattern using the advanced possibilities of classes.
Generally you should prefer not to unload within the form's code behind - I didn't change that to leave the example comprehensible, but would recommend to study ►Mathieu Guindon's outstanding article "UserForm1.Show?" for a first insight, better understanding and some ideas on the road.
Citation
A Userform is not only a class, but disposes of an internal pecularity - or to cite Mathieu:
"UserForm
is a class module: it defines the blueprint of an object. Objects usually want to be instantiated, but then someone had the genius idea of granting all instances of MSForms.UserForm
a predeclared ID, which in COM terms means you basically get a global object for free."
c.f. Disadvantages in putting code into UserForms instead of modules
Modified Example code
Option Explicit
Sub UserForm_Initialize() ' << typo: not UserForm1_Initialize !
ComboBox1.AddItem "Item1"
ComboBox1.AddItem "Item2"
ComboBox1.AddItem "Item3"
End Sub
Sub ComboBox1_Click()
If ComboBox1 = "Item3" Then
''' Load UserForm2 ' << don't reference the default instance
''' UserForm2.Show ' << but
ComboBox1.List(2) = yourChoice ' make it a function call returning your choice
End If
End Sub
Option Explicit
Sub UserForm_Initialize() ' typo: not UserForm2_Initialize !
ListBox1.AddItem "Apple"
ListBox1.AddItem "Pear"
ListBox1.AddItem "Banana"
End Sub
Sub CommandButton1_Click()
' Purpose: assign listbox value to variable (here: global; better: via class property)
MyVal = ListBox1 ' equals ListBox1.List(ListBox1.ListIndex)
''' UserForm1.ComboBox1 = MyVal ' << reinitializes the default instance of UF1 !!!
Unload Me ' (better to make the calling function terminate the form instead)
End Sub
Side note: - as close as possible to the OP and sticking to the global variable method as mentioned above to allow better comprehension (consider mentioned suggestions, too :-)
Option Explicit
Public MyVal As String ' here: global variable
Sub showMain()
With New UserForm1
.Show vbModeless ' any mode allowed: 0-vbModeless or 1-vbModal (default)
End With
End Sub
Function yourChoice$()
With New UserForm2
.Show vbModal ' or simply: .Show to allow a correct return of the function result
End With
yourChoice = MyVal ' (a modeless form would execute any code before termination)
End Function
Further link
This post doesn't treat modeless forms; calling the 2nd Userform this way would need other logic - see
Destroy a modeless UserForm instance properly
MyVal
as aVariant
and using.List
? – braX