View Full Version : PowerPoint vba - Event not fired when screen is empty
VeronicaStr
04-04-2022, 05:43 AM
Note: I did post this question also on StackOverflow and Docs.Microsoft.com:
https://stackoverflow.com/questions/71439577/powerpoint-vba-custom-ribbon-group-does-not-refresh-when-screen-is-empty. Here I have had many help already, but not for this problem.
https://docs.microsoft.com/en-us/answers/questions/796398/show-or-hide-custom-group-depending-on-powerpoint.html.
I could not solve the problem yet, so that is why I post it here also and hope to find a solution ...
I am making an add-in with a custom Ribbon Tab. When PowerPoint is opened, and the add-in is loaded, the user only sees three buttons on the custom Tab (= the choice between three templates) which can be used to start a new presentation.
When template A is choosen to make a new presentation, group 1 (with a set of buttons) gets visible on the custom Ribbon Tab.
When the presentation is closed, the group disappears. When template B is choosen, group 2 appears. When template C is choosen, group 3 appears. The groups are never visible all together.
So everytime a presentation is new created, closed or opened, the Ribbon has to refresh. The Getvisible code is checking the Design name of the template to see which group has to be visible.
This works fine as long as there is already a presentation open on screen. But as soon as there is no presentation open (empty PowerPoint screen) and a new presentation is made via the custom Tab, the Ribbon does not refresh. The template-depended group does not appear in the Ribbon. This also happens when I open an existing presentation on an empty screen. I can also see in another way that the Ribbon is not refreshed because of the fact that after the Event, the Ribbon does not go back to the Home Tab.
I can't figure out where it goes wrong. Here is my code:
XML:
<customUI onLoad="RibbonOnLoad" …>
<group id="MyCustomGroup1" label="Name" getVisible="GetVisible" tag="MyPersonalGroup1"
And there I've added some custom buttons.
I also made "MyPersonalGroup2" and "MypersonalGroup3" like this.
VBA:
Dim Rib As IRibbonUI
Dim MyTag As String
'Callback for customUI.onLoad
Sub RibbonOnLoad(ribbon As IRibbonUI)
Set Rib = ribbon
MsgBox "Ribbon Loaded"
End Sub
Sub getVisible(control As IRibbonControl, ByRef returnedVal)
Select Case control.Tag
Case "MyPersonalGroup1"
returnedVal = ActiveWindow.Selection.SlideRange.Design.Name = ("TemplateA")
Case "MyPersonalGroup2"
returnedVal = ActiveWindow.Selection.SlideRange.Design.Name = ("TemplateB")
Case "MyPersonalGroup3"
returnedVal = ActiveWindow.Selection.SlideRange.Design.Name = ("TemplateC")
End Select
End Sub
Class module ApplicationEventClass:
Public WithEvents PPTEvent As Application
Private Sub PPTEvent_WindowSelectionChange(ByVal Sel As Selection)
MyTag = Tag
If Rib Is Nothing Then
MsgBox "Error, restart your presentation"
Else
Rib.Invalidate
End If
End Sub
I repeated this code for 'PPTEvent_NewPresentation' 'PPTEvent_AfterNewPresentation' 'PPTEvent_AfterPresentationOpen' 'PPTEvent_PresentationOpen' 'PPTEvent_PresentationClose'
And this Module going with the code above:
Dim X As New ApplicationEventClass
Sub InitializePPTEvent()
Set X.PPTEvent = Application
End Sub
Help is very much appreciated!
Paul_Hossler
04-04-2022, 03:14 PM
I'm not sure I understood all of what is happening, but here's something to look at
I've found it usually works out better (= less confusing) to set and read boolean status variables
VeronicaStr
04-05-2022, 03:11 AM
Hi Paul, thanks a lot!
I immediately implemented your code into my PPTM. I saved as an add-in, but now the events do not fire at all...
I first tried it without the btnAction code (as I want the custom groups to be visible only by checking the template name, not by clicking a button), but then the custom groups did not appear.
Then I put in only the first part (btnA, btnB, btnC). My custom groups are quite extensive, so I thought that would be better. When I click one of the buttons, my custom group appears. But the Ribbon does not refresh on opening, starting new or closing a presentation.
There is one other thing I don't understand. The code does not declare what bFormatA, bFormatB and bFormatC actually is. In my previous code I referred to the tags of the groups in the Custom UI ("MyPersonalGroup1" etc).
Should I not declare that somewhere?
I could send you my complete code if you want to take a look at it?
Thanks for your help!
Veronica
Paul_Hossler
04-05-2022, 11:46 AM
Module 1 --
Option Explicit
Public oRibbon As IRibbonUI
Public bFormatA As Boolean, bFormatB As Boolean, bFormatC As Boolean ' <<<<<<<<<<<<<<<<<<<<<<
Public oApp As ApplicationEventClass
Right click on variable and select [Definition] and the editor will take you to where it's defined
29577
Edit - forgot to attach latest attempt
Format_Addin.pptm is the source for the addin
I left a bunch of MsgBox lines in for now
It seems to throw an error on closing when the addin (PPAM) is also loaded and I open and close the PPTM. No error it the PPAM is not loaded
VeronicaStr
04-06-2022, 10:02 AM
Thanks a lot, this has been of so much help!
I changed on thing:
When there was no presentation open (empty screen) and I click on one of the template buttons, I got the run-time error "There is no currently active document window" See image:
29582
So I changed the Sub GrpVisible code from "If ActiveWindow is Nothing Then" to "If Windows.Count = 0 Then" and now it works fine, I don't get that run-time error anymore.
Now there is only one thing I have to solve. If the cursor is between two slides in the left-hand pane with slide thumbnails (so no slides selected), I get the run-time error "Nothing appropriate is currently selected". The debugger point to the Sub GrpVisible line "With ActiveWindow.Selection.SlideRange.Design" Could it be the WindowSelectionChange Event? I'm not sure, as the msg box "change" never appears... It happens when I save the PPTM to PPAM and load the add-in
Paul_Hossler
04-06-2022, 01:59 PM
So I changed the Sub GrpVisible code from "If ActiveWindow is Nothing Then" to "If Windows.Count = 0 Then" and now it works fine, I don't get that run-time error anymore.
That's good. I tried a number of things to get rid of the error
I only got it some times and it's hard to debug an addin
Try this and see if it works
'Callback for grpA / grpB / grpC getVisible
Sub GrpVisible(control As IRibbonControl, ByRef returnedVal)
If Windows.Count = 0 Then
returnedVal = False
ElseIf ActiveWindow.Selection.Type = ppSelectionNone Then
returnedVal = False
ElseIf ActiveWindow.Selection.Type = ppSelectionSlides Then
returnedVal = False
Else
With ActiveWindow.Selection.SlideRange.Design
Select Case control.Id
Case "grpA"
returnedVal = (.Name = "TemplateA")
Case "grpB"
returnedVal = (.Name = "TemplateB")
Case "grpC"
returnedVal = (.Name = "TemplateC")
End Select
End With
End If
oRibbon.Invalidate
End Sub
John Wilson
04-06-2022, 10:56 PM
AFAIK there is no way to detect where the cursor is if it is between slides.
A workaround is to change the view and then change it back. The slide before the cursor is now selected
ActiveWindow.ViewType = ppViewOutline
ActiveWindow.ViewType = ppViewNormal
VeronicaStr
04-07-2022, 05:29 AM
Isn't is possible to say something like:
If selection is nothing Then do nothing?
That way the Ribbon stays as is at the time when the cursor is placed between slides, which is OK.
ActiveWindow.ViewType = ppViewOutline
ActiveWindow.ViewType = ppViewNormal
When I put these two lines in the code (after Else), PowerPoint is flashing non-stop and crashes eventually
I removed the event WindowSelectionChange, because I thaught it was causing the problem, but it didn’t.
I tried the two options ppSelectionNone and ppSelectionSlides too.
With the ppSelectoinNone the tabgroup also disappears if I don’t have anything selected on the slide.
With ppSelectionSlides the run-time error appears too.
I now have this code:
[CODE]
'Callback for grpA / grpB / grpC getVisible
Sub GrpVisible(control As IRibbonControl, ByRef returnedVal)
If Windows.Count = 0 Then
returnedVal = False
'In the slide sorter view I get the run-time error too, so I added this code. That works fine.
ElseIf ActiveWindow.ActivePane.ViewType = ppViewSlideSorter Then
returnedVal = False
Else
With ActiveWindow.Selection.SlideRange.Design
Select Case control.Id
Case "grpA"
returnedVal = (.Name = "TemplateA")
Case "grpB"
returnedVal = (.Name = "TemplateB")
Case "grpC"
returnedVal = (.Name = "TemplateC")
End Select
End With
End If
oRibbon.Invalidate
End Sub
Paul_Hossler
04-07-2022, 05:55 AM
I took this ...
If the cursor is between two slides in the left-hand pane with slide thumbnails (so no slides selected), I get the run-time error "Nothing appropriate is currently selected".
... to mean
29590
which isn't the same as Slide Sorter View
29591
With the cursor between slides on the left, then ActiveWindow.Selection.Type = ppSelectionNone
With one of the slides on the left selected, then ActiveWindow.Selection.Type = ppSelectionSlides
Sub test()
Stop
If ActiveWindow.Selection.Type = ppSelectionNone Then
MsgBox "None1"
ElseIf ActiveWindow.Selection.Type = ppSelectionSlides Then
MsgBox "None2"
End If
End Sub
VeronicaStr
04-07-2022, 06:51 AM
Hi!
The first picture describes the problem correctly! The reason I added code for the slide sorter view, is that I get the run-time error there too, if the cursor is between two slides.
So I get this run-time error in two occassions. Slide Sorter View is fixed now, but "If the cursor is between two slides in the left-hand pane with slide thumbnails" not...
I was now thinking about something like "If Selection is nothing Then do nothing" Or maybe "Exit Sub" to skip the whole refreshing in that case. But I don't know if that is possible...
Paul_Hossler
04-07-2022, 08:08 AM
Try adding the code I added in #6 and see if something like that works
'Callback for grpA / grpB / grpC getVisible
Sub GrpVisible(control As IRibbonControl, ByRef returnedVal)
If Windows.Count = 0 Then
returnedVal = False
ElseIf ActiveWindow.Selection.Type = ppSelectionNone Then
returnedVal = False
ElseIf ActiveWindow.Selection.Type = ppSelectionSlides Then
returnedVal = False
ElseIf ActiveWindow.ActivePane.ViewType = ppViewSlideSorter Then
returnedVal = False
Else
With ActiveWindow.Selection.SlideRange.Design
Select Case control.Id
Case "grpA"
returnedVal = (.Name = "TemplateA")
Case "grpB"
returnedVal = (.Name = "TemplateB")
Case "grpC"
returnedVal = (.Name = "TemplateC")
End Select
End With
End If
oRibbon.Invalidate
End Sub
VeronicaStr
04-07-2022, 10:54 AM
I think I found a workaround. Referring to the design name turns out to be very unstable. All kinds of tricks have to be used to make it work without run-time errors.
So then I thought it might be better to refer to a fixed value, while it doesn't matter if you select something or not. So now I refer to Keywords in the Document Properties. I entered the template name there and it works! See below the code:
'Callback for grpA / grpB / grpC getVisible
Sub GrpVisible(control As IRibbonControl, ByRef returnedVal)
If Windows.Count = 0 Then
returnedVal = False
'I think i can delete this but for now it is still here
ElseIf ActiveWindow.ActivePane.ViewType = ppViewSlideSorter Then
returnedVal = False
Else
With ActivePresentation.BuiltInDocumentProperties
Select Case control.Id
Case "grpA"
returnedVal = .Item("keywords").Value = ("TemplateA")
Case "grpB"
returnedVal = .Item("keywords").Value = ("TemplateB")
Case "grpC"
returnedVal = .Item("keywords").Value = ("TemplateC")
Case Else
returnedVal = False
End Select
End With
End If
oRibbon.Invalidate
End Sub
What do you think of it?
Paul_Hossler
04-07-2022, 01:08 PM
Seems like it'd be a better choice
I'd suggest that you use
If ActivePresentation.BuiltInDocumentProperties("Template") = "FormatA" Then
since 'keywords' might have multiple ... well, keywords ... like "Sales, 2021, FormatA, Ver3" and
1. A straight equality test won't work
2. A user might change or delete keywords
3. The only way I know to set the Template property is via the Immediate Window, which is beyond your typical user, or by creating the PPTX (File, New) from a POTX
29595
29594
VeronicaStr
04-08-2022, 02:39 AM
That's a good idea!
I start a new presentation from a template. I can't store the template name in the template itself, but when a new presentation is started, the name is there, so that should work.
Or is setting a Customdocumentproperty maybe an even better idea? For instance I create TemplateName. I can set that already in the properties. If someone changes the template name it has no effect than.
Paul_Hossler
04-08-2022, 08:02 AM
The way I believe it works makes me think that
Using FormatA.potx to create SalesJan.pptx (example) then the built in Template property for SalesJan.pptx = "FormatA".
Using FormatB.potx to create CostsJan.pptx (example) then the built in Template property for CostsJan.pptx= "FormatB".
I'd think that would be enough
If you're concerned, then when a new PPTX is created, you could add a CustomDocumentProperty ("OriginalTemplate") = BuildinDocumentProperty ("Template") and test against that
Personally I think that's overkill, but then you should never trust Users
VeronicaStr
04-09-2022, 05:40 AM
but then you should never trust Users
Hahaha, that is so true. They ruin things you did not know could be ruined ....
Many thanks for all your help! Have a nice weekend!
All the best, Veronica
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions Inc. All rights reserved.