How to interrupt live Clock loop for next slide transition? - vba

This is my first time ever programming something and I have managed to create a macro for a live clock on a Powerpoint (2016) presentation. The macro works perfectly, activating on my designated named slide only. However, I cannot find a way to interrupt the "Do Until clock=false" loop so that the presentation can advance to the next slide. The idea is for the presentation to be on a continuous loop so I need to macro to stop after the designated slide to avoid any lagging when cycling through.
I have tried to include a timevalue function to add a time onto the current time and give a place to stop, but this seems to have no effect.
Any help would be much appreciated!
Public clock As Boolean
Private Sub Pause()
Dim PauseTime, start
PauseTime = 1
start = Timer
Do While Timer < start + PauseTime
DoEvents
Loop
End Sub
Sub OnSlideshowPageChange(Wn As SlideShowWindow)
Dim currenttime, currenttimecount As Date
Dim currentdate, currentday As String
If Wn.View.Slide.Name = "autoclock 1" Then clock = True
Do Until clock = False
On Error Resume Next
If Weekday(Now) = 1 Then currentday = "Sunday"
If Weekday(Now) = 2 Then currentday = "Monday"
If Weekday(Now) = 3 Then currentday = "Tuesday"
If Weekday(Now) = 4 Then currentday = "Wednesday"
If Weekday(Now) = 5 Then currentday = "Thursday"
If Weekday(Now) = 6 Then currentday = "Friday"
If Weekday(Now) = 7 Then currentday = "Saturday"
currentdate = FormatDateTime(Now, vbLongDate)
currenttime = FormatDateTime(Now, vbLongTime)
currenttimecount = currenttime + TimeValue("00:00:10")
If currenttime = currenttimecount Then clock = False
If clock = False Then SlideShowWindows(1).View.Next
activepresentation.Slides(SlideShowWindows(1).View.CurrentShowPosition).Shapes("shpDayClockAuto").TextFrame.TextRange.Text = currentday & Space(20) & currentdate & Space(15) & currenttime
Pause
Loop
End Sub
Private Sub OnSlideshowTerminate(SW As SlideShowWindow)
clock = False
End Sub

Related

VBA Countdown Timer

I created a countdown timer in VBA from some code I found a while back. The issue is that if I duplicate the timer to use on a different slide, they are both linked and will both start at the same time. This means that when I pause the timer on one slide, it becomes the starting point of the next.
I'm wanting to know what the simplest way is of duplicating my timer where each one is independent of the others. I'm looking to have around 10 timers on 10 different slides.
I've tried copying and pasting the timer, then changing the shape names in the selection panel which the code pulls on as the action buttons. This didn't work the way I thought it would.
I thought about just changing the macros names and then linking it to the new timer. But I couldn't find any macros attached to any of the timer's buttons.
Here is a file with the timer: Timer Powerpoint
(Note: Only 1 timer will work on one slide at a time, so place any duplicate on a different slide. Open in ppt not google slides.)
Any help with this would be amazing.
CODE:
`
Option Explicit
Global timeLeft As Date
Global updateTimer As Boolean
Global timerRunning As Boolean
Global changeTimerbyValue
Global currentTimerSlide As Integer
Global pauseTimer As Boolean
Sub countdownTimer()
On Error Resume Next
Dim thisSlide As Slide
Dim currentSlide As Integer
currentSlide = ActivePresentation.SlideShowWindow.View.Slide.SlideIndex
For Each thisSlide In ActivePresentation.Slides
thisSlide.Shapes("PauseTimer").Visible = True
thisSlide.Shapes("StartTimer").Visible = False
thisSlide.Shapes("EndBackground").Visible = False
thisSlide.Shapes("MainBackground").Visible = True
Next thisSlide
updateTimer = False
timerRunning = True
Dim seconds As Integer
seconds = ActivePresentation.Slides(currentSlide).Shapes("seconds").TextFrame.TextRange
Dim minutes As Integer
minutes = ActivePresentation.Slides(currentSlide).Shapes("minutes").TextFrame.TextRange
Dim hours As Integer
hours = ActivePresentation.Slides(currentSlide).Shapes("hours").TextFrame.TextRange
Dim time As Date
time = hours & ":" & minutes & ":" & seconds
Dim currentTime As Date
currentTime = Now()
Dim timerTime As Date
timerTime = DateAdd("s", seconds + 60 * minutes + 3600 * hours + 0.99, currentTime)
pauseTimer = False
Do Until timerTime < Now()
DoEvents
If (updateTimer = True) Then
timerTime = DateAdd("s", changeTimerbyValue, timerTime)
updateTimer = False
End If
timeLeft = timerTime - Now()
For Each thisSlide In ActivePresentation.Slides
thisSlide.Shapes("hours").TextFrame.TextRange = Format(timeLeft, "hh")
thisSlide.Shapes("minutes").TextFrame.TextRange = Format(timeLeft, "nn")
thisSlide.Shapes("seconds").TextFrame.TextRange = Format(timeLeft, "ss")
Next thisSlide
If (pauseTimer) Then
pauseTimer = False
timerRunning = False
Exit Do
End If
Loop
timerRunning = False
For Each thisSlide In ActivePresentation.Slides
thisSlide.Shapes("PauseTimer").Visible = False
thisSlide.Shapes("StartTimer").Visible = True
Next thisSlide
ActivePresentation.Slides(currentSlide).Shapes("EndBackground").Visible = False
ActivePresentation.Slides(currentSlide).Shapes("MainBackground").Visible = True
If (timerTime < Now()) Then
For Each thisSlide In ActivePresentation.Slides
thisSlide.Shapes("hours").TextFrame.TextRange = Format(0, "hh")
thisSlide.Shapes("minutes").TextFrame.TextRange = Format(0, "nn")
thisSlide.Shapes("seconds").TextFrame.TextRange = Format(0, "ss")
Next thisSlide
ActivePresentation.Slides(currentSlide).Shapes("EndBackground").Visible = True
ActivePresentation.Slides(currentSlide).Shapes("MainBackground").Visible = False
Beep
Call AppWait
Beep
Call AppWait
Beep
Call AppWait
ActivePresentation.Slides(currentSlide).Shapes("EndBackground").Visible = False
ActivePresentation.Slides(currentSlide).Shapes("MainBackground").Visible = True
End If
End Sub
Sub hitPause()
pauseTimer = True
Dim currentSlide As Integer
currentSlide = ActivePresentation.SlideShowWindow.View.Slide.SlideIndex
End Sub
Sub changeTime(ByVal theTime As Integer)
On Error Resume Next
Dim currentSlide As Integer
Dim thisSlide As Slide
currentSlide = ActivePresentation.SlideShowWindow.View.Slide.SlideIndex
If (currentTimerSlide <> currentSlide And currentTimerSlide <> 0 And timerRunning = True) Then
pauseTimer = True
Exit Sub
End If
Dim currentTime As Date
currentTime = Now()
Dim seconds As Integer
seconds = ActivePresentation.Slides(currentSlide).Shapes("seconds").TextFrame.TextRange
Dim minutes As Integer
minutes = ActivePresentation.Slides(currentSlide).Shapes("minutes").TextFrame.TextRange
Dim hours As Integer
hours = ActivePresentation.Slides(currentSlide).Shapes("hours").TextFrame.TextRange
If (timerRunning = True) Then
If (theTime = -3600 And hours = 0) Then
'Do nothing
ElseIf (theTime = -60 And hours = 0 And minutes = 0) Then
'Do nothing
Else
changeTimerbyValue = theTime
updateTimer = True
End If
End If
If (timerRunning = False) Then
Dim time As Date
time = hours & ":" & minutes & ":" & seconds
Dim timerTime As Date
If (theTime = -3600 And hours = 0) Then
timerTime = DateAdd("s", seconds + 60 * minutes + 3600 * hours + 0.99, currentTime)
ElseIf (theTime = -60 And hours = 0 And minutes = 0) Then
timerTime = DateAdd("s", seconds + 60 * minutes + 3600 * hours + 0.99, currentTime)
Else
timerTime = DateAdd("s", seconds + 60 * minutes + 3600 * hours + 0.99, currentTime)
timerTime = DateAdd("s", theTime, timerTime)
End If
timeLeft = timerTime - Now()
For Each thisSlide In ActivePresentation.Slides
thisSlide.Shapes("hours").TextFrame.TextRange = Format(timeLeft, "hh")
thisSlide.Shapes("minutes").TextFrame.TextRange = Format(timeLeft, "nn")
thisSlide.Shapes("seconds").TextFrame.TextRange = Format(timeLeft, "ss")
Next thisSlide
End If
End Sub
Sub increaseSeconds()
changeTime (1)
End Sub
Sub decreaseSeconds()
changeTime (-1)
End Sub
Sub increaseMinutes()
changeTime (60)
End Sub
Sub decreaseMinutes()
changeTime (-60)
End Sub
Sub increaseHours()
changeTime (3600)
End Sub
Sub decreaseHours()
changeTime (-3600)
End Sub
Sub startTimer()
If (timerRunning = False) Then
Call countdownTimer
End If
End Sub
Sub AppWait()
Dim WAIT As Double
WAIT = Timer
While Timer < WAIT + 0.75 ' 1 seconds
DoEvents 'do nothing
Wend
End Sub
`
You can duplicate timelimit and countdown objects on each slide you need. Just make sure those objects have exactly the same names. Then, you can get the active slide in a Loop. On activating another slide, the countdown object on that slide will be updating.
Something like this:
Sub countdown()
Dim activeSlide As Slide
Dim count As Integer
Dim tstart As Date
Dim tend As Date
tstart = Now()
Do While True
DoEvents
Set activeSlide = _
PowerPoint.Application.ActiveWindow.View.Slide
count = activeSlide.Shapes("timelimit").TextFrame.TextRange
tend = DateAdd("n", count, tstart)
activeSlide.Shapes("countdown").TextFrame.TextRange = _
Format((tend - Now()), "nn:ss")
If tend < Now() Then
activeSlide.Shapes("countdown").TextFrame.TextRange = "TIME UP"
End If
Loop
End Sub

Fade volume of background media on specific slide in PowerPoint using VBA

I have a PowerPoint which begins with a a media file automatically playing. The first slide is programmed to transition after 20 seconds, all the while the music keeps playing. I would like for it to keep playing for the duration of the slideshow, but fade to a lower volume once the second slide appears and remain that way for the rest of the presentation. I've looked at this Powerpoint change sound effect volume in macro but it doesn't seem to satisfy my needs.
I tried this:
Sub fadeVolSlideChange(ByVal ShowPos As SlideShowWindow)
Dim ShowPos As Integer
Dim bkgMusic As Shape
Dim Step As Long
ShowPos = ShowPos.View.CurrentShowPosition
Set bkgMusic = ActiveWindow.Selection.ShapeRange(1)
If ShowPos = 2 Then
Set Step = 0.05
For i = 1 To 0.5
With bkgMusic.MediaFormat
.Volume = i
.Muted = False
End With
i = i - Step
Application.Wait (Now + 0.0000025)
Next i
End If
End Sub
With no luck. Thoughts?
Here's the latest edit (still no luck getting it to work):
Sub OnSlideShowPageChange()
Dim i As Integer
Dim bkgMusic As Shape
Dim bkgVol As Long
Dim inc As Long
i = ActivePresentation.SlideShowWindow.View.CurrentShowPosition
Set bkgMusic = ActivePresentation.Slides(1).Shapes("Opening Theme")
If i = 1 Then
'Do nothing
ElseIf i <> 1 Then
inc = 0.05
For bkgVol = 1 To 0.1
With bkgMusic.MediaFormat
.Volume = bkgVol
.Muted = False
End With
bkgVol = bkgVol - inc
Application.Wait (Now + TimeValue("0:00:01"))
Next bkgVol
End If
End Sub
This almost works, but PPT shoots us down in the end. After it runs, the volume of the sound file has been reduced, but it doesn't change during the slideshow.
Sub OnSlideShowPageChange()
Dim i As Integer
Dim bkgMusic As Shape
' This needs to be single, not Long
Dim bkgVol As Single
Dim inc As Long
Dim lCounter As Long
i = ActivePresentation.SlideShowWindow.View.CurrentShowPosition
Set bkgMusic = ActivePresentation.Slides(1).Shapes("Opening Theme")
If i = 2 Then
inc = 0.05
' Changing the value by fractions so must be a single, not a long, and
' decreasing the value requires Step and a negative number:
For bkgVol = 1 To 0.1 Step -0.1
With bkgMusic.MediaFormat
.Volume = bkgVol
.Muted = False
End With
'bkgVol = bkgVol - inc
' Application.Wait is not supported in PPT
'Application.Wait (Now + TimeValue("0:00:01"))
WaitForIt
SlideShowWindows(1).View.GotoSlide (2)
Next bkgVol
End If
End Sub
Sub WaitForIt()
Dim x As Long
For x = 1 To 1000000
DoEvents
Next
'MsgBox "Done waiting"
End Sub

Excel SUM formula doesn't work for hours from VBA

I have VBA that counts time spent on the project and after user is pressing STOP button it enters time into other sheet. Everything is working fine expect for SUM formula to calculate total amount of hours spent. Formula =SUM(A2:A15290) gives value of 00:00:00 (zero) in cell A1. I have tried to "Format cell" in different ways but nothing works. If I enter time manually to cells, then everything works fine. Maybe problem is in my VBA that is entering counted time to cells?
Here is the macro I am using:
Option Explicit
Sub StartTimer()
Dim Start As Single, RunTime As Single
Dim ElapsedTime As String
'Set the control cell to 0 and make it green
Range("Y18").Value = 0
Range("Y14").Interior.Color = 5296274 'Green
Start = Timer ' Set start time.
Debug.Print Start
Do While Range("Y18").Value = 0
DoEvents ' Yield to other processes.
RunTime = Timer ' current elapsed time
ElapsedTime = Format((RunTime - Start) / 86400, "h:mm:ss")
'Display currently elapsed time in A1
Range("Y14").Value = ElapsedTime
Application.StatusBar = ElapsedTime
Loop
Range("Y14").Value = ElapsedTime
Range("Y14").Interior.Color = 192 'Dark red
Application.StatusBar = False
End Sub
Sub StopTimer()
Application.ScreenUpdating = False
Dim copySheet As Worksheet
Dim pasteSheet As Worksheet
'Set the control cell to 1
Range("Y18").Value = 1
Set copySheet = Worksheets("MAIN")
Set pasteSheet = Worksheets("Time Spent")
copySheet.Range("Y14").Copy
pasteSheet.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
You are putting text-that-looks-like-time into the cells. Use real time.
Dim Start As DOUBLE, RunTime As DOUBLE
Dim ElapsedTime As DOUBLE
...
Start = Timer ' Set start time.
...
DoEvents ' Yield to other processes.
RunTime = Timer ' current elapsed time
ElapsedTime = (RunTime - Start) / 86400
Range("Y14").Value = ElapsedTime
Range("Y14").numberformat = "[hh]:mm:ss"
Remember to be careful about a start and end that cross midnight. Timer resets at midnight and Excel doesn't like negative time.

Manually change a cell value without breaking an infinite loop in a running macro?

I want to make a macro that has an infinite loop. in this loop, I change values of cells every second.
I want to manually change a cell without stopping the macro (Alpha variable in the code). Is there any workaround to make it possible ? or threads ?
here is my code :
Sub test()
Dim wb As Workbook
Dim ws As Worksheet
Dim i As Integer
i = 0
Set wb = ActiveWorkbook
Set ws = wb.Sheets("Sheet1")
Set P1 = ws.Range("A1")
Set Q1 = ws.Range("A2")
Set Alpha = ws.Range("G1")
On Error GoTo CleanExit
If Target.Address = "$Q$21" Then
Application.EnableEvents = False
End If
CleanExit:
Application.EnableEvents = True
While i = 0
P1.Value = 100 + WorksheetFunction.RandBetween(1, 6)
Q1.Value = Alpha
Pause (1)
Wend
On Error GoTo 0
End Sub
and here is the Pause function:
Public Function Pause(NumberOfSeconds As Variant)
On Error GoTo Error_GoTo
Dim PauseTime As Variant
Dim Start As Variant
Dim Elapsed As Variant
PauseTime = NumberOfSeconds
Start = Timer
Elapsed = 0
Do While Timer < Start + PauseTime
Elapsed = Elapsed + 1
If Timer = 0 Then
' Crossing midnight
PauseTime = PauseTime - Elapsed
Start = 0
Elapsed = 0
End If
DoEvents
Loop
Exit_GoTo:
On Error GoTo 0
Exit Function
Error_GoTo:
Debug.Print Err.Number, Err.Description, Erl
GoTo Exit_GoTo
End Function
When I select the cell, I get the Error 1004 "Application-defined or Object-defined error"
Basically, I want to simulate the functioning of hydraulic pump, there is an angle alpha that varies. If alpha changes the other parameters (pressure , flow ...) change. that's why I want to make a continuous loop on the parameter with some error every second(with the random function). When alpha changes (manually), The parameter change the value.That is the main Idea.
For repeated Calculations using data from the worksheet I would use a construction like the following. It uses the Application.OnTime Event to run the procedure repeatedly (~ every second) until some condition is met (or a stop precedure is called). I used some simple code to show that you can enter data in the worksheet:
Option Explicit
Private Running As Boolean
Sub Start_Timer()
Running = True
Application.OnTime Now + TimeSerial(0, 0, 1), "Timed_Code"
End Sub
Sub Stop_Timer()
Running = False
End Sub
Sub Timed_Code()
If [A1] = False Then Call Stop_Timer
[C1] = [B1] + Application.WorksheetFunction.RandBetween(1, 6)
If Running Then Application.OnTime Now + TimeSerial(0, 0, 1), "Timed_Code"
End Sub

Vba Stopwatch unintendently resets back 0 when changing other cells

I have a VBA stopwatch in my Excel spreadsheet, code:
Public StopIt As Boolean
Public ResetIt As Boolean
Public LastTime
Private Sub CommandButton1_Click()
Dim StartTime, FinishTime, TotalTime, PauseTime
StopIt = False
ResetIt = False
If Range("C2") = 0 Then
StartTime = Timer
PauseTime = 0
LastTime = 0
Else
StartTime = 0
PauseTime = Timer
End If
StartIt:
DoEvents
If StopIt = True Then
LastTime = TotalTime
Exit Sub
Else
FinishTime = Timer
TotalTime = FinishTime - StartTime + LastTime - PauseTime
TTime = TotalTime * 100
HM = TTime Mod 100
TTime = TTime \ 100
hh = TTime \ 3600
TTime = TTime Mod 3600
MM = TTime \ 60
SS = TTime Mod 60
Range("C2").Value = Format(hh, "00") & ":" & Format(MM, "00") & ":" & Format(SS, "00") & "." & Format(HM, "00")
If ResetIt = True Then
Range("C2") = Format(0, "00") & ":" & Format(0, "00") & ":" & Format(0, "00") & "." & Format(0, "00")
LastTime = 0
PauseTime = 0
End
End If
GoTo StartIt
End If
End Sub
Private Sub CommandButton2_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
StopIt = True
End Sub
Private Sub CommandButton3_Click()
Range("C2").Value = Format(0, "00") & ":" & Format(0, "00") & ":" & Format(0, "00") & "." & Format(0, "00")
LastTime = 0
ResetIt = True
End Sub
This stopwatch works correctly. My problem is that when I change a cell in my spreadsheet or make any changes it resets the stopwatch to '0'.
I want it to run throughout my session as I have other cells which refer to this counter.
Any help would be greatly appreciated. I could not find any similar problems while searching for a solution to this.
Thanks
Not sure if you have found a solution yet, but I did some research and think I know why your code doesn't work, and possibly have another solution... if acceptable...
When I test your code by starting the timer then changing any cell, it doesn't reset to zero but it does stop the timer. Looking at the code you have (which maybe came from https://www.extendoffice.com/documents/excel/3684-excel-create-stopwatch.html), the code is only good for using a simple timer ... nothing else. And since it is never relinquishes control until you stop it, it uses a tremendous amount of your processor (take a look at Task Manager!)
I did find code here on Stack VBA Macro On Timer style to run code every set number of seconds, i.e. 120 seconds and used the second answer (simply too lazy to use first answer at startup).
You can now change cells and the code continues to run (except it 'pauses' while a change is being made to a cell). You may not like the fact that it increments by seconds, but maybe someone else knows a solution to that.
The code does NOT go in a sheet module.
Option Explicit
Dim TimerActive As Boolean
Sub StartTimer()
Start_Timer
End Sub
Private Sub Start_Timer()
TimerActive = True
Application.OnTime Now() + TimeValue("00:00:01"), "Timer"
End Sub
Private Sub Stop_Timer()
TimerActive = False
End Sub
Private Sub Timer()
If TimerActive Then
Activesheet.Cells(2, 3).value = Time
Application.OnTime Now() + TimeValue("00:00:01"), "Timer"
End If
End Sub