How to remove a Label in UserForm? - vba

I have a UserForm with this function:
Public MyVariable As String
Private Sub UserForm_Initialize()
[...my code...]
End Sub
To call my Userform from a button i do:
Sub CallUserForm_Appro()
UserForm1.MyVariable = "Appro"
UserForm1.Show
End Sub
Sub CallUserForm_User()
UserForm1.MyVariable = "User"
UserForm1.Show
End Sub
My goal is to remove "Label1" if user click on button to call CallUserForm_Appro()
So, i tried in UserForm_Initialize() to do:
Public MyVariable As String
Private Sub UserForm_Initialize()
[...my code...]
If MyVariable = "Appro" Then
UserForm1.Controls.Remove "Label1"
End If
End Sub
I have no error but my Label1 is always visible.

This is how you set the visibility of the label to false:
UserForm1.label1.Visible = false
Then it should not be visible any more.

The `Initialize event occurs before the variable is set (because you can't access any property of the form without it being loaded first).
You should use the Activate event instead as long as the control is added at run time. If it's a design time control, you can't delete it, only hide it. Alternatively, you might only add it to the form if the variable is not set to "Appro"

Related

VBA multiple option dialog box output

I created a user form with multiple options and now I want that the option the user selects is shown in a label under the button that calls the user form.I changed the caption in the text box under the button to resemble what should happen
However my options aren't working. Should I save the output in a global variable and then call it back to change the label and if so how do I do that? Or is it possible to just call the selection within the user form?
The code I was trying to run was this one to call the message box and then change the text box which is actually a label called "labelpage"
Private Sub CommandButton1_Click()
UserForm1.Show
If UserForm1.OptionButton1 = True Then LabelPage.Caption = "Company Restricted"
If UserForm1.OptionButton2 = True Then LabelPage.Caption = "Strictly Confidential"
If UserForm1.OptionButton2 = True Then LabelPage.Caption = "Public Information (does not need to be marked)"
End Sub
I also had this for each button click just to close them after selection, within the user form code.
Private Sub OptionButton1_Click()
OptionButton1.Value = True
Unload Me
End Sub
Private Sub OptionButton2_Click()
OptionButton2.Value = True
Unload Me
End Sub
Private Sub OptionButton3_Click()
OptionButton3.Value = True
Unload Me
End Sub
Is there just a tiny mistake of syntax or something like that or is this just completely wrong? Thank you in advance for your help.
The issue is that you are unloading the UserForm, meaning the controls are not available to you. The solution is to just hide the UserForm:
Private Sub OptionButton1_Click()
Hide
End Sub
Private Sub OptionButton2_Click()
Hide
End Sub
Private Sub OptionButton3_Click()
Hide
End Sub

How to dynamically edit a excel vba form label and tab label?

I have an excel vba form which has some tabs(pages).What I need is, if I double click on label, it should be editable. same is the case for the tabs.
I tried to add some things into the double click function, but not showing any change.
Labels are not editable by the end user
you may adopt this workaround
'change "Label1" occurrences to your actual label name
Private Sub Label1_DblClick()
Me.Label1.Caption = Application.InputBox("enter label text", "label editing", "")
End Sub
You can have a TextBox and disable it. The side effect is you will have textbox edit cursor over the label.
Have two subroutines, one called Labelize and another Textboxize. The former locks the textbox, makes it tranparent, and sets the 3D effect to flat. The latter unlocks it, makes it opaque, and sets the 3D to sunken (the default).
' Makes a textbox look like a label
Private Sub Labelize(txtbox As MSForms.TextBox)
txtbox.Locked = True
txtbox.BackStyle = fmBackStyleTransparent
txtbox.SpecialEffect = fmSpecialEffectFlat
End Sub
' Makes a textbox look like a textbox
Private Sub Textboxize(txtbox As MSForms.TextBox)
txtbox.Locked = False
txtbox.BackStyle = fmBackStyleOpaque
txtbox.SpecialEffect = fmSpecialEffectSunken
End Sub
In the form initialize event set call the Labelize method passing in your textboxes.
Private Sub UserForm_Initialize()
Labelize Me.txtExample
End Sub
In the double-click event per textbox, call the Textboxize method passing in your textbox again.
Private Sub txtExample_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Textboxize Me.txtExample
End Sub
Then in each KeyDown event, check if the key pressed was enter then call the Labelize method.
Private Sub txtExample_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 13 Then Labelize Me.txtExample
End Sub

Set values on User Form using form properties

Appologies if this has been asked already, but I cannot seem to find an answer. I want to set a do something on a UserForm as it is loaded up based on the value passed to it from a property. What I have is a button on an Excel worksheet which loads the user form as follows:
Sub button()
Dim fm As New UserForm1
fm.ValueToPass = "Hello"
fm.Show
End Sub
Behind the form is the following code:
Private myString As String
Public Property Let ValueToPass(ByVal x As String)
myString = x
End Property
Private Sub UserForm_Initialize()
If myString = "Hello" Then
'Do something on my form
else
'Do something else on my form
end if
End Sub
The problem is that when the form is loaded up, the myString is empty. I believe that the reason is that the form is initialised before the property ValueToPass is set. What is the best solution to this?
You probably think that when you call:
fm.ValueToPass = "Hello"
in Private Sub UserForm_Initialize() it is possible that the myString value is passed before initializing the form. E.g., you are somehow expecting that myString can be something different than "" (thus you have the condition). This is not the case - first the _Initialize constructor is executed and then anything else is carried out:
With your code, you need somehow to tell the form, that it should update its label. Consider this inside the form:
Public Sub ShowForm()
Me.Label1 = myString
Me.Show
End Sub
Then in the module, call it like fm.ShowForm instead of fm.Show.
Actually, it is a good idea, if you work with userforms, following the Model-View-Controller pattern. For this you would need a separate class.
Userform closes after "End Sub" without ever calling "Unload Me"
Easiest way:
Sub button()
Dim fm As New UserForm1
fm.Label1.Caption = "Hello"
fm.Show
End Sub
you should be using the initialize event for this:
Sub OpenForm()
MyForm.show
end sub
Then in the initialize event of the userform, put this:
Me.LabelName.Caption = "Your label text"
(double-click the userform to view its code, then select from the top right drop-down "Initialize".)

VBA Input Value From Another UserFormB into TextBox From UserFormA

I have a userForm (mappingGuide) that allows user to pick a smartyTag from a list of more user-friendly names.
I have a second user-form (conditionalBuilder) that I would like to call this userForm upon double-clicking a text field so that a user can lookup which smartyTag to apply (in case they don't know).
So logic, is:
open conditionalBuilder
double-click Field text box
mappingGuide opens
pick a smartytag from listbox
fill smartytag value into field text-box in conditionalBuilder
unload mappingGuide
The issue I think I having with completing the requirement is that when I load the forms themselves I cannot find a way to set the text of the fieldName textbox of the loaded instance of conditionalBuilder (see last code block below). I've been searching around, but cannot figure it out.
Here is relevant code:
conditionalBuilder loads from Custom UI ribbon
Sub RunCode(ByVal Control As IRibbonControl)
Select Case Control.ID
Case Is = "mapper": LoadMappingGuide
Case Is = "conditional": LoadConditionalBuilder
End Select
End Sub
Sub LoadConditionalBuilder()
Dim conditionalForm As New conditionalBuilder
conditionalForm.Show False
End Sub
double-click event of fieldName then loads mappingGuide
Private Sub fieldName_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Me.hide
Dim pickField As New mappingGuide
pickField.Show False
End Sub
smartTag listbox click event then attempts to place selection into fieldName (or selection if form not loaded)
Private Sub smartTagList_Click()
If smartTagList.ListIndex > -1 And smartTagList.Selected(smartTagList.ListIndex) Then
Dim smartyTag As String
smartyTag = smartTagList.List(smartTagList.ListIndex, 2)
If isUserFormLoaded(conditionalBuilder.Name) Then
'*** ---> below is my issue how to reference instance of form
conditionalBuilder.fieldName.Text = smartyTag
conditionalBuilder.Show
Else
Selection.Range.Text = smartyTag
End If
End If
Unload Me
End Sub
If there is a better set-up that would be great to know too. I have the forms separate because there's a couple of levels a user can create tags with.
This is how I would do it, a bit of overkill but in case of multiple forms it will be beneficial.
Module 1:
Option Explicit
Sub test()
frmMaster.Show False
End Sub
Form 1 : frmMaster:
Option Explicit
'/ Declare with events
Dim WithEvents frmCh As frmChild
Private Sub TextBox1_DblClick(ByVal cancel As MSForms.ReturnBoolean)
handleDoubleClick
End Sub
Sub handleDoubleClick()
If frmCh Is Nothing Then
Set frmCh = New frmChild
End If
frmCh.Show False
End Sub
'/ Handle the event
Private Sub frmCh_cClicked(cancel As Boolean)
Me.TextBox1.Text = frmCh.bChecked
End Sub
Form 2: frmChild:
Option Explicit
Event cClicked(cancel As Boolean)
Private m_bbChecked As Boolean
Public Property Get bChecked() As Boolean
bChecked = m_bbChecked
End Property
Public Property Let bChecked(ByVal bNewValue As Boolean)
m_bbChecked = bNewValue
End Property
Private Sub CheckBox1_Click()
Me.bChecked = Me.CheckBox1.Value
'/ Raise an event when something happens.
'/ Caller will handle it.
RaiseEvent cClicked(False)
End Sub
You can do this with a presenter class which controls userform instances and pass values between them. I mocked up something similar to give you an idea.
Presenter. This is a class module which creates the userforms, controls their scope, and catches the event thrown by the
ConditionalBuilder. It makes it super easy to pass values between
userforms.
Private WithEvents CB As ConditionalBuilder
Private MG As MappingGuide
Public Sub ShowCB()
Set CB = New ConditionalBuilder
CB.Show vbModal
End Sub
Private Sub CB_ShowMappingGuide()
Set MG = New MappingGuide
MG.Show vbModal
CB.UpdateTB1 Value:=MG.SmartTag
End Sub
ConditionalBuilder.
This has a simple function to update your textbox and also an event which raises actions in the presenter.
Public Event ShowMappingGuide()
Public Function UpdateTB1(Value As String)
TextBox1.Value = Value
End Function
Private Sub TextBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
RaiseEvent ShowMappingGuide
End Sub
MappingGuide.
The Type and Property could be overkill since we just want one value from the mapping guide but it's still good practice.
Private Type TView
Tag As String
End Type
Private this As TView
Public Property Get SmartTag() As String
SmartTag = this.Tag
End Property
Private Sub UserForm_Initialize()
Tags.List = Array("a", "b", "c")
End Sub
Private Sub Tags_Click()
this.Tag = Tags.List(Tags.ListIndex, 0)
Me.Hide
End Sub
I have one final Standard Module which creates the Presenter. This is what you'd hook up to your ribbon.
Public Sub ShowProject()
With New Presenter
.ShowCB
End With
End Sub
Step 1 (double click text field)
Step 2 (selecting "b")
Step 3 (result)
I actually solved it by placing the below block inside the IF where I check for the form being loaded and I will leave open for better answers, if there are any.
Dim uForm As Object
For Each uForm In VBA.UserForms
If uForm.Name = conditionalBuilder.Name Then
uForm.fieldName.Text = smartyTag
uForm.Show
End If
Next

VBA EnableEvents fire textbox_change

I have a textbox with code on change, and if I press a button with the following code
Private Sub CommandButton1_Click()
Application.EnableEvents = False
TextBox1.Text = "new text"
Application.EnableEvents = True
End Sub
but this still fires the on change event of the textbox.
This happens because Application.EnableEvents allows enabling/disabling events fired from the Application (i.e. Excel).
In your case, the parent firing the TextBox1 change is not the Application but rather the UserForm. This is an example from cpearson about how to create your own EnableEvents property on your Userform. I report the content of the link here (to avoid "link-only answer"):
To suppress events in a form, you can create a variable at the form's
module level called "EnableEvents" and set that to False before
changing a property that will cause an event to be raised.
Public EnableEvents As Boolean
Private Sub UserForm_Initialize()
Me.EnableEvents = True
End Sub
Sub Something()
Me.EnableEvents = False
' some code that would cause an event to run
Me.EnableEvents = True
End Sub
Then, all of the controls on form should have a test if that variable
as their order of business in any event code. For example,
Private Sub ListBox1_Change()
If Me.EnableEvents = False Then
Exit Sub
End If
MsgBox "List Box Change"
End Sub
You can declare the EnableEvents as Private if only procedures with
that form need to suppress events. However, if you have forms that are
programmatically linked together, such UserForm2 adding an item to a
ListBox on UserForm1, you should declare the variable as Public and
set it for another form with code like the following:
UserForm1.EnableEvents = False
'
' change something on UserForm1
'
UserForm1.EnableEvents = True