In Outlook 2010 VBA run a macro whose name was passed as a parameter - vba

I am in Outlook 2010 in Windows 7 writing in VBA and want to pass the name of a macro (or sub routine) as a string variable to another sub routine and have that routine run the macro. In Word you can do this with
Application.Run MacroName:=strMacroName
Where strMacroName is a string variable with the name of the macro. That approach does not work in Outlook 2010. How can I accomplish the same thing?
I tried
Call Application.strMacroName
Call strMacroName
strMacroName on its own line
Outlook.Application.strMacroName
None of those things worked.
I just upgraded to Outlook 2010 and so can no longer use keyboard shortcuts to run custom code for handling email. So to restore some version of that functionality I have created code to present a dialog box with my most common macros. The code is fairly clean to modify as time goes along and pass along the name of the macro I want to run but I used to be able to run that routine in one command (Application.Run MacroName:=strMacroName).
Now I have to include a long switch statement to accomplish the same thing. Not nearly as simple.
Thanks!

CallByName seems the only way to go.
With this code in ThisOutlookSession:
Public Sub TestFoo()
Dim testClass As New TestClass1
CallByName testClass, "TestMethod1", VbMethod
End Sub
And this code in TestClass1:
Public Sub TestMethod1()
MsgBox "huzzah!"
End Sub
Calling ThisOutlookSession.TestFoo gives you the expected message box.

As far as I can tell, the only way to run a named macro programmatically in Outlook (without using custom Classes, as the other answer here does) is to create a temporary CommandBarButton, execute it, and immediately delete it. This works in Outlook 2013 even with the Ribbon:
Public Sub runProc(procToRun As String)
With Application.ActiveExplorer.CommandBars.Add("Custom", temporary:=True)
With .Controls.Add(msoControlButton, 1, , , True)
.OnAction = procToRun
.Execute
.Delete
End With
.Delete
End With
End Sub
I know this is an old question, but I was unable to find this exact answer myself in late 2017, so hopefully it will help someone else. Please note that this will NOT run macros that are in ThisOutlookSession...your macro needs to be in a code module.

Related

Remove partial string from macro added to Outlook ribbon

I have templates I'm trying to add to users' PCs and have these templates easily accessible in the ribbon. I've been mostly successful except that the name of each macro is far too long.
It was Project1.ThisOutlookSession.OpenTemplate1. I realized the last portion was the name of the sub for opening that particular template. Then I realized I could change "Project1" to anything, whereby shortening the string.
I was wondering how I could go about changing the ThisOutlookSession portion or even better, remove the "Project1.ThisOutlookSession" portion altogether, leaving us with only whatever we name the sub (which will be the template name). My code:
'https://www.slipstick.com/outlook/hyperlink-templates/
Dim template As String
Sub OpenTemplate1()
template = "...Microsoft\Templates\FollowUpOnOrgSurvey.oft"
MakeItem
End Sub
Sub OpenTemplate2()
template = "...Microsoft\Templates\How Are We Doing.oft"
MakeItem
End Sub
Sub OpenTemplate3()
template = "...Microsoft\Templates\Option1.oft"
MakeItem
End Sub
Sub OpenTemplate4()
template = "...Microsoft\Templates\Option2.oft"
MakeItem
End Sub
Private Sub MakeItem()
Set newItem = Application.CreateItemFromTemplate(template)
newItem.Display
Set newItem = Nothing
End Sub
ThisOutlookSession is a default module name where your VBA macro resides. If you remove that part from the macro name there is a change the VBA sub will not be found at all.
I'd recommend creating a COM add-in instead of VBA macros. They were designed especially for distributing your Office based solution on multiple machines. VBA macros are not designed for distributing on multiple machines. See Walkthrough: Creating Your First VSTO Add-In for Outlook to get started quickly.
Also you may find the To distribute Microsoft Outlook VBA code to other users article helpful.

Is there a way to hide macros in Excel?

I just finished some VBA and I was wondering if there is a way to hide certain macros on Excel.
I need the user to run a certain macro and only that one, but it shows all the sub macros in Excel. I want to hide the unnecessary macros from the user so that way the user doesn't accidentally click on the wrong one.
You can also do this by placing the macros you want to hide in a separate module and using Option Private Module at the top of the module before the code. The macros will still be available to your project but will not appear in the Macros seen by the user when he clicks the Macros button.
You can either create a button in the ribbon to run the macro, or you can add "Private" before each "Sub" in the VBA editor that you don't want the user to easily access.
To subjectively 'hide' certain sub procedures (i.e. 'macros') from the (Alt+F8) Developer, Macros dialog use an optional non-variant parameter that means nothing.
Sub meh(Optional w As Worksheet)
Debug.Print "hello world"
End Sub
The meh macro will not show up in the list of macros to run. If you dim the parameter as variant it will show in the list. This is likely due to a optional variant parameter being able to use the IsMissing function. It will also not be able to be run from the VBE with F5 or stepped through with F8.
The test sub procedure will run the code correctly.
Sub test()
meh
End Sub
Sub meh(Optional w As Worksheet)
Debug.Print "hello world"
End Sub

Macros not showing up in the run macro menu

I started learning VBA and I don't understand why some macros copy-pasted from the internet do not show up in the run macro menu (Alt-F8).
Below there are 2 macros, but only the second one is showing. Why? And how do I fix it?
Sub Test1(ByVal Target As Hyperlink)
'...
End Sub
Sub Test2()
'...
End Sub
Macros with arguments are not available in Macros list because they cannot be run alone instead they are called by another macro by passing the required arguments.
If a Sub declaration contains parameters it will not show there.
You cannot call macros that have parameters as you are describing. If you need to have a parameter, you can take it out and then have the user input the value.
Sub Test1()
Dim hyperLink As String
hyperLink = InputBox("Please input hyperlink", "My Parameter")
'...
End Sub
Alternatively, if the hyperlink is in your document, grab the value from your document instead.
Here are my 5 cents - if you give an optional parameter, you will be able to call the sub routine, even if it will not be shown among the ones which you can chose from.
Write aaaaTestMe and press Run.
Public Sub aaaaTestMe(Optional lngA As Long = 8)
Debug.Print lngA
End Sub
You can call an even private macro from any excel object you can assign a macro, calling it this way:
'MyWorkbook'!'MyModule.MyProcedure "MyParameter1"'
(be careful with single quotes: ' around procedure name with parameter)

Running Macros from Toolbar/Running one macro from another

I am trying to develop a macro for a publisher document. This macro will, when run, show a pop-up allowing the user to select one of three types of clients, and add different bullet points to a text box depending on which option was selected. I'm having two different problems which I suspect are coming from the same source. Problem number one is that I can't get the button on my User Form to run a different macro when the button is clicked. Problem two is that I've added my macros to one of the toolbars, and nothing happens when I click on them. In both cases, it's simply not running the macro. What am I doing wrong?
UserForm1
Private Sub CommandButton1_Click()
Application.Run ("ShapeTest")
End Sub
Private Sub UserForm_Initialize()
With ListBox1
.AddItem ("Federal")
.AddItem ("State")
.AddItem ("Local")
End With
End Sub
ThisDocument
Private Sub GenerateStatement()
UserForm1.Show
End Sub
Private Sub ShapeTest()
MsgBox ("Hello!")
Application.ActiveDocument.Pages(1).Shapes(1).TextFrame.TextRange.InsertAfter`enter code here`(Chr(13) & "My Text")
End Sub
Why are you using Application.Run("ShapeTest") rather than simply ShapeTest?
I don't have enough information to be 100% sure, but the following should work: To make ShapeTest callable from the userform you do two things:
1) Move it from ThisDocument to a general code module (first Insert/Module in the editor).
2) Eliminate the word Private in front of Sub ShapeTest()-- you don't want this to be a private sub since you want code outside of the module to be able to use it.
On edit: Alternatively -- you could keep ShapeTest() where it is in ThisDocument, get rid of the Private qualifier and in the userform code refer to ShapeTest as ThisDocument.ShapeTest. I prefer using the first method since I tend to like to keep as much code as possible in general code modules (reserving things like ThisDocument for event handlers) but OTOH my VBA experience is mostly Excel with a smattering of Word and there might be reasons to keep the code in ThisDocument in Publisher. I don't know Publisher, but a problem that I have run into in Word at times is I have sometimes accidentally put code in the Normal template that I wanted to go in the document's project. If something similar is possible in Publisher you should double check where your code is living.

vba private scripts

I know that even private vba scripts can be called by the user, such that making it "private" in fact only hides its name.
However, is there a way to set up a macro so it is only runnable if you are inside that particular VBA project? Not from Excel and not from any VBScript or the likes.
If you want to lock down the code you could
make the code private so the macro names areen't exposed
lock the protect, and then test that the project is actually unlocked before letting the code run
The sample code below checks that the VBA in the host workbook is not protected before running
Does this meet your needs?
Private Sub TestMe()
Dim objVB As Object
Set objVB = ThisWorkbook.VBProject
If objVB.Protection = 0 Then
Call TestSub
Else
MsgBox "Sorry sport - unauthorised", vbCritical
End If
End Sub
Private Sub TestSub()
MsgBox "Project unprotected - i've been run", vbOK
End Sub
Honestly, there is no foolproof way around it. You can have certain checks but that's all you can do.
If you are sure that a user will not have access to VBA Code then what brettdj suggested is the best way to go ahead. Protect your project. One cannot run a macro from Excel or from outside Excel if one doesn't know the macro name ;)
The basic intention of making a macro Private is not to prevent it from running but making it invisible to the user. Mostly, the only macros that needs to be private in Excel are the inbuilt Worksheet or Workbook events or macros referred by other macros which necessarily don't need to be accessed by the user. A user can still access them from outside VBA if he or she wants to.
Having said that, you can restrict (But not STOP - Not referring to disabling your macro security) the macros from running. Pass an authorization FLAG. Only when it receives an "Authorization", will it run.
For Example
Option Explicit
Private Sub Sample(Auth As Boolean)
If Auth = True Then
'~~> Your macro code goes here
End If
End Sub
Now if you want this macro to be called from VBA then you have to call it like this
Sample True
or
Call Sample(True)
This will ensure that the above macro will only run when you allow it to.
Would this method prevent user from running this from VBS?
NO. It won't. However, it won't run till the time the user specifies or gives the "Authorization"
HTH