I am looking for the best way to deploy Excel Macros to users. My goal is to make it super easy for end users to install and promote use by adding to the addin toolbar. I know that there are a number of help articles on this topic but couldn't find anything that covered this exact issue. Can you please help and excuse me if this is a noobie question. Please see below for replication steps for my issue.
I have added the code below as a worksheet event on "This Worksheet" of an excel macro file
I add the main code to a module that it references
I save this as an .XLAM in the addin roaming folder
I enable this as an addin in EXCEL 2013
After I install it adds the button to an add in tab
It works until I close Excel in which case the button disappears
It is still under active add ins but not on the toolbar
The code:
Option Explicit
Dim cControl As CommandBarButton
Private Sub Workbook_AddinInstall()
On Error Resume Next 'Just in case
'Delete any existing menu item that may have been left.
Application.CommandBars("Worksheet Menu Bar").Controls("Super Code").Delete
'Add the new menu item and Set a CommandBarButton Variable to it
Set cControl = Application.CommandBars("Worksheet Menu Bar").Controls.Add
'Work with the Variable
With cControl
.Caption = "Convert Survey Reporter Tables"
.Style = msoButtonCaption
.OnAction = "CMB_General_Table_Formatting"
'Macro stored in a Standard Module
End With
On Error GoTo 0
End Sub
Private Sub Workbook_AddinUninstall()
On Error Resume Next 'In case it has already gone.
Application.CommandBars("Worksheet Menu Bar").Controls("Convert Survey Reporter Tables").Delete
On Error GoTo 0
End Sub
If you want an alternative to using VBA to build the interface, I have previously deployed Excel add-ins (XLAM files) using some variety of Ribbon XML. This allows for very fine-grained control of the resulting interface and does not require you to work in VBA to build the interface. For most applications, I have found it is much easier to build the Ribbon components outside of VBA and then wire up the callbacks in VBA.
For the end user, I think this approach also delivers a better looking add-in since the resulting interface has its own Ribbon tab (or you can add to any of the existing ones) instead of being in the Add-ins Ribbon tab.
If you want to pursue this route, I highly recommend using the Ribbon X Visual Designer to build the interface and set callbacks. I have used it to build an add-in that had more than 50+ features accessible by buttons and other Ribbon form controls. It was fairly painless once I got going.
Related
I'm trying to create my own menu in Excel's (2010) Ribbon.
I wrote the following Sub to create a 'test' menu but I cannot find any evidence that the menu was created other than it being listed in the Controls Collection.
I feel like I've done everything correctly especially since I looked up bunch of code samples (example, this does not work for me either) from other people as well.
I guess my question is twofold, does the code below produce a new menu in YOUR Excel, and if so any idea why would this fail on my computer?
Sub CreateInterface()
Dim Controls As CommandBarControls
Dim CmdBar As CommandBarControl
Dim NewMenu As CommandBarControl
Set Controls = Application.CommandBars("Worksheet Menu Bar").Controls
Set NewMenu = Controls.Add(Type:=msoControlPopup, Temporary:=True, before:=Controls.Count)
NewMenu.Caption = "&Test"
NewMenu.Visible = True
For Each CmdBar In Controls
Debug.Print CmdBar.Caption & "|" & CmdBar.Tag
Next
End Sub
EDIT:
Thanks to D.O. I can see that the code is working it just isn't creating a new menu in the ribbon (like the default ones (Home, Insert, Page Layout, etc.)).
That being said to the best of my knowledge this was supposed to create a new menu, not an item in one of the menus, how can I actually create a new menu?
To the best of my knowledge, the old (pre-2007) CommandBars and Controls way is obsolete enough that it only adds buttons to the "Add-ins" ribbon tab. This is for backward compatibility with old Office solutions, so that they can still be used (somewhat) under 2007+ Office apps.
The way forward (if you plan on using Office 2007 and up) is to modify the ribbon itself. It's a completely new paradigm, and real-time customizations are done in a completely different way, but if you get the hang of it (it's not that difficult) it is quite useful.I suggest Googling some ribbon tutorials, and using the "Custom UI editor" tool to add your ribbon code to your Office files. Ron de Bruin's web site is always a good resource for more information.
The program, that I'm working on, has a separate (additional) Add-in tab in the Excel ribbon. And there are our custom controls, etc. Some of the controls open a new workbook (new Excel window).
In Excel 2010, when the new workbook is opened, our custom tab is selected by default. But in 2013, the first (Home) tab is selected.
In the project, there is no code that controls which tab to be selected by default in a newly open workbook. That is why I am wondering it works in 2010, but not in 2013?
I researched about that, but I could find mostly articles about "how to create new tab", etc.
Any ideas and suggestions are welcome.
This should be the fix you're looking for:
yourRibbonInstance.ActivateTab("tabID")
keep in mind that the id of the tab might not be the same as its displayed name.
Not sure if this might be overkill but you could use a macro that runs on the workbook open event to activate the sheet you want to see first..
Sub workbook_open()
Sheets("Sheet2").Activate
End Sub
Apologies in advance if this ends up being generic. I have done some research on this and drawn a complete blank.
Excel is great, I love Excel. So much so that the "Recent Documents" section is of almost no use to me as I use that many spreadsheets in an insane amount of locations.
I have been researching a way to log (using VBA as an AddIn) documents when they are opened. Even if it is into something as simple as a text file with the date, however I cannot figure out how to have the VBA code "know" when a file is opened (which, along with outputting to a Text file, is all I want it to do at this stage).
Is there a way to have the VBA look for this action from within an excel instance?
The following steps (adapted from the excellent post at http://www.cpearson.com/excel/AppEvent.aspx ) is the "minimally viable" way to do what you need.
open a new workbook
open the VB editor
Insert a class module; in the properties window, set class name to CExcelEvents
Add the following code in the class module:
Private WithEvents App As Application
Private Sub Class_Initialize()
Set App = Application
MsgBox "initialized the class!"
End Sub
Private Sub App_WorkbookOpen(ByVal Wb As Workbook)
MsgBox "New Workbook was opened: " & Wb.Name
End Sub
5. Right-click on the "ThisWorkbook" element in the project explorer, and select "View Code"
6. Add the following code:
Private XLApp As CExcelEvents
Private Sub Workbook_Open()
Set XLApp = New CExcelEvents
End Sub
This creates an instance of the CExcelEvents class, and "turns on event handling" when the addIn is loaded.
Finally, save the file as myEvents.xlam in the location where addIns are stored - this varies depending on your machine...
If you now close the file, and add the addIn (again, depends on your environment whether that is from the Developer ribbon or the Tools menu), you should see a dialog box that says "initialized the class!". This shows the addIn is properly installed and working.
Now, when you open a workbook, another message box will appear: "New Workbook was opened: " with the name.
Obviously you will want to get rid of the message boxes, and put in some "useful" code that does whatever you want to do (for example, log the name of the workbook to a file). It sounds to me like you don't need help with the latter - if I am wrong then please let me know.
I have a custom ribbon which works fine but I only want to enable it and have my add in show for certain workbooks so I check for the workbook title on load and try to use the Invalidate method if the condition is false. Unfortunately nothing happens the custom ribbon tab is still showing.
The following is my sub:
Public Sub loadMyRibbon(ribbon As IRibbonUI)
Set RibUI = ribbon
If Not workbookTitle = "My Workbook" Then
If Not RibUI Is Nothing
RibUI.Invalidate
MsgBox "Not Working"
End If
End If
End Sub
Which seems correct to me from reading through the method documentation:
Microsoft Documentation
I see my MsgBox message displayed on the screen so I know the code is executing correctly up to that point but RibUI.Invalidate doesn't hide my tab. Appreciate any pointers!
I have also tried:
RibUI.InvalidateControl "myTag"
But this also doesn't work
Ribbon.Invalidate doesn't mean the ribbon will not show. Invalidate function just tells the ribbon to invalidate and re-initialize the ribbon controls with their default/dynamic properties.
I worked with few Add-ins where the clients wanted to hide the ribbon items if users cannot pass the authentication. So in such a case, I used "GetVisible" attribute in all of my Control and then I used this code
Sub GetVisible(control As IRibbonControl, ByRef Visible)
On Error Resume Next
Visible = shouldShowOrNot
End Sub
shouldShowOrNot is a boolean variable, which I set in Ribbon Load to true if user passes the authentication. See the following image:
Now the above image is a representation of Ribbon in case User has failed the authentication. There might be a better way to do it, but i found it to be the best way so far.
Hope this helps,
Vikas B
I have developed a PowerPoint add-in for versions 2003 and earlier that generates a custom commandbar/toolbar on install.
I have no difficulty removing this commandbar on uninstall, but because it uses the Auto_Close event to do so, it also deletes the toolbar every time PowerPoint closes, preventing the user from permanently customizing the commandbar's position.
I've tried a conditional delete by checking if the add-in is registered or loaded, but Auto_Close seems to run before any unloading or deregistration.
Any ideas on how to delete the commandbar ONLY when the add-in is being uninstalled?
Sub Auto_Close()
Dim pptAddin As AddIn
For Each pptAddin In AddIns
If pptAddin.Name = "AddInName" And _
pptAddin.Registered <> msoTrue Then
Application.CommandBars("CommandBarName").Delete
End If
Next
End Sub
It's a good idea to do what you're doing - deleting your CommandBar when PowerPoint closes. That way if there is ever an error, your add-in doesn't leave artifacts in the UI that don't work.
For managing state though, many folks use GetSetting and SaveSetting for reading/writing to a sandboxed area in the Registry for VB/VBA programs. Look up the following functions on this page: GetSetting, SaveSetting, GetAllSettings, DeleteSetting. You can use these to manage your add-in's CommandBar between PowerPoint instances. It's relatively simple to use - here's a tutorial for Excel that would apply equally to PowerPoint.