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
Related
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
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.
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.