I have read and applied solution I found on similar topics but nothing seem to work in my case.
So, I want to pass a variable from one sub of my Module1 to a userform. It's a string called "provinceSugg".
Here is the relevant part of my code :
Public provinceSugg As String
Sub probaCity()
[...]
If province = "" And city <> "" Then
provinceSugg = sCurrent.Cells(p, db_column).Offset(0, 1).Value
UserForm2.Label1 = "Do you mean " & city & " in " & provinceSugg & " ?"
UserForm2.Label1.TextAlign = fmTextAlignCenter
UserForm2.Show
Else
End If
End Sub
And then in my userform code :
Private Sub userformBtn1_Click()
MsgBox provinceSugg
sMain.Range("J6").Value = provinceSugg
End Sub
When I run my program :
1/ I have the content of provinceSugg showing in the MsgBox called from my sub (so there is a provinceSugg, it's not an empty variable).
2/ The MsgBox called from the userform is empty (so passing the value failed) and my program crashes when running " sMain.Range("J6").Value = provinceSugg" with something like "Error 424 Object Required" (so the variable failed to pass to the userform).
I tried all the stuff I found on forum and here (different ways to indicate that provinceSugg is a public variable but still crashing...).
Thanks in advance for your help !
You would be able to create public variables within the Userform that can be set by the Module.
These variables are only accessible within the Userform as it is loaded.
Within the Userform, declare public variables for both objects.
Public sMain As Worksheet
Public provinceSugg as string
Private Sub userformBtn1_Click()
MsgBox provinceSugg
sMain.Range("J6").Value = provinceSugg
End Sub
Within the Module, you can assess both of those variables.
Sub probaCity()
[...]
If province = "" And city <> "" Then
provinceSugg = sCurrent.Cells(p, db_column).Offset(0, 1).Value
With UserForm2
.provinceSugg = provinceSugg
Set .sMain = sMain
.Label1 = "Do you mean " & city & " in " & provinceSugg & " ?"
.Label1.TextAlign = fmTextAlignCenter
.Show
End With
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim selectColumn
selectColumn= Split(Target.Address(1, 0), "$")(0)
Call UserFormStart(selectColumn)
End Sub
Inside Main Module
Public columnSelection As String
...
Public Sub UserFormStart(ByVal columnRef As String)
'MsgBox "Debug columnRef=" & columnRef
columnSelection = columnRef
UserForm1.Show
End Sub
Inside UserForm
Private Sub UserForm_Initialize()
'MsgBox "Debug UserForm_Initialize =" & columnSelection
...
End Sub
Worksheet_SelectionChange calls a sub on the module where columnSelection is declared as public and visable from the UserForm.
I used three different variables for the Column Reference to show that there is where the UserForm has access to the Module.
The above all works and took ages to find and work out hence the submission. Happy hunting folks
If you have a hidden worksheet in your workbook, simply write the parameter to be passed to the User Form somewhere on the worksheet and go read it from there in the User Form.
Related
I'm trying to reduce repetition in my Userform Code. I've tried writing a sub that sets a SpinButton and Textbox values equal to a defined default value. How do I pass the Spinbutton/Textbox as parameters in a private sub?
Referring to them directly brings up a type mismatch error.
Here's the code that doesn't work:
Private Sub UserForm_Initialize()
Call Default_Setter(TextBox_1, SpinButton_1, 0)
End Sub
Private Sub Default_Setter(InputTextBox As TextBox, InputSpinButton As SpinButton, InputDefaultValue As Integer)
InputTextBox.Locked = True
InputSpinButton.Value = InputDefaultValue
InputTextBox.Text = InputSpinButton.Value
InputTextBox.ControlTipText = "Value between " & InputSpinButton.Min & " and " & InputSpinButton.Max
End Sub
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.
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
I have created a UserForms with a comboBox (dropdown).
And i have also written sub in a module.
I want to call the userforms in the one the steps of the sub, like a Inputbox.
The userforms
I have written the a Public Sub UserForm_Initialize() in userforms code
Public Sub UserForm_Initialize()
Dim t
UserForm.Show
t = ComboBox1.Value
End Sub
My code in the module :
Sub Ingestion()
Dim x, z
Dim rRange
Sheets("Time Log").Select
x = Range("H300").End(xlUp).Row
If Range("A" & x).Value <> "" Then
z = InputBox("Please confirm the Task type")
Range("B" & x) = z
End If
End Sub
Now I want to change the Input box to the combobox.
but if i call this in the module, it throws an Error :
Sub Test()
Call UserForm_Initialize
End Sub
Sub or Function Not Defined
Basically, i am trying to create a Inputbox with drop down options.
A UserForm_Initialize event gets executed as soon as, surprise, the userform is initialized. So, trying to show the UF when it's already being opened is illogical. Next to that you'd have to refer to the correct UF name, in this case that would result in TaskList.Show.
You open the UF outside of the UF's code module. For example
Sub openUF()
TaskList.Show
End Sub
Then you can execute code inside the UF's module. These are usually bound to objects on the UF, e.g.:
Sub CommandButton_Click() 'in case the UF has a command button and a combobox
MsgBox "You picked '" & Me.ComboBox1.Value & "'.", vbInformation, "Help"
End Sub
I am experimenting with the capabilities of a User Form to assist in Data entry. I would like to know if there is a specific code that can transfer the Value of a Checkbox to a Text box that is on the same User Form when the box is checked. Basically, instead of having to type all of the words out, it would be easier to simply check a series of boxes to create the sentence. I know how to input the Checkbox value into the Excel worksheet but I have yet to figure out how to have that same value entered into a Text Box that would provide a "Preview" of the sentence for editing purposes and then the data can be transferred to the Excel Worksheet once it has been approved in the User Form. In my attached example that I had created and I have a before and the desired after result of what I am looking to do.
Thank you
JLY Test form:
EDIT:
Though really, you'd be best off using a listbox, much easier and shorter code. Put your list of items in a worksheet and set that to a dynamic named range so you can edit it and the userform will pick it up on the fly. Make sure the listbox has a MultiSelect property set to fmMultiSelectExtended and the ListStyle property is set to fmListStyleOption. Then you can select multiple entries in the listbox by holding the Ctrl key.
In this example if have put it in Sheet1 (though can be any sheet, and the sheet can even be hidden), and then set a dynamic named range named listProperties to this formula: =Sheet1!$A$2:INDEX(Sheet1!$A:$A,MAX(2,ROWS(Sheet1!$A:$A)-COUNTBLANK(Sheet1!$A:$A)))
Then the userform has this code:
Private Sub listJewelryProperties_Change()
Dim sTemp As String
Dim i As Long
For i = 0 To Me.listJewelryProperties.ListCount - 1
If Me.listJewelryProperties.Selected(i) = True Then sTemp = sTemp & " " & Me.listJewelryProperties.List(i)
Next i
Me.txtPreview.Text = WorksheetFunction.Trim(sTemp)
End Sub
Private Sub UserForm_Initialize()
Me.listJewelryProperties.Clear
Me.listJewelryProperties.List = ActiveWorkbook.Sheets("Sheet1").Range("listProperties").Value
End Sub
And this is what the results look like:
Original Answer Here for Posterity:
Alternate solution, set all your checkboxes to call a function and pass an argument of their value and caption, then the function will update the textbox. The reason for using the .Tag property is to avoid removing too much due to duplicates in partial matches for the checkboxes (such as Ring and Ring Band where just plain Ring can be found within Ring Band, this way it will only remove the Ring entry, and not incorrectly remove both Ring entries)
Private Sub chk14ktWhiteGold_Click()
UpdatePreview Me.chk14ktWhiteGold.Value, Me.chk14ktWhiteGold.Caption
End Sub
Private Sub chkAntique_Click()
UpdatePreview Me.chkAntique.Value, Me.chkAntique.Caption
End Sub
Private Sub chkArtisinal_Click()
UpdatePreview Me.chkArtisinal.Value, Me.chkArtisinal.Caption
End Sub
Private Sub chkBand_Click()
UpdatePreview Me.chkBand.Value, Me.chkBand.Caption
End Sub
Private Sub chkHandCarved_Click()
UpdatePreview Me.chkHandCarved.Value, Me.chkHandCarved.Caption
End Sub
Private Sub chkHandEtched_Click()
UpdatePreview Me.chkHandEtched.Value, Me.chkHandEtched.Caption
End Sub
Private Sub chkHandmade_Click()
UpdatePreview Me.chkHandmade.Value, Me.chkHandmade.Caption
End Sub
Private Sub chkRing_Click()
UpdatePreview Me.chkRing.Value, Me.chkRing.Caption
End Sub
Private Sub chkRingBand_Click()
UpdatePreview Me.chkRingBand.Value, Me.chkRingBand.Caption
End Sub
Private Sub chkSterlingSilver_Click()
UpdatePreview Me.chkSterlingSilver.Value, Me.chkSterlingSilver.Caption
End Sub
Private Sub chkVintage_Click()
UpdatePreview Me.chkVintage.Value, Me.chkVintage.Caption
End Sub
Private Sub UpdatePreview(ByVal bChkState As Boolean, ByVal arg_sText As String)
If bChkState = True Then
Me.txtPreview.Text = WorksheetFunction.Trim(Me.txtPreview.Text & " " & arg_sText)
If Len(Me.txtPreview.Tag) = 0 Then
Me.txtPreview.Tag = arg_sText
Else
Me.txtPreview.Tag = Me.txtPreview.Tag & "|" & arg_sText
End If
Else
Me.txtPreview.Tag = Replace("|" & Me.txtPreview.Tag & "|", "|" & arg_sText & "|", "|")
Me.txtPreview.Text = WorksheetFunction.Trim(Replace(Me.txtPreview.Tag, "|", " "))
End If
End Sub
Something like below will do that for you, as I don't know the names of your UserForm or your Checkboxes, you will have to amend as required, also you will have to add the following code to each of the CheckBoxes Click Event:
Private Sub CheckBox1_Click()
UserForm1.TextBox1.Text = UserForm1.TextBox1.Text & " " & CheckBox1.Caption
End Sub
UPDATE:
To also remove when checkbox is unchecked, the following code will do that:
Private Sub CheckBox1_Click()
If CheckBox1.Value = True Then
UserForm1.TextBox1.Text = UserForm1.TextBox1.Text & " " & CheckBox1.Caption
Else
pos = InStr(UserForm1.TextBox1.Text, CheckBox1.Caption)
If pos > 0 Then UserForm1.TextBox1.Text = Replace(UserForm1.TextBox1.Text, " " & CheckBox1.Caption, "")
End If
End Sub