How to use the results of User Form in another macro? - excel

I have a userform, lets say when I click the button name in the userform it will request me to enter a name and it is always stored in
private sub button_click()
name = inputbox("Please enter your name:")
end sub
The thing I want is, when I start the macro first user form will appear then after user enters the necessary information, the variables values' will last until the end of the main macro.
I am searching for last two days couldn't find a solution but who knows maybe I couldn't find it. Therefore, i am writing here. Thanks in advance!
`
another question related:
lets say I have
Public plant As Variant
Public checking As Variant
Public MeanCov1 As Variant
Public MeanCov2 As Variant
Public MeanCov3 As Variant
Public WeekCov1 As Variant
Public WeekCov2 As Variant
Public WeekCov3 As Variant
Public RolLow As Variant
Public RolHigh As Variant
Public ServiceLevel As Variant
Public TrendMultiplier As Variant
Public WeekCov11 As Variant
Public WeekCov22 As Variant
Public WeekCov33 As Variant
Sub initialize()
MeanCov1 = 0.3
MeanCov2 = 0.5
MeanCov3 = 0.7
WeekCov1 = 18
WeekCov2 = 13
WeekCov3 = 8
WeekCov11 = -14 + WeekCov1
WeekCov22 = -14 + WeekCov2
WeekCov33 = -14 + WeekCov3
RolLow = 0.3
RolHigh = 0.7
TrendMultiplier = 4
ROL_Analysis.Show
Application.Run ("ROL_Analysis_Macro")
End Sub
I can not initialize the public variables, for example in user form it says show variable values but when I click it is completely empty
Private Sub ROLparameter_Click()
Line1: RolLow = InputBox("Please enter the lower bound percentage for ROL calculation between 0 and 100 (initially " & RolLow & "%):")
If Not 0 <= RolLow <= 100 Then GoTo Line1
Line2: RolHigh = InputBox("Please enter the upper bound percentage for ROL calculation between 0 and 100 (initially " & RolHigh & "%):")
End Sub

To access a variable in a different sub, you define it globally
Public Name As String
Private Sub button_click()
Name = InputBox("Please enter your name:")
End Sub
Sub Foo()
MsgBox Name
End Sub
and for your second question, if you are clicking on the buttons, then for the below code you will get a alert if you have clicked the button which corresponds to the name you typed in the InputBox
Public name As String
Sub button_click()
name = InputBox("Please enter your name:")
End Sub
Private Sub button1_click()
If name = "john" Then
MsgBox name
End If
End Sub
Private Sub button2_click()
If name = "james" Then
MsgBox name
End If
End Sub
Private Sub button3_click()
If name = "david" Then
MsgBox name
End If
End Sub

As was said, define a variable globally to access it in different subs and different modules. I have a very simple example here for you. I created a module called Module1. Here is all its code:
Option Explicit
Public name As String
Sub Test()
name = "David"
UserForm1.Show
MsgBox "The userform has closed"
End Sub
I also created a userform called UserForm1. Here is all the code and a screenshot of it:
Option Explicit
Private Sub CommandButton1_Click()
MsgBox Module1.name
End Sub
How it works:
If I launch Module1, the public variable name gets set to "David". In your case you could set it to whatever you want with your inputbox. After that, the userform is launched with .Show and the Module1 stops reading code until you're done with UserForm1.
While Userform1 is active, clicking the button will open a MsgBox saying "David", because I access the public variable Module1.name. I always specify which module the public variable comes from. When I close the userform, Module1 gets activated again and I get a msgbox saying "The userform has closed".
Does this answer all your questions?
Clicking the button:
Closing the form:

Related

Set a variable name to a Workbook selected from a VBA ComboBox

I will always have Workbook SQ_Macro_v1 as my main DB.
Two named Workbooks old_wk and new_wk will have different names, as I will choose them among the currently active WB on my computer.
I am going for a VBA ComboBox listing it all to a choice of mine, but in the end I am not able to store the name of my chosen WB.
Sub Macro1()
Dim main_wk, old_wk, new_wk As Workbook
Set main_wk = Workbooks("SQ_Macro_v1.xlsm")
Set old_wk = Workbooks(old_chosen) 'also tried UserForm1.ComboBox1.Value
Set new_wk = Workbooks(FileName_New) '
main_wk.Sheets("Main_DB").Range("C4").Value = old_wk.Worksheets("Sheet 1 Synthese").Range("C35").Value
As I run the UserForm code below, the old_chosen variable I set as empty in the main Sub. It seems that as I close the UserForm after it runs, nothing remains stored. Any clues to keep that variable saved after I close the UserForm?
Option Explicit
Public Sub UserForm_Activate()
Dim vWorkbook As Workbook
ComboBox1.Clear
For Each vWorkbook In Workbooks
ComboBox1.AddItem vWorkbook.Name
Next
End Sub
Public Sub CommandButton1_Click()
If ComboBox1.ListIndex <> -1 Then
Call YourMacro(ComboBox1)
End If
End Sub
Public Sub YourMacro(vWorkbookName As String)
Dim old_chosen As String
old_chosen = Me.ComboBox1.Value
MsgBox "You choose: " & Workbooks(vWorkbookName).Name
End Sub
The MsgBox pops up but no value is stored afterward:
Public Sub YourMacro(vWorkbookName As String)
Dim old_chosen As String
old_chosen = Me.ComboBox1.Value
MsgBox "You choose: " & Workbooks(vWorkbookName).Name
End Sub
You have declared the variable at procedure level and hence it is not visible after the userform is closed.
To make this variable available to all procedures in the project, precede it with the Public statement. Insert a module and paste this there
Public old_chosen As String
Having said that, I would recommend moving Macro1 inside the userform and handle the code from there after declaring the variable at module level

UserForm allowing a User to Update a certain or multiple bits of an existing Private Sub Code

Would anyone know if it possible or have any ideas on how I could allow a user to update certain parts of a existing Private Sub Code?
For example:
Current: UserForm_Initialize Textbox1 = "Test"
After User Update: UserForm_Initialize TextBox1 = "Hello"
Supposing that you need the form opening next time displaying the last text used in TextBox1, please use the next approach:
Copy the next declarations on top of the form code (in the declarations area):
Option Explicit
'It is good to use relevant constants, able to better reflect their meaning:
Private Const MyApp As String = "MyApplication"
Private Const Sett As String = "Settings"
Private Const Txt1 As String = "Txt1Val"
Put this code in the TextBox1 Change event:
Private Sub TextBox1_Change()
SaveSetting MyApp, Sett, Txt1, TextBox1.Text
End Sub
Copy the next code in the Userform_Initialize event:
Dim Txt1Val As String
Txt1Val = GetSetting(MyApp, Sett, Txt1, "No value")
If Not Txt1Val = "No value" Then Me.TextBox2.Text = Txt1Val
Now, when the user change the TextBox1 text, the new string is memorized in Registry and used to to be load during the next UserForm initialization...
If something unclear, do not hesitate to ask, please.

Is it possible to hook CommandBarComboBox.Change event such that when a change has been made from Excel VBA code it fires event?

I have a ComboBox control on a custom CommandBar. I want to detect when a change has been made to the ComboBox and run some code.
This works fine when the user changes the value in the ComboxBox, but if some other VBA code changes it, the Event is not fired.
I have taken the code from here: https://learn.microsoft.com/en-us/office/vba/api/office.commandbarcombobox.change
and modified it slightly to delete a CommandBar with the same name so I can run it a number of times. I have then added another function to change the value of the ComboBox programmatically. When I change the value programmatically it can be seen to change on the Excel GUI, but the event code does not fire.
I have also tried the easier OnAction method, rather than hooking events, both seem to give the same result.
In a ClassModule called ComboBoxHandler I have the following code:
Private WithEvents ComboBoxEvent As Office.CommandBarComboBox
Public Sub SyncBox(box As Office.CommandBarComboBox)
Set ComboBoxEvent = box
If Not box Is Nothing Then
MsgBox "Synced " & box.Caption & " ComboBox events."
End If
End Sub
Private Sub Class_Terminate()
Set ComboBoxEvent = Nothing
End Sub
Private Sub ComboBoxEvent_Change(ByVal Ctrl As Office.CommandBarComboBox)
Dim stComboText As String
stComboText = Ctrl.Text
Select Case stComboText
Case "First Class"
FirstClass
Case "Business Class"
BusinessClass
Case "Coach Class"
CoachClass
Case "Standby"
Standby
End Select
End Sub
Private Sub FirstClass()
MsgBox "You selected First Class reservations"
End Sub
Private Sub BusinessClass()
MsgBox "You selected Business Class reservations"
End Sub
Private Sub CoachClass()
MsgBox "You selected Coach Class reservations"
End Sub
Private Sub Standby()
MsgBox "You chose to fly standby"
End Sub
In a module I have the following:
Private ctlComboBoxHandler As New ComboBoxHandler
Sub AddComboBox()
Set HostApp = Application
On Error Resume Next
CommandBars("Test CommandBar").Delete
Dim newBar As Office.CommandBar
Set newBar = HostApp.CommandBars.Add(Name:="Test CommandBar", Temporary:=True)
Dim newCombo As Office.CommandBarComboBox
Set newCombo = newBar.Controls.Add(msoControlComboBox)
With newCombo
.AddItem "First Class", 1
.AddItem "Business Class", 2
.AddItem "Coach Class", 3
.AddItem "Standby", 4
.DropDownLines = 5
.DropDownWidth = 75
.ListHeaderCount = 0
End With
ctlComboBoxHandler.SyncBox newCombo
newBar.Visible = True
End Sub
Sub test()
Dim newBar As Office.CommandBar
Set newBar = Application.CommandBars("Test CommandBar")
Dim cmbox As Office.CommandBarComboBox
Set cmbox = newBar.Controls(1)
cmbox.Text = "Business Class" ''<< I was hoping this would fire an event, but it does not! Same is true if I
End Sub
First I run AddComboBox and the events work fine if I manually change the ComboBox.
Then I run test() and the value displayed inside the ComboBox changes, but the event does not fire.

Global variable not accessible in different sub?

I declared projname globally at the top of the module 1. It is assigned in the userform, and is successfully accessed in the createWB sub. However, when I go to access it in the addWindow sub also in module 1, it becomes empty (""). I'm unsure of why this is happening because I thought that since the variable was globally declared I should be able to access it in any sub.
Module 1
Option Explicit
Public outputWorkbook As Workbook
Public globalcounter As Integer
Public projname As String
Public projnum As String
createWB()
Dim uf2 As New UserForm2
uf2.Show
Set outputWorkbook = Workbooks.Add(xlWBATWorksheet)
outputWorkbook.SaveAs Filename:=Environ("userprofile") & "\Desktop\" &
Replace(projname, " ", "") & ".xlsx"
outputWorkbook.Activate
Range("B3") = projname
Range("B4") = projnum
End Sub
addWindow()
Workbooks(Replace(projname, " ", "") + ".xlsx").Activate
End Sub
Userform Code
Public Sub CommandButton1_Click()
projname = Me.TextBox1.Text
projnum = Me.TextBox2.Text
Me.Hide
End Sub
Cells B3 and B4 are assigned the correct value, but the addWindow() line causes a subscript out of range error. When I test it with Debug.Print, I see that projname = "". I also simply tried outputWorkbook.Activate, which did not work either.
Avoid Global Pollution
Unless there is a really good reason to use them, try to avoid global variables. We want to avoid polluting the global namespace. Captain Planet warned us of that.
Instead, try passing your parameters through your various methods as they are needed. This helps prevent errors, makes your code easier to follow, and utilizes composition.
Using your userform to store and expose your properties
Try to instantiate your userform using a With statement so that you have a captured instance of it where you have access to its various properties that you expose. In your case ProjectName and ProjectNumber.
Additionally, there should be a property to check if the userform was canceled or the X button was pressed.
You userform would look something like this:
Option Explicit
Private cancelled As Boolean
Public Property Get ProjectName() As String
ProjectName = TextBox1.Value
End Property
Public Property Get ProjectNumber() As Long
ProjectNumber = TextBox2.Value
End Property
Public Property Get IsCancelled() As Boolean
IsCancelled = cancelled
End Property
Private Sub CommandButton1_Click()
Me.Hide
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()
cancelled = True
Hide
End Sub
Instantiating the userform
Here is the example of now calling your userform (P.S. Change the name from Userform2). Notice we are capturing our instance of your userform using the With block. Within this block, we have access to the properties we exposed: ProjectName, ProjectNumber, IsCancelled.
Private Sub createWB()
With New UserForm2
.Show
If Not .IsCancelled Then
' Do neccessaray steps here...
' You have access to ProjectName and Project number.
' Pass this to your addWindow method.
addWindow .ProjectName
End If
End With
End Sub
The ProjectName now can be accessed from your userform and passed as a parameter to you addWindow method.
Private Sub addWindow(ByVal projName As String)
Workbooks(Replace(projName, " ", "") + ".xlsx").Activate
End Sub
For more information on using userforms in this way see this helpful Rubberduck Blog Post.
could you try using Module1 as prefix? , jus like in this code
Public Sub CommandButton1_Click()
Module1.projname = Me.TextBox1.Text
Module1.projnum = Me.TextBox2.Text
Me.Hide
End Sub

How to call a global string variable

I have the following global variable:
Option Explicit
Public locationCode As String 'Access the locationCode on the form anywhere on the project
Public Sub Settings()
'Declaration to access the data entered in the
'locationCode from anywhere on the project
locationCode = frmEnterLocation.txtLocationCode.Value
End Sub
But when I try to use my variable on another part of the project for example here:
Private Sub cmdOKButton_Click()
frmEnterLocation.txtLocationCode.SetFocus
If locationCode = "" Then
MsgBox "You have not entered a Location Code", vbCritical, "Please Enter a Location Code"
frmEnterLocation.txtLocationCode.SetFocus
Else
Unload Me
End Sub
The variable is not storing the value from the text box. How can I properly call this property on my Sub?
Assign value from text box via text box Change Event in Form code module
You have to assign the text box value after each change in text box txtLocationCode from within the user form to get it stored:
Private Sub txtLocationCode_Change()
' assign new value to global variable after each change in text box txtLocationCode
locationCode = Me.txtLocationCode.Value
End Sub
Calling the Userform from a Standard code module
To make your settings you just show an instance of the userform after global declaration of your locationCode and a variable that restores the old value after user abortion via red [x] (see the last section below Sub UserForm_QueryClose).
Option Explicit ' declaration head of a standard code module
' Access the locationCode on the form anywhere on the project
Public locationCode As String
Public locationCodeOld As String
Sub Settings()
With New frmEnterLocation
.Show vbModeless
End With
End Sub
Note: The With New .. statement allows you to unload (destroy) the called userform instance properly.
Complete Userform code module (without UserForm_QueryClose -> see below)
Option Explicit
Private Sub txtLocationCode_Change() ' << as discussed above
' assign new value to global variable after each change in text box txtLocationCode
locationCode = Me.txtLocationCode.Value
End Sub
Private Sub cmdOKButton_Click()
' SetFocus isn't executed after MsgBox, so use a Label1 info
If locationCode = "" Then
Me.Caption = "No Location Code entry yet"
Me.Label1.Caption = "Please Enter a Location Code"
Me.txtLocationCode.SetFocus
Else
Me.Caption = "Location code is " & locationCode
Me.Label1.Caption = "Location Code"
Me.Hide
End If
End Sub
Private Sub UserForm_Activate()
' remember old setting of locationCode
locationCodeOld = locationCode
' display current setting in text box and headers
Me.txtLocationCode.Value = locationCode
Me.txtLocationCode.SetFocus
Me.Caption = "Location code is " & IIf(Len(locationCode) = 0, " not yet entered", locationCode)
Me.Label1.Caption = IIf(Len(locationCode) = 0, "Please enter ", "") & "Location Code"
End Sub
Recommended Addition to userform code module
This allows you to restore the old value after user abortion via red [x]:
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
' Reset old locationcode if form is aborted by user via [x}
If CloseMode = VbQueryClose.vbFormControlMenu Then
Cancel = True
locationCode = locationCodeOld
locationCodeOld = ""
Me.Hide
End If
End Sub
Put Public locationCode As String in the Declarations area (i.e. at the top) of a standard public module code sheet, not a private worksheet code sheet.

Resources