I know you can use
Option Private Module
to hide macros from the macro list, but apparently this is not true for public functions in class modules that do not have an input parameter. Any ideas how I could hide them?
This is the public procedure in my class
Its appearing in the macro list:
If you want it to remain Public, you can pass to it an optional argument and do nothing with it, so it doesn't show up in the Macro list.
Public Sub RemoveDuplicates(Optional DoNothing As Variant)
'Macro code goes here
End Sub
Just use Private and not Public like:
Private Sub RemoveDuplicates()
' your code here
End Sub
Option Private only restrict inter-project visibility as explained in the link.
It does not hide it in the Macro List.
Related
I might miss just a stupid small detail but I don't get a hang on it.
I've created a userform with a listbox where I want the user to select one item. This is working so far as my variable "termin" has the right value before I close the user form
Private Sub OKButton_click()
termin = Eventlist.List(Eventlist.ListIndex)
MsgBox termin 'Just for testing purposes. It gives me the selected item
Unload Eventabfrage
End Sub
And this is a part of what I have in 'ThisOutlookSession':
Option Explicit
Dim termin As String
Public Sub MailMerge()
Eventabfrage.Show
MsgBox termin 'and there it is empty but shouldn't be empty
enter code here
End Sub
What do I have to do to hand over the value to my MailMerge Sub?
It is a macro in Outlook so storing it in any Excel cell is not an option.
Other than using Public variable (which I would only as the last chance since it's prone to many drawbacks), you can use UserForm class Tag property to pass info in and out an instance of a Userform and a more safe Userform instantiating and terminating scheme, as follows:
in the calling module:
Public Sub MailMerge()
Dim termin As String ' declare 'termin' as a Sub scoped variable
With New Eventabfrage ' get a new instance of the wanted userform class and reference it
.Show
termin = .Tag ' retrieve referenced userform 'Tag' property and store it in 'termin' variable
'enter code here
End With ' <-- this will unload the userform instance
End Sub
in the Eventabfrage class module
Private Sub OKButton_Click()
With Me ' reference the Userform class current instance
.Tag = .Eventlist.List(.Eventlist.ListIndex)
.Hide ' hide the userform instead of unloading it, so as to have it "alive", along with its properties (and methods) in its calling sub
End With
End Sub
I have created a button in Word which can help me to save files much more easier. I have a question related to this button from the document. I have read that it is not possible to hide or show the button. So I though I will delete the button which worked, but once the project got a bit complicated.
Private Sub CommandButton1_Click()
CommandButton1.Select
Selection.Delete
UserForm1.Show
End Sub
My questions are:
Is it possible to use hide/show command for the CommandButtton1?
If 1 is not possible then is it possible to call from UserForm the function CommandButton1 and delete it from there if a certain value is true?
Unfortunately there is no way to hide/unhide buttons in Word, but deleting them instead is a good solution for this problem.
You can simply write a method and call that method from a UserForm.
Public Sub test()
CommandButton1.Select
Selection.Delete
End Sub
Now all you need to do is call the method :
call test
Edit:
Public Sub test()
CommandButton1.Select
Selection.Delete
'All the Other code
End Sub
Private Sub CommandButton1_Click()
call test
End Sub
Now you can just call the sub test to execute the same code as the CommandButton1 does.
Hope I could help.
I was wondering if there's a way to refer to the object of the "Click()" sub.
To make it clearer, let's say we have a button named foo1 and this button has a click sub "foo1_Click()". Does vba has a keyword to get the reference to foo1 that is global?
Something like:
Public Sub foo1_Click()
GlobalKeyword.Property
End Sub
P.s.: something like the word "this" from java refering to its own instance of class
Edit: In the example, the "GlobalKeyword" would refer to "foo1"
I think you're looking for the Application.Caller property found here.
In your case you would want to do something like....
Public Sub foo1_Click()
Dim button As Shape
Set button = ThisWorkbook.Sheets("sheetname").Shapes(Application.Caller)
End Sub
Of course after that you would want to do some error checking to make sure button is not nothing.
If you want to use the same code for a lot of buttons, then you may be better of using a separate subroutine.
Private Sub foo1_Click()
Call do_something
End Sub
Private Sub foo2_Click()
Call do_something
End Sub
Sub do_something() 'called by the foo _Click event
MsgBox Application.Caller
End Sub
This way, you it is easy to maintain the core functionality for all buttons simply by updating the do_something procedure.
In a VBA project of mine I am/will be using a series of reasonably complex userforms, many of which are visually identical but have different subroutines attached to the buttons. As a result I'm not overly keen on the idea of duplicating them multiple times in order to get different functionality out of the same layout. Is it possible to have a userform detect which subroutine called it and use this in flow control? I would like to be able to do something like this:
Private Sub UserForm_Initialize()
If [the sub that called the userform is called "foo"] then
Call fooSub
else
Call barSub
End If
End Sub
My backup plan is to have the calling subroutine set a global variable flag and have the userform check that, but that seems like a rather crude and clumsy solution.
Thanks everyone,
Louis
You can use the tag property of the form. Load the form, set the property, then show the form:
Sub PassCallerToForm()
Load UserForm1
UserForm1.Tag = "foo"
UserForm1.Show
End Sub
Now that the property is set, you can determine what to do in the form:
Private Sub UserForm_Activate()
If Me.Tag = "foo" Then
Call fooSub
Else
Call barSub
End If
End Sub
You can also use public variables:
' in userform
Public Caller As String
Private Sub UserForm_Click()
MsgBox Caller
Caller = Now()
Me.Hide
End Sub
' in caller
Sub callUF()
Dim frm As New UserForm1
frm.Caller = "Test Caller"
frm.Show
MsgBox frm.Caller ' valid after Me.Hide
Set frm = Nothing
End Sub
Personally, I would not have one userform doing two disparate activities. The code would get hard to read pretty quickly, I think. Copying the layout of a userform is pretty trivial.
To copy a userform: Open a blank workbook. In the Project Explorer, drag the userform to the new workbook. Rename the userform in the new workbook. Now drag it back to the original workbook. Change the code in the userform copy.
If you absolutely don't want separate userforms, I recommend setting up a property of the userform. Userforms are just classes except they have a user interface component. In the userform module
Private mbIsFoo As Boolean
Public Property Let IsFoo(ByVal bIsFoo As Boolean): mbIsFoo = bIsFoo: End Property
Public Property Get IsFoo() As Boolean: IsFoo = mbIsFoo: End Property
Public Sub Initialize()
If Me.IsFoo Then
FooSub
Else
BarSub
End If
End Sub
I always write my own Initialize procedure. In a standard module:
Sub OpenForm()
Dim ufFooBar As UFooBar
Set ufFooBar = New UFooBar
ufFooBar.IsFoo = True
ufFooBar.Initialize
ufFooBar.Show
End Sub
I have a userform with a basic combobox and command button. When the user hits the command button, I want the UserForm to close, and the value of the combobox to be saved in a variable that can be accessed by a subroutine contained within "ThisWorkbook".
In the UserForm code:
Public employee_position As String
Public Sub CommandButton1_Click()
employee_position = Me.ComboBox1.Value
Unload Me
End Sub
In the "ThisWorkbook" Code
Private Sub GetUserFormValue()
Call Userform_Initialize
EmployeePosition.Show
MsgBox employee_position
End Sub
When "GetUserFormValue()" runs, the UserForm comes up, you can select a value in the combobox and press the command button, but when the MsgBox comes up, it displays "" (Nothing)
What am I doing wrong here?
When you Unload Me, I think you lose all information associated with the module (including the global variable). But if you use Me.Hide rather than Me.Unload, then you can access the value of the form after the routine returns. So try this:
-- userform code includes:
Public Sub CommandButton1_Click()
Me.Hide
End Sub
-- main module includes:
Private Sub GetUserFormValue()
Call Userform_Initialize
EmployeePosition.Show
MsgBox EmployeePosition.ComboBox1.Value
Unload EmployeePosition
End Sub
I think that should work.
I had the same problem, and this is how I resolved it:
If the main code is in a worksheet, and the variable is declared as public in that worksheet (e.g. in Microsoft Excel Objects -> Sheet1 (Sheet1)), the result from "Unload Me" cannot be passed from a UserForm to the worksheet code.
So to solve my problem, I inserted a new Module, and declared my public variable there. I didn't even have to move my code from the worksheet to the module... just the declaration of the public variable.
I hope this works for you too!
Andrew