How do you run vba code when changing slides in powerpoint? - vba

I'm trying to reset the contents of some text boxes and labels when I change slides, but I'm struggling to get it to work. I've come up with this after doing a lot of googling and searching, but it doesn't seem to work. I'm trying to use the OnSlideShowPageChange event in PowerPoint 2013 and 2016, but it seems to have no effect. I'm not used to working with PowerPoint vba, so I might be doing something completely wrong.
Edit: I've managed to find an alternative method of resetting the label text. I've managed to get it to reset when the user focuses on one of the text boxes or moves their mouse over the label. But, I'm still curious to know the answer to this question; I'm not sure why my code isn't working.
I'll be greatful if anyone can point out any issues and how to fix them.
Here's what I've got so far:
Public Sub OnSlideShowPageChange(ByVal Wn As SlideShowWindow)
Dim Sld As Slide
If Wn.View.CurrentShowPosition = 9 Then
'Perform Updates for slide #9
Set Sld = Application.ActivePresentation.Slides(9)
Sld.Shapes(TextBox_Form_Name).TextFrame.TextRange.Text = ""
Sld.Shapes(TextBox_Form_Email).TextFrame.TextRange.Text = ""
Sld.Shapes(TextBox_Form_Message).TextFrame.TextRange.Text = ""
Sld.Shapes(Label_Form_Info).TextFrame.TextRange.Text = ""
End If
If Wn.View.CurrentShowPosition = 18 Then
'Perform Updates for slide #18
Set Sld = Application.ActivePresentation.Slides(18)
Sld.Shapes(TextBox_Form_Name).TextFrame.TextRange.Text = ""
Sld.Shapes(TextBox_Form_Email).TextFrame.TextRange.Text = ""
Sld.Shapes(TextBox_Form_Message).TextFrame.TextRange.Text = ""
Sld.Shapes(Label_Form_Info).TextFrame.TextRange.Text = ""
End If
End Sub
I've also tried putting the shape names in speech marks, but that doesn't seem to help.
By the way, I need the code to work in both PowerPoint 2013 and 2016.

Here's an answer from the PowerPoint FAQ at http://www.pptfaq.com
Suppose your code that depends on the OnSlideShowPageChange( SHW as SlideshowWindow ) event works when run from within VBA or when you launch the presentation from within PowerPoint, but not when you start the show by doubleclicking the icon for the PPS or PPSM. The slide show launches normally, but the code in your OnSlideShowPageChange subroutine never runs.
Solution
Add an Active-X control (from the Developer tab) on first slide (drag it just off the slide if you don't want it visible during the slide show).
This forces VBA to initialize when the presentation starts, so the event gets triggered and your code runs.

Related

Add clickable checkbox to powerpoint slide on Mac

I want to add a clickable checkbox (one or more) to a PowerPoint presentation slide. I'm using MacOS and Microsoft Office 365.
I guess that it is possible to do using macros created with VBA, but I have no idea what code needs to be created for this.
I would be very grateful if you would share the necessary code or suggest me another relevant ways to create clickable checkboxes in pptx under the Mac.
Checkboxes, labels, textboxes etc are all ActiveX features, and since ActiveX isn't supported on the Mac version of Office or in MacOS generally, you can't do this the way you would in Windows versions of Office.
You might be able to fake it by adding drawn rectangles and assigning a Run Macro action setting to each of them.
This page on the PPT FAQ that I maintain explains how to write the macro.
Determine which shape was clicked
https://www.pptfaq.com/FAQ00141_Determine_which_shape_was_clicked.htm
TL;DR - here's some sample code. This runs on both Windows and Mac (where bugs in PPT's VBA model force it to be more complicated than it would be otherwise):
Sub DoSomethingTo(oSh as Shape)
Dim oSl as Slide
Dim oShTemp as Shape
' oSh.Parent returns a valid reference to the shape's host slide:
Set oSl = ActivePresentation.Slides(oSh.Parent.SlideIndex)
' and oSh.Name works:
MsgBox oSh.Name
' So we use those two bits to get a reference
' to the clicked shape like so
Set oShTemp = oSl.Shapes(oSh.Name)
With oShTemp
.TextFrame.TextRange.Text = oSh.Name
' and whatever else you want to do with the shape
End With
End Sub

Running macro in PowerPoint slideshow does not run unless done manually first

I'm creating a slideshow to display some stats from a sql table. The macro does not want to run unless I run it manually once so I created a simple test to see if it was something with the sql call. Doing this in PPT 2016.
New presentation with 3 slides, a "title page" and two for data. Created a text box on slides 2 & 3. Saved as .pptm
Sub OnSlideShowPageChange()
Dim i As Integer
i = ActivePresentation.SlideShowWindow.View.CurrentShowPosition
If i = 1 Then Call ChangeData
End Sub
Sub ChangeData()
If ActivePresentation.Slides(2).Shapes("TextBox 1").TextFrame.TextRange.Text = "Answer 1" Then
ActivePresentation.Slides(2).Shapes("TextBox 1").TextFrame.TextRange.Text = "Answer A"
ActivePresentation.Slides(3).Shapes("TextBox 1").TextFrame.TextRange.Text = "Answer B"
Else
ActivePresentation.Slides(2).Shapes("TextBox 1").TextFrame.TextRange.Text = "Answer 1"
ActivePresentation.Slides(3).Shapes("TextBox 1").TextFrame.TextRange.Text = "Answer 2"
End If
End Sub
Close the presentation. Open presentation and run the slideshow. It cycles through the 3 slides and repeats as I want but the "data" is not changing. Esc slideshow and manually run the ChangeData macro. Start slideshow again. Now it cycles through the slides and changes the data as desired.
Any ideas as to why it requires a macro to be run first? I would like to go straight to the slideshow or better yet use the ppt viewer.
Edit:
After looking around more I found this thread How do you run vba code when changing slides in powerpoint?
So, added an ActiveX TextBox and moved off slide with the following code for the control
Private Sub TextBox1_Initialize()
End Sub
Interestingly on the test presentation I have to click on the title slide to kick off the slideshow but when I include the control on my actual presentation it works just fine, without having to click on the first slide. I also tested saving my presentation as a ppsm and it still works. Can modify the sql data and it updates the slide table as desired.
I incorporated Sam's suggestion of Sub OnSlideShowPageChange(ByVal Wn As SlideShowWindow) and also tested as orig and both work. I also tested by adding an ActiveX Label but that did not work, had to be a TextBox or maybe other but not as a Label.

VBA Powerpoint : what is the VBA equivalent to "hyperlink to a different Powerpoint Presentation?

I want to use several slideshows (in kiosk mode if possible), to be able to jump between them, without going back in edit mode...
No problem to do it with shapes and "hyperlink to a different powerpoint presentation".
But i'd need to do it also in VBA macros, in some slides.
For example, after a quiz is finished, jump to another slideshowwindow and a given slide, and give focus to that slideshowwindow :
What would be the code like ?
I'm unable to give focus to the new slideshowwindow...
I suppose it is the equivalent of what "hyperlink to a different PPT Presentation does, but i can't figure to do it.
Thank you very much in advance !
Alex
This Code opens a Presentation goes to Slide Number 5 and starts in Kiosk Mode
Dim PowerPointApp As PowerPoint.Application
Dim myPPT As PowerPoint.Presentation
'Open the Slideshow
Set myPPT = PowerPointApp.Presentations.Open(FileName:="filename.pptx")
Application.ActivePresentation.SlideShowSettings.ShowType = ppShowTypeKiosk
'You need this to work
ActivePresentation.SlideShowWindow.View.Exit
ActivePresentation.SlideShowSettings.Run
'Goto Slide number 5
myPPT.Windows(1).View.GotoSlide 5
'Start Slide Show
myPPT.SlideShowSettings.Run

Refresh all charts without blinking

The aim is to refresh all charts in Excel after cells recalculation.
I work with Microsoft Excel 2010.
As we know, there is a bug? in Excel so that Excel does not update charts even after
Application.CalculateFullRebuild
A known hack is to do something like this:
Application.ScreenUpdating = False
Temp = ActiveCell.ColumnWidth
ActiveCell.Columns.AutoFit
ActiveCell.ColumnWidth = Temp
Application.ScreenUpdating = True
This does work. However, all Excel charts blink (they become white for a moment while updating). Could you advise, please, is there any way to avoid such blinking?
I tried to call
.Refresh
on all charts (https://msdn.microsoft.com/en-us/library/office/ff198180(v=office.14).aspx):
For Each ChartObject In ActiveSheet.ChartObjects
ChartObject.Refresh
Next
but for some reason my Excel (2010) shows error #438 "Object doesn't support this property or method".
Could you advise, please, do I miss something important?
Untested But the .Refresh may work with this:
Sub ChangeCharts()
Application.ScreenUpdating = False 'This line disable the on screen update for better performance, the blink you see, you could delete both lanes but it will run slower
Dim myChart As ChartObject
For Each myChart In ActiveSheet.ChartObjects
myChart.Chart.Refresh
Next myChart
Application.ScreenUpdating = True'This line reenable the on screen update for better performance, the blink you see, you could delete both lanes but it will run slower
End Sub
And that's because (as the link you provide shows) .Refresh only works with the object Chart and not with the object ChartObjects as you have been trying to apply it. Hope it'll guide you in the right direction. (also added quotes for the blink/flicker on screen in the code)
Happy Pi Day!
I just did some experiments with animating charts, using VBA to change a counter in a cell, and worksheet formulas to recalculate chart data based on this counter.
I used to do a lot of chart animations, back in the days of Excel 97-2003, and those ran pretty well. When Excel 2007 came out, the animations really degraded, and nothing seemed to help. But just now I did these tesst in the latest build of Office 365 (Version 1904, Build 11504). And it turns out, sometime in the past few years or so, Microsoft has made it work better.
Sub ChartAnimation1()
Dim i As Double
For i = 0 To 1000 Step 50
ActiveSheet.Range("Stepper") = i
Next
End Sub
The animation didn't animate, that is, the chart didn't change despite the data changing.
My experience told me I should put something like DoEvents in the code after I change the cell's value.
Sub ChartAnimation2()
Dim i As Double
For i = 0 To 1000 Step 50
ActiveSheet.Range("Stepper") = i
DoEvents
Next
End Sub
This helped a little, the chart changed, but the animation was not smooth. Some steps were missed, and the effect was a herky-jerky animation.
Sub ChartAnimation3()
Dim i As Double
For i = 0 To 1000 Step 50
ActiveSheet.Range("Stepper") = i
DoEvents
DoEvents
Next
End Sub
This ran a bit more slowly than with one DoEvents, but it was a lot smoother; still not perfect, but pretty good.
More than two DoEvents was overkill: the code took the same length of time, and the animation was not any smoother.
I also tried various combinations of Chart.Refresh, Chart.Activate, and ScreenUpdating. Two takeaways:
Without a couple DoEvents, the animation didn't work regardless of what other things I tried.
With a couple DoEvents, none of these extra steps made the animation any smoother, but they could make it significantly slower.
This was pretty interesting, so I'll blog about it some day. When I do I'll come back and post a link.
As is often the case I was sent to this VBA post following a VB.NET query regarding blinking or flashing Excel Charts after turning on Excel ScreenUpdating. Blinking Charts is something that has been driving me mad for a long time now and I have seen no solutions that work including the above solution that looks like it should work but doesn't. I have now found a solution that works 100% for all of my programs. As this is a VBA post I have shown a VBA solution to the flashing charts but my VB.NET solution is for anyone else who is sent to this post looking for a VB.NET solution. My solution is based on the answer by Zegad above but it has a couple of essential additions that are not documented and which to me are not obvious. Use the following sub as a replacement for "MyXLApp.ScreenUpdating = True". If you find it works for you please do not ask me to explain why it works. I'm sure there are many here who could probably explain this but for me it is the result of luck and dogged determination. An odd addition here is that you actually only need to activate and refresh then deactivate any one chart and all of the charts will update without flashing when re-enabled, See 'VB.NET CODE-2 sub below.
Sub ScrUpdateEnableNoFlicker()'VBA CODE
Dim myChartObj As ChartObject
For Each myChartObj In ActiveSheet.ChartObjects
myChartObj.Activate 'IMPORTANT ADDITION
myChartObj.Chart.Refresh
Next
Cells.Range("A1").Select 'IMPORTANT ADDITION
Application.ScreenUpdating = True
End Sub
Private Sub ScrUpdateEnableNoFlicker() 'VB.NET CODE-1
'BEFORE TURNING SCREEN UPDATING BACK ON...
'ACTIVATE and refresh the chart objects on the sheet with the charts.
Dim aSheet As Excel.Worksheet = CType(mXLWrkbk.Sheets("Sheet1"), Excel.Worksheet)
Dim aChartObjects As Excel.ChartObjects = CType(aSheet.ChartObjects, Excel.ChartObjects)
For Each achartobject As Excel.ChartObject In aChartObjects
achartobject.Activate() 'IMPORTANT - Will not work without activating first
Dim achart As Excel.Chart = achartobject.Chart
achart.Refresh()
Next
'Now deactivate the current activated chart object by selecting any cell
'THIS IS IMPORTANT - It will not work without doing this
Dim selRange As Excel.Range = aSheet.Range("A1")
selRange.Select()
'Now turn Screen Updating back on...
'All of the Charts will have updated and will not flicker
mXLApp.ScreenUpdating = True
End Sub
Private Sub ScrUpdateEnableNoFlicker() 'VB.NET CODE-2
'BEFORE TURNING SCREEN UPDATING BACK ON...
'ACTIVATE ANY ONE of the chart objects on the sheet with the charts.
Dim aSheet As Excel.Worksheet = CType(mXLWrkbk.Sheets("Sheet1"), Excel.Worksheet)
Dim aChartObject As Excel.ChartObject = CType(aSheet.ChartObjects("Chart 9"), Excel.ChartObject)
aChartObject.Activate() 'IMPORTANT - Will not work without activating first
'Refresh just the ONE activated chart.
Dim aChart As Excel.Chart = aChartObject.Chart
aChart.Refresh()
'Now deactivate the current activated chart object by selecting any cell
'THIS IS IMPORTANT - It will not work without doing this
Dim selRange As Excel.Range = aSheet.Range("A1")
selRange.Select()
'Now turn Screen Updating back on...
'You only need to activate/deactivate any one chart and all of the Charts will have updated and will not flicker
mXLApp.ScreenUpdating = True
End Sub
I was having this issue when hiding or showing a series in my chart. The change would not be apparent until I would scroll away then back again to the chart, which was really a pain. I tried all the above solutions with no luck until I realized unselecting and selecting again the chart before doing the change would work.
myChart.TopLeftCell.Select
myChart.Select
...
Good luck in your research for a solution ;)
Thanks to those who have posted here before! Without your successes, I would not have smooth animation of a dynamic simulation. In my case, it is an xlXYScatterLinesNoMarkers type chart. Running in VBA.
This works for me when changing the series programmatically. The chart is animated smoothly. Running Excel 2016 64 bit
Public Sub ShowOneAnimationFrame(worksheetName As String, chartName As String, _
xvals() As Double, yvals() As Double)
'update chart series programmatically
'Excel 2016 64bit
'Dec 21, 2020
'Author: S^3
Dim theChart As chart
Dim chrtObj As ChartObject
Dim oneSeries As Series
Set chrtObj = Sheets(worksheetName).ChartObjects(chartName)
Set theChart = chrtObj.chart
If theChart.SeriesCollection.Count = 0 Then
theChart.SeriesCollection.NewSeries
End If
Set oneSeries = theChart.SeriesCollection(1)
'update the series with new values
oneSeries.XValues = xvals
oneSeries.Values = yvals
theChart.Refresh 'required (this and the next line are required but the order doesn't matter)
chrtObj.Select 'required
Cells.Range("A1") = Cells.Range("A1").value 'something like this is required
End Sub

How to refresh the active Slide in a slide show?

Based on my last question I got the right code to change the image of an shape.
Unfortunatly, this does not update the active Presentation. If I close the presentation and restart it, the image is changed, but the change should be directly visible.
This is my code to change the image:
ActivePresentation.SlideShowWindow.View.Slide.Shapes("SolutionA_Image").Fill.UserPicture ("D:\User\SolutionWrong.jpg")
I found a way to update the presentation, but this lets the presentation flicker.
ActivePresentation.SlideShowWindow.Height = ActivePresentation.SlideShowWindow.Height - 1
ActivePresentation.SlideShowWindow.Height = ActivePresentation.SlideShowWindow.Height + 1
Edit
I tried refreshing the slide as proposed here, but this didn't worked for me.
Dim lSlideIndex As Long
lSlideIndex = SlideShowWindows(1).View.CurrentShowPosition
SlideShowWindows(1).View.GotoSlide lSlideIndex
Edit 2
I uploaded my file: Download
In the end I found my answer in this blog post. It appears to be a bug in PowerPoint 2007.
This code helps to fix the bug:
Dim osld As Slide
'get current slide
Set osld = ActivePresentation.SlideShowWindow.View.Slide
'the next line adds the empty textbox and refreshs the slide
osld.Shapes.AddTextbox msoTextOrientationHorizontal, 1, 1, 1, 1
I found this bug in my Power Point as well,
I add this line into the code and it fixes the bug
Application.SlideShowWindows(1).View.GotoSlide Me.SlideIndex