powerpoint linked object update flickers - vba

After much hunting the last couple days, I've managed to get my powerpoint to update its excel link (which itself has data from an autoupdate query off our SQL db).
I open the excel file, then the powerpoint.
I have Excel autosaving every minute (will be every 10 when go live).
the powerpoint has this in module 1
Sub SlideShowNextSlide(ByVal Wn As SlideShowWindow)
ActivePresentation.UpdateLinks
With Application.ActivePresentation
If Not .Saved And .Path <> "" Then .Save
End With
End Sub
Sub OnSlideShowPageChange(ByVal objWindow As SlideShowWindow)
ActivePresentation.UpdateLinks
With Application.ActivePresentation
If Not .Saved And .Path <> "" Then .Save
End With
End Sub
I set the slideshow to loop until ESC.
the VBA does (almost all the time) run.
But when it runs, it loads the slide with the refreshed data.. and then in the last instant before the slide changes to the next one, you see the old data flicker onto the screen.
That's why I put that save after the updatelinks, hoping it would make the update stick for the next cycle.. but no joy.
Is there some sort of cache it uses while the slideshow is running? Can it be updated? Somehow have the running slideshow 'reload' from the now saved file.
If I have to I'll have the slideshow stop every hour and restart using some sort of Windows macro.. but that would be pretty ducktape-y.

Related

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.

Adding a text clock to PowerPoint using VBA

I'm trying to add a clock to a PowerPoint slide, and it has to show the current time, which means it has to update once every second. This is my current macro:
Sub OnSlideShowPageChange()
Dim i As Integer
i = ActivePresentation.SlideShowWindow.View.CurrentShowPosition
MsgBox "Macro still working!"
'With ActivePresentation.Slides(i).Shapes("Date Placeholder 8")
' Do
' Sleep 1000
' .TextFrame.TextRange.InsertDateTime ppDateTimehmmssAMPM
' DoEvents
' Loop
'End With
End Sub
This shows a MsgBox with the text "Macro still working!" as expected. However, if I remove the apostrophes, thus (supposedly) allowing the update code to run, nothing happens, and I don't see a MsgBox. Can anyone help?
I've tried using the AutoDateTime add-in, and it works, except there are animations that need to run on my slide and AutoDateTime keeps interrupting those animations. I've also tried TM Timer and it has the same problem.

Close a workbook at a specific time

I have looked everywhere to get an answer to this and can't figure it out. I'm looking for a way to close and save a workbook automatically at midnight every night because it has important information that people keep losing because they don't save it. I've got the closing and saving part down, if I manually click the X to close Excel, but I can't get it to do it at a predetermined time. I've used Application.OnTime without any success. Here is the code that I'm using to close and save the workbook. I just need the code to have it run at midnight if the workbook is still open.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Sheet1.Activate
Sheet1.Range("AB18:AD18").Select
Selection.ClearContents
ActiveWorkbook.Save
End Sub
I had trouble referencing the Worksheet .CodeName property but not with the Worksheet .Name property.
Module1 code sheet
Option Explicit
Sub ScheduleClose()
Application.OnTime Now + TimeSerial(0, 0, 4), "Kamikaze"
End Sub
Sub Kamikaze()
Debug.Print "boom"
Application.DisplayAlerts = False
With ThisWorkbook
.Worksheets("Sheet1").Activate
.Worksheets("Sheet1").Range("AB18:AD18").ClearContents
.Save
.Close savechanges:=False
End With
End Sub
Of course, the workbook must be already saved (i.e. not Book1) since no name is provided but a Workbook.SaveAs method could be used if the workbook habitually is not already saved.
This will also leave 'orphaned' VBA projects within the Excel application 'instance'. VBA cannot kill itself as it has to be running to complete the command.

Shared Excel Document

I've got a Excel documents with macros with input and update forms for information, the document is used as a monthly database where you can run reports from as well.
The issue is that when using the document sometimes the input and update options are used at the same time causing information loss. Both the input and output save at the end of the macro to minimise the losses, but I was wondering if there is anyway of checking at runtime if there is a macro being use by another user and if so delay the next macro run until the other user is finished?
There is one way I can think of. Logically it should work. However I have not tested it.
Create a temp sheet and hide it
When anyone runs a macro, check if cell A1 of that sheet is empty or not
If it is empty then run the macro
Before running the macro, write to that cell and once the macro is run, clear the contents of the other cell
Sandwich your macro code as mentioned below
Code
Sub Sample()
Dim ws As Worksheet
ThisWorkbook.Save
Doevents
Set ws = ThisWorkbook.Sheets("HiddenSheetName")
If Len(Trim(ws.Range("A1").Value)) = 0 Then
ws.Range("A1").Value = "Macro Starts"
ThisWorkbook.Save
Doevents
'
'~~> Rest of your code goes here
'
ws.Range("A1").ClearContents
ThisWorkbook.Save
Doevents
Else
MsgBox "Please try after some time. There is a macro running... Blah Blah"
End If
End Sub
CAUTION: Once the code runs, you cannot undo the changes since the code save the file programatically. The changes are permanent. In a file which is not shared, you can undo by closing the file without saving and re-opening it.

Excel 2016 crash on API timer initiated Workbook.close

I have a workbook that crashes Excel on close when the close is triggered by an API timer.
Edit: The workbook in link below has nothing but the timer and exit modules and it has the same behavior so it's not an issue with the content.
https://www.dropbox.com/s/x0xdwgj5h34ctdk/Book1.xlsm?dl=0
A few seconds after the workbook closes Excel crashes. I have tried turning the timer off, unhiding all sheets, unloading forms...all the objects are set to Nothing.
All I am doing is Workbooks(ThisWorkbook.Name).Close SaveChanges:=True??!!
The same sub is called from a UserForm with no problem. The workbook closes without Excel crashing.
How to fix this?
Sub ApplicationExit()
' Call UnloadAllForms
' DoEvents
' Sleep 1000
' Call StopCloseTimer
'DoEvents
'If Application.Workbooks.Count = 1 Then
' Workbooks(ThisWorkbook.Name).Save
' Application.Quit
'Else
DoEvents
Workbooks(ThisWorkbook.Name).Close SaveChanges:=True
'End If
End Sub
The code triggered by the timer is;
Sub TimerCalled()
If CloseTimerValue = "" Then Call Reset_CloseTimerValue
DoEvents
If basTimers.CloseTimerValue <= Now() And Not Unlocked Then Call ApplicationExit
On Error Resume Next 'In case sheet is protected
ThisWorkbook.Sheets("JobIndex").Range("CloseCount").Value = Format(Now() - CloseTimerValue, "hh:m:s")
End Sub
The userform says;
CloseUp:
i = MsgBox("Close Project Register?", vbYesNo, MsgBoxTitle)
Select Case i
Case vbYes
Call ApplicationExit
Case vbNo
Workbooks(ThisWorkbook.Name).Save
End Select
Timer in excel vba is done by using the Application.OnTime command or windows timer, as you are using.
Notice that, to schedule the call for a function (using the upper-mentioned command), it's used APPLICATION, which means it tells EXCEL to execute the call, not your workbook. So, in your case, the workbook is closed, BUT the to-be-called procedure is still scheduled to go off at some time in the future. The error that you get is that the excel doesn't find the procedure and then throws an error.
The reason it crashes in your case is that you are using windows timer to do it. When you close your workbook, your instance of the lib32 is lost and when time comes, Windows can't reach in the memory and then crashes the whole application.
In both cases, it seems that your scheduled procedure is still running.
I suggest that you look into that and consider using application.ontime.