VBA ComboBox to TextBox in two diferent user forms - excel

So I need help finishing up a app lookup on elements from the periodic table. The idea if to have the user input the element in the combo box in Userform1 which has a drop down list. To then depending on the element chosen be directed to Userform2 that has a text box, and in that text box be given the atomic mass for each element . I need an example of how and where to write the code in either userfroms. This is what i have so far.
UserForm1 name is Element_LookUp
Userform2 Name is Element_LookUp_Result
Userform1 :
Private Sub CommandButton1_Click()
Unload Me 'Closes The Screen after the click
Element_LookUp_Result.Show 'Shows The result scrren in a new pop up
End Sub
Private Sub UserForm_Initialize()
' All 118 Elements will be shown on a drop down list
' The elements are in order ; autofill helps input the element.
ComboBox1.AddItem "Hydrogen"
ComboBox1.AddItem "Helium"
ComboBox1.AddItem "Lithium"
ComboBox1.AddItem "Beryllium"
ComboBox1.AddItem "Boron"
ComboBox1.AddItem "Carbon"
End Sub ' Not all the elements are listed below i just wanted to save time
UserForm 2 :
Private Sub UserForm_Terminate()
Unload Me 'Once the (X) is clicked the result screen goes away
Element_Lookup.Show 'Result scrren goes back to the input screen again
End Sub

As you're maintaining data from different userforms/modules, etc., I believe you're looking to have a global variable... At the top of the module for your userform (for the purpose of this post, will say UF1 is userform1, UF2 as userform2), you will put (not inside of a subroutine):
Public ElementName as String
Now, in your commandbutton1_click:
ElementName = Combobox1.Value
In UF2 initilize subroutine, you will put something like:
Textbox1.value = UF1.ElementName
The above example would be how to just pass the variable. You could also use ElementName such as:
Textbox1.Value = Application.Index(OutputRange,Application.Match(UF1.ElementName,LookupRange,0))
With that index/match you have used ElementName to find an output, where you would want the column for atomic mass.

Related

How can I run a userform from a macro?

I developed many UDFs and macros in VBA for Excel 2016. One of my macros uses an Inputbox to get data used subsequently by the macro. I want to replace the Inputbox with a user form. I have created the user form, with one text box. I want to activate the user form, populating the text box with the default data, and return the text box data to the macro when OK is selected. I have searched extensively for an end-to-end example for all the the code needed to do this, with no luck. Does an example for this simple problem exist?
Add a Property to your user form. For this answer, let us use the following code within the user form.
Public Property Get MyResult() As String
' You may want to do any manipulation here
' including converting to a number, in which case the return type should be changed (*)
MyResult = TextBox1.Text
End Property
(*) If you are doing conversion, you can have another function in your user form to disable the "OK" button until they have valid convertible data in the text box.
You also want to know if they have hit "Cancel"
Public Property Get Cancelled() As Boolean
Cancelled = pCancelled ' Declare pCancelled as a Boolean in the scope of the form
End Property
Public Sub CancelButton_Click() ' Standard click event for the button
pCancelled = True
Me.Hide
End Sub
Public Sub OKButton_Click() ' Standard click event for the button
pCancelled = False
Me.Hide
End Sub
In your calling macro
MyForm.Show ' This is modal, so will block execution until a response is provided
If Not MyForm.Cancelled Then
Debug.Print MyForm.MyResult
'Do something with MyForm.MyResult
End If
UnLoad MyForm ' assuming you do not want to re-use this form as part of your logic.
There is an example of how you can pass the value to a form and get the result back. The approach uses Scripting.Dictionary object created within standard module scope and passed to userform to allow values to be changed. So it makes possible to send the default values to userform, and keep the result values in the dictionary even after the userform is closed and unloaded. You may have multiple values, just add the necessary quantity of keys to the dictionary, e. g. oData("property1"), oData("property2"), etc.
Add a standard module to the project and put the below code into it:
Option Explicit
Sub Test()
Dim oData
' Set default value and show form
Set oData = CreateObject("Scripting.Dictionary")
oData("") = "Some default text"
UserForm1.ShowForm oData
' Wait until user close form
Do While IsUserFormLoaded("UserForm1")
DoEvents
Loop
' Output returned value
MsgBox oData("")
End Sub
Function IsUserFormLoaded(UserFormName As String) As Boolean
Dim oUF As Object
For Each oUF In UserForms
If LCase(oUF.Name) = LCase(UserFormName) Then
IsUserFormLoaded = True
Exit Function
End If
Next
End Function
Add a userform module named UserForm1 to the project, place controls as shown:
And put the below code into the userform module :
Private opData
Public Sub ShowForm(oData)
Set opData = oData
Me.TextBox1.Value = opData("")
Me.Show
End Sub
Private Sub UserForm_Initialize()
If TypeName(opData) <> "Dictionary" Then Set opData = CreateObject("Scripting.Dictionary")
End Sub
Private Sub CommandButton1_Click()
Unload Me
End Sub
Private Sub CommandButton2_Click()
opData("") = Me.TextBox1.Value
Unload Me
End Sub

How to reference variables from listboxes in the main code of a userform?

Say I had a userform with 3 options:
Listbox1: Item 1
Item 2
Item 3
I want to reference them in the main code, like:
If Listbox1 = *Item 1*
do something
or
*Item 1* = 400
How do I reference Item 1 in the code? Would it be Listbox1.1? Listbox1 = 1? "Item 1"?
Here is one simple example illustrating the concept. As Mathieu Guindon pointed out in a comment, you can use ListBox.Text.
Suppose you have the following user form which is opened by clicking the button "Show User Form". I assume from your question that you would like to do something like selecting an item in the list and then do something in the code when you click the OK button. In my example, clicking OK launches the Message Box showing which item was selected, but you could of course do whatever you want. The code that generates the messsage box is located in a regular module, while the code for the OK button and Listbox is located in the user form.
The button "Show User Form" simply calls the following sub in the regular module:
Public Sub ShowForm1()
UserForm1.Show
End Sub
This displays the user form, which is initialized with the following code:
Private Sub Userform_initialize()
With Me.ListBox1
.AddItem "Item 1"
.AddItem "Item 2"
End With
End Sub
The code below for the OK button includes the reference Me.ListBox1.Text that captures the selected item and stores it in a variable which is then passed to the subroutine ShowMsgBox in the regular module. Note the use of Me. which is shorthand for referencing the user form where the listbox is located (i.e. the same form as the OK button):
Private Sub okButton_Click()
sSelectedItem = Me.ListBox1.Text
ShowMsgBox (sSelectedItem)
Unload Me
End Sub
The code above calls ShowMsgBox, which is in the regular module:
Public Sub ShowMsgBox(sInput As String)
MsgBox "You selected " & sInput & ".", vbOKOnly
' Other code to do something with the selected item goes here.
End Sub
Note that in ShowMsgBox() you no longer reference the listbox, but rather work with the value sInput passed as an argument.
Hope you find this useful.
EDIT:
Following Skye's comment, here is a suggestion on how to open other forms instead of a message box. You must replace one line in okButton_Click()
, like this:
Private Sub okButton_Click()
sSelectedItem = Me.ListBox1.Text
ShowOtherUserForm (sSelectedItem)
Unload Me
End Sub
Then, in the regular module, add the sub ShowOtherUserForm(). This sub uses Select Case to check which item was selected. You can do the same job with If, but I prefer the Select style for this scenario. My example requires that you have two userforms called "OtherForm1" and "OtherForm2".
Sub ShowOtherUserForm(sInput As String)
Dim x As Object ' Must be "Object", declare "As UserForm" won't work.
Select Case sInput
Case "Item 1"
Set x = OtherForm1
Case "Item 2"
Set x = OtherForm2
End Select
x.Show
End Sub
Screenshot of result:

Userform showing when not wanted, not called for

im having some weird things happen with some code in excel
Private Sub CommandButton2_Click()
Dim thiswb As Workbook
Set thiswb = ActiveWorkbook
Call EnterDataToSS(thiswb)
Me.Hide
BeamNoFind.Show vbModal
End Sub
the called code basically drops some values into a spreadsheet.
any left over values are populated to LISTBOX1 on BeamNoFind Userform.
Then on the BeamNoFind userform there is a button and the LISTBOX1. when you select and item from listbox1, and click the button, a third userform opens (VBMODELESS) to allow placement of the value.
below is the code of the button to show the third userform.
Private Sub CommandButton2_Click()
Dim Selected_Length As String
Dim Selected_Name As String
Dim Selected_Length_index As Integer
Selected_Length_index = BeamNoFind.ListBox1.ListIndex
With BeamNoFind.ListBox1
If .ListIndex > -1 Then
Selected_Name = .Column(0, .ListIndex)
Selected_Length = .Column(1, .ListIndex)
CellInputForm.beam_length_label.Caption = Selected_Name & " [ " & Selected_Length & " ] "
BeamNoFind.Hide
'ChngDataSrc.Hide
'Unload ChngDataSrc
CellInputForm.Show vbModeless
Else
MsgBox "No selection", vbExclamation, "Oops!"
End If
End With
End Sub
the weird thing is, when i click the button to show my modeless userform, to place the data in a cell, the initial macro is being triggered that drops you into the first userform.
Where i have the commented code 'ChngDataSrc.Hide' and 'Unload ChngDataSrc' are my attempts to stop the userform from displaying when i dont want it to.
When i unload the form, i then get an error instead of the form displaying, the error is with the initial macro:
Sub get_scheduling_data(control As IRibbonControl)
ChngDataSrc.Show
End Sub
It has something to do with vbModeless because if i replace "vbModeless" from "CellInputForm.Show vbModeless" line with "vbModal", it shows correctly, without the unwanted form (ChngDataSrc). but then the function of the form (select cell, press ok button, value placed in selected cell) is gone.
I found a solution, but its not a real solution,
i placed
ChngDataSrc.Hide in the Activate sub of the CellInputForm userform.
So when CellInputForm.show vbModeless is run, and the ChngDataSrc userform pops up unwantedly, it is then hidden again.
Id rather find out why it is being showed in the first place, but this fix seems to work for now.

Changing label captions based on a combobox index?

I have a userform with a combobox that is populated with a list of client names that are stored in a hidden sheet. I am trying to make it so the user can select a name and click a button that brings up that client's profile (name address, phone number etc).
I am trying to get it to work for just the name before I do the other fields. When I view the profile the name label (which I named name_) is blank. ClientBox is the name of the combobox with the names which is on userform2, and ClientProfile is the name of the userform that has the name_ label.
The last 2 lines commented out are what I tried before I tried this method. Neither method works.
Sub ProfilePopulator()
Dim index As Integer, str As String
Application.ScreenUpdating = False
Sheets("Clients").Visible = True
Sheets("Clients").Select
Range("A1").Select
index = UserForm2.ClientBox.ListIndex
str = Cells(index + 1, 1)
ClientProfile.Name_.Caption = str
'ActiveCell.Offset(index, 0).Select
'ClientProfile.Name_.Caption = ActiveCell
End Sub
The problem wasn't actually in this part of the code (oops). It was in the code for the button that opens the ClientProfile userform. Before I had:
Private Sub CommandButton2_Click()
UserForm2.Hide
ClientProfile.Show
Call ProfilePopulator
End Sub
ProfilePopulator has to run before ClientProfile is shown, so now it looks like this and it works:
Private Sub CommandButton2_Click()
UserForm2.Hide
Call ProfilePopulator
ClientProfile.Show
End Sub

User form can't pass value to module

I've inserted a user form into a project that already contains a bunch of modules. By playing around with the code in the user form, I've verified that I can return the value from a combo box.
User form code:
Public SelectedPacking As Integer
Private Sub CancelButton_Click()
UserForm1.Hide
End Sub
Private Sub OKButton_Click()
SelectedPacking = ComboBox1.ListIndex
Call DemoDialogOk
'Return list index value to cell C50
Worksheets("Inputs & Results").Range("C50") = SelectedPacking
Unload UserForm1
End Sub
My problem is that I can't pass this value on to any of the macros written in the modules.
Module code:
Public Sub ShowComboBox()
UserForm1.Show
End Sub
Public Sub DemoDialogOk()
ival = SelectedPacking
'Return value of ival (list index value from combo box) to cell C17
Worksheets("Packed bed (Random)").Range("C17") = ival
End Sub
Obviously the module contains more useful code, but I've commented out everything to try and figure out where I'm going wrong. I've been changing some things around, but I still can't get anything to appear in cell C17, so I think I'm missing something fundamental.
I think two options: 1) change DemoDialogueOK to accept variables:
Public Sub DemoDialogOk(SelPack as integer)
' ival = SelectedPacking
Worksheets("Packed bed (Random)").Range("C17") = SelPack
End Sub
Private Sub OKButton_Click()
SelectedPacking = ComboBox1.ListIndex
Call DemoDialogOk(SelectedPacking)
...
End Sub
Or option two: fully qualify the variable from the useform i.e:
Public Sub DemoDialogOk()
ival = ufYourForm.SelectedPacking
...
End Sub
Public variables in userforms don't appear to be as "public" as module level...
Tipping on top of Simon's answer, you could pass the entire userform if you'd like. This would give you access to all the pieces of it and is especially useful if you need to do some validation on, say, different checkboxes being checked or not.
Sub inOurUserForm()
Call inADifferentModule(Me) 'Passes this userform
End Sub
Sub inADifferentModule(ourForm As UserForm1)
'Passed the form, and using it like a class (As whatever the form is called)
If ourForm.chkYes = True Then
'Do something
Else
'Do something else, like
ourForm.chkYes = False 'Because we are passing the object itself _
rather than a copy, at least in my understanding
End If
End Sub
And you don't necessarily need to pass the userform, as you could just reference it as an object itselft e.g.
UserForm1.chkYes
A very easy solution to this would be to declare a variable within the Userform (UserForm1 in this example)
Public Pass as string
This Pass would contain the string where you store the password. Once you store the password, you can hide the form
Me.Hide
Within the module, you can open the Form as modal
UserForm1.Show vbModal
Now after all the code inside the userform is run, the password can be retrieved within the module -
UserForm1.Pass
You can then unload the hidden form
unload UserForm1

Resources