Excel Add-In Context Menu Buttons - vba

I have an Excel Add-In that I have created ( .xlam file ) I am trying to have this add-in create buttons on the right click menu so that I can quickly run a macro based on the selected cell. I added code to ThisWorkbook, and it works in the xlsm file. (I copied the code from HERE.) I SaveAs to an xlam, load the add-in, and I get nothing on the context menu. I have a feeling these subs do not load through the add-in. However, I can get code in Workbook_Open to function. Can someone point me in the right direction?
Private Sub Workbook_Deactivate()
On Error Resume Next
With Application
.CommandBars("Cell").Controls("Open Drawing").Delete
End With
On Error GoTo 0
End Sub
Private Sub Workbook_SheetBeforeRightClick(ByVal Sh As Object, ByVal Target As Range, Cancel As Boolean)
Dim cmdBtn As CommandBarButton
On Error Resume Next
With Application
.CommandBars("Cell").Controls("Open Drawing").Delete
Set cmdBtn = .CommandBars("Cell").Controls.Add(Temporary:=True)
End With
With cmdBtn
.Caption = "Open Drawing"
.Style = msoButtonCaption
.OnAction = "Open_Drawing_Main"
End With
On Error GoTo 0
End Sub

You have to use AddinInstall event. I assume that your context menu procedure works fine. So double click on ThisWorkbook in the add-in file (before you install it and save it as xlam), select AddinInstall event from the upper write dropdown menu and place some code like this:
Private Sub Workbook_AddinInstall()
Call AddToRightClickMenuOptions_Main
End Sub
in this code AddToRightClickMenuOptions_Main is the sub that creates the context menu. Note that you may want to remove the context menu when you uninstall the add-in:
Private Sub Workbook_AddinUninstall()
Call DeleteFromRightClickMenuOptions_Main
End Sub
where DeleteFromRightClickMenuOptions_Main is the routine that removes the context menu (you can find the code easily on the internet)

An Excel Add-in (at least, the ones I have created) still have their own workbook. The Workbook_SheetBeforeRightClick and Workbook_Deactivate will run when the .xlam's workbook is either right-clicked or deactivated. If you want the code to run only for when the selected workbook is right-clicked or deactivated, you'll have to have the code in that specific workbook's code.
However
Since you are trying to get this to work with an add-in, I'm going to go through a few relevant points since once an Add-in is loaded, it (and it's features) are accessible from all other open workbooks.
If the option is added to the context menu whenever a page is right-clicked in any book (which it would (as coded, if it worked)), removing the context menu option when any workbook is deactivated won't have any visible effect, as the next time a right-click happens the option will once again be visible.
Is there a reason why the context menu can't just be added when the add-in is opened (add-in's Workbook_Open), and removed when it's closed(add-in's Workbook_BeforeClose)? (As this will visibly have the same effect as the above code.)

Related

MS Word Add-in constant has different values during start up (AutoExec)

I am developing two Word Add-Ins that customize the ribbon.
The first one is on the local machine.
It contains an AutoExec sub to load the second add-in that is on a network drive:
Private Const AddInPath As String = "\\path\to\add\in"
Public Sub AutoExec()
AddIns(AddInPath).Installed = True
Call AddMenu
End Sub
The network add-in stores the name of the menu in a private const variable:
Private Const MENUNAME As String = "My Menu Name"
It contains the sub that adds the menu:
Public Sub AddMenu()
Dim menu As CommandBar
' Ugly workaround for multiple menus
On Error GoTo Handler
While True
Application.CommandBars(TOOLBAR_NAME).Delete
Wend
Handler:
'Just go on
Set menu = Application.CommandBars.Add(MENUNAME)
With menu
' [Do menu config]
End with
End Sub
When Word starts, it executes the AutoExec Sub multiple times and adds the menu multiple times. I haven't figured why. As a workaround I delete the menu until there are no more of them (see ugly workaround section above).
My issue is that initially the menu was named "MyMenuName". Then I renamed it "My Menu Name" and it appears that Word executes pieces of codes with "MyMenuName" and others with "My Menu Name". As a result my menu is not clean: buttons are duplicated several times!

Documents.open affecting macro functionality?

I have created a simplistic menu in word that opens a number of word files with various macros built in. Some of the macros function as normal when opened via the menu (e.g. forms that are showed on Private Sub Document_Open), but others (code to ignore warnings about saving in a macro free environment) are ignored.
Other issues, such as a debug errors about Word being 'unable to fire event', also seem to be occurring, but only when the files are opened via the menu. All the menu does is use Documents.Open and open the file.
When users open the file without the menu, no issues occur (no warnings about saving in a macro free environment, no errors about firing events).
Any help would be appreciated! I would prefer to not have to scrap the menu entirely for usability, as there are quite a few files that the menu serves as an index for.
Code below:
If ComboBox1.Text = "- Full title page" Then
Documents.Open ("A:/Workgroup Documents/Folder 1/templates/name of file.docm")
End If
Code from document that is opened (ThisDocument module):
Private WithEvents App As Word.Application
Option Explicit
Dim sDocName As String
Dim kcsval As String
Private Sub Document_Open()
frmFooters.Show
Set App = Word.Application
CATform.Show
On Error Resume Next
Documents("J:\Workgroup Documents\Edited Transcript\templates\menu.docm").Close SaveChanges:=wdDoNotSaveChanges
FixSaveError
End Sub
Then some forms, and a module and class module that deal with the save error. Module:
Option Explicit
Dim MyClass As New Class1
Sub FixSaveError()
Set MyClass.App = Word.Application
End Sub
Class module (Class1):
Public WithEvents App As Word.Application
Private Sub App_DocumentBeforeSave(ByVal Doc As Document, _
SaveAsUI As Boolean, Cancel As Boolean)
Application.DisplayAlerts = wdAlertsNone
ActiveDocument.Save
Application.DisplayAlerts = wdAlertsAll
End Sub
The module and class module function purely to remove the warning message about saving in a macro-free environment when saving as docx from docm.
The forms that open up on Document_Open function fine, if it gets that far (the 'error firing event' error sometimes stops it getting there, but only sometimes and only on some machines - and only when using the menu to open the files).

Set focus back to the application window after showing userform

When showing a userform (running its Show method) it not only shows up on the screen but also takes the focus (the destination of e.g. keystrokes).
Say, the userform is a custom made toolbar. Its Show fires in Workbook_Open() but the form itself is used relatively rarely so we want the focus to go back to the main application window right after its appearance.
Unfortunately, it seems SetFocus method is not valid for application objects.
So how is this done?
I suppose the solution for my example comes after
Private Sub Workbook_Open()
[...]
UserForm1.Show
i use this one :
AppActivate Application.caption
this resets the focus from a userform to your Excel Sheet.
For me
AppActivate ThisWorkbook.Application
right after the Show statement seems to work fine.
In other cases
AppActivate "Microsoft Excel"
may also be ok.
This is a bit tricky, but this is what can do.
In the subroutine “Private Sub UserForm_Initialize()”, add this as the last line:
Private Sub UserForm_Initialize()
. . . . . . . . . .
Application.OnTime Now(), "MoveFocusToWorksheet"
End Sub
In any of the general code modules (add one if you have none), declare an API function:
Public Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long
In any of the general code modules (could be the one with the API declaration, of course), add this subroutine:
Public Sub MoveFocusToWorksheet()
Dim Dummy As Long
ThisWorkbook.Worksheets("Sheet1").Activate
' "Sheet1" here is the tab name of the sheet you want to move focus to. _
Or simply use then: With shtABC.Activate _
where "shtABC" being the worksheet's CodeName, _
same as ThisWorkbook.Worksheets("Sheet1").CodeName, _
same as the sheets module name showing in the Project Explorer panel.
Dummy = SetForegroundWindow(Application.hwnd)
End Sub
Both AppActivate Application.Caption and (the better) AppActivate ActiveWindow.Caption mentioned in the other answers do their job in focusing back on the application window itself ... but they do NOT focus on the actual cell/range where one typically wants the focus to be. For that, use:
ActiveCell.Activate
which has the benefit of not requiring an additional click on the cell area of the sheet where you want to return focus - an additional click that can potentially change the previous selection.
I create an object for the application e.g. Outlook, then change the WindowSate to Maximised (OlMaximized), then when I want to remove focus I minimise (olMinimized)
Set OutlookObj = GetObject(, "Outlook.Application")
OutlookObj.ActiveExplorer.WindowState = olMinimized
OutlookObj.ActiveExplorer.WindowState = olMaximized
Or you change the state from inside the application, you can also change its location and size etc for more info see: https://msdn.microsoft.com/en-us/library/office/ff838577.aspx
Application.WindowState = xlMaximized
An other form is:
AppActivate ThisWorkbook.Name
I use
AppActivate ActiveWindow.Caption
because
AppActivate Application.Caption
can focus the wrong window if multiple windows are opened for the same workbook.
As a footnote to this excellent discussion, in some circumstances you may avoid the focus problem by skipping the call to .Show, so the focus never moves in the first place. For example with Word, if you are updating a modeless form or dialog box, just update the required area and omit the call to .Show, e.g.:
Sub ShowProblems(ByVal ProbLoc)
EditBox2.TextBox.Text = "Here is the problem location: " & ProbLoc
' not needed: EditBox2.Show vbModeless
End Sub
Private Sub UserForm_Activate()
RefRangeIn.SetFocus
End Sub
it work for me, in excel 2013 VBA
Add a dummy form and add codes as below:
Private Sub SomeButton_Click()
frm_Dummy.Show vbModeless
Unload frm_Dummy
End Sub
OR
Sub SomeSub()
frm_Some.Show vbModeless
frm_Dummy.Show vbModeless
Unload frm_Dummy
End Sub
I created a floating menu with a user form and use this code to make my cursor leave the user form and jump/focus back to my worksheet. It works at the end of each command button code and with the initiation code of the user form as well.
AppActivate ThisWorkbook.Application
Just place the above line of code before the "End Sub" line of any command button code and the initial show userform code.

Userform not triggering Initialize or Activate event

I kept a userform control button in my worksheet to fire up a macro, which in turn shows a user form, In the form I wish to display the opened files in checkboxes(using the Workbooks collection).I wish to run a macro that performs action for the user selected files only.
So for the button in my worksheet, I have assigned the following macro
Private Sub Button2_Click()
Load MyForm
MyForm.Show
End Sub
At first I kept the below code in the module where my macro sub is there.Since it's not working, I right clicked on user form and selected view code and kept the below code there.But still it's showing the same static designed user form, not the dynamic.I kept breakpoint at both load Myform and MYform.Show() and I stepped through code.It never went into intialize or activate method at all.
Private Sub MyForm_Activate()
'for checking the whether this method is called or not I am trying to change caption
MyForm.LabelSelectFile.Caption = "dhfdfldkfldzjf;zdfkz;d"
Dim mymyWorkBook As Workbook
For Each mymyWorkBook In Workbooks
'code for creating checkbox based on the file name displayed by the workbook collection
Next mymyWorkBook
End Sub
I can't understand why that event is not getting triggered.Please help me to overcome this.Thanks in advance
Even though the name of the form is MyForm, you still need to use userform.
'~~> in your worksheet
Private Sub Button2_Click()
MyForm.Show
End Sub
'~~> In the userform code area
Private Sub UserForm_Initialize()
'~~> Your code here
End Sub
or
Private Sub UserForm_Activate()
End Sub
The best is to always select the event from the drop down, rather than typing it

Calling a macro from a button in edit mode while in PowerPoint

I'm trying to write a vba macro that can be called in edit-mode in PowerPoint 2007-2010.
I can easily add a Command Button to a presentation. However, this button can only be clicked to trigger the vba macro while in slideshow mode.
However, what I would like to do is have this button trigger the associated vba macro while in edit mode. Clicking on it in edit mode allows me to change its size etc, but it doesn't call the macro.
In Excel on the other hand, I get exactly the expected behaviour when I insert a button -> clicking on it calls the vba action.
So how can I create a button (or other element that acts the same way) that calls a vba macro during edit view in PowerPoint. The only way I can think of is using a ribbon action, however this is unpractical in this case, because the macro will modify a shape that is associated with the button and there might be several of these shapes per slide that should each have their own button.
The only way I can think of is using a ribbon action, however this is unpractical in this case, because the macro will modify a shape that is associated with the button and there might be several of these shapes per slide that should each have their own button.
Depending on what you're trying to do, a ribbon button that launches a macro might be quite practical. The macro could operate on the current selection (and test the current selection to ensure that it's something appropriate).
With ActiveWindow.Selection.ShapeRange
' operate on the currently selected shapes
End with
just answer it a some where else also
it is possible to do so all you need is download this file
http://www.officeoneonline.com/eventgen/EventGen20.zip
install it
create a class module
paste this code
Option Explicit
Public WithEvents PPTEvent As Application
Private Sub Class_Initialize()
End Sub
Private Sub PPTEvent_WindowSelectionChange(ByVal Sel As Selection)
If Sel.Type = ppSelectionShapes Then
If Sel.ShapeRange.HasTextFrame Then
If Sel.ShapeRange.TextFrame.HasText Then
If Trim(Sel.ShapeRange.TextFrame.TextRange.Text) = "Text inside your shape" Then
Sel.Unselect
yoursub
End If
End If
End If
End If
End Sub
insert a new module
paste this code
Dim cPPTObject As New Class1
Dim TrapFlag As Boolean
Sub TrapEvents()
If TrapFlag = True Then
MsgBox "Already Working"
Exit Sub
End If
Set cPPTObject.PPTEvent = Application
TrapFlag = True
End Sub
Sub ReleaseTrap()
If TrapFlag = True Then
Set cPPTObject.PPTEvent = Nothing
Set cPPTObject = Nothing
TrapFlag = False
End If
End Sub
Sub yoursub()
MsgBox "Your Sub is working"
End Sub
Now run TrapEvents and whenver you will click shape with that text in it your sub will run
Credits to the person who wrote this http://www.officeoneonline.com/eventgen/eventgen.html