Vba Stopwatch unintendently resets back 0 when changing other cells - vba

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

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

How to interrupt live Clock loop for next slide transition?

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

Create Stopwatch in Excel that runs while the sheet is manipulated

I'm trying to create a stopwatch in Excel in cell K1 with Start and Stop buttons that continues to run even if other cells are updated on the sheet.
I'm trying this code below in the sheet's VBA window, but I keep getting an error message saying "Cannot run the Macro 'UpdateTime'. The macro may not be available in this workbook or all macros may be disabled." I'm positive that macros are enabled and the file is saved as a .xlsm. How should I update the code to make it work?
Sub UpdateTime()
Range("K1").Value = Now - gdtStart
DoEvents
If Not gbStop Then
Application.OnTime Now + TimeSerial(0, 0, 1), "UpdateTime"
End If
End Sub
Private Sub CommandButton1_Click()
Range("K1") = Format(0, "00") & ":" & Format(0, "00") & ":" & Format(0,
"00")
gbStop = False
gdtStart = Now
Application.OnTime Now + TimeSerial(0, 0, 1), "UpdateTime"
End Sub
Private Sub CommandButton2_Click()
gbStop = True
End Sub
screenshot of the modules/sheets available

Countdown after button click

I would like to make a countdown, so I've set a cell, E1 with time format, and given 0:02:55 as start time. After that I try to make coutdown after button click with this code, but got an error, that it isn't runnable.
Sub Timer()
Dim gCount As Date
gCount = Now + TimeValue("00:00:01")
Application.OnTime gCount, "ResetTime"
End Sub
Sub ResetTime()
Dim xRng As Range
Set xRng = Application.ActiveSheet.Range("E1")
xRng.Value = xRng.Value - TimeSerial(0, 0, 1)
If xRng.Value <= 0 Then
MsgBox "Countdown complete."
Exit Sub
End If
Call Timer
End Sub

Entering Dates Without Slashes

I sometimes have to enter a lot of dates in Excel spreadsheets. Having to enter the slashes slows things down a lot and makes the process more error prone. On many database programs, it is possible to enter the dates using only the numbers.
I have written a SheetChange event handler that lets me do this when entering dates in cells formatted as dates, but it fails if I copy a date from one location to another. If I could determine when an entry has been copied as opposed to entered, I could handle the two cases separately, but I have not been able to determine this yet.
Here is my code, but before you look at it, be aware that the last section handles inserting a decimal point automatically and it seems to be working ok. Finally, I added some variables (sValue, sValue2, etc.) to make it a little easier for me to track the data.
Option Explicit
Private WithEvents App As Application
Private Sub Class_Initialize()
Set App = Application
End Sub
Private Sub App_SheetChange(ByVal Sh As Object, ByVal Source As Range)
Dim s As String
Dim sFormat As String
Dim sValue As String
Dim sValue2 As String
Dim sFormula As String
Dim sText As String
Dim iPos As Integer
Dim sDate As String
On Error GoTo ErrHandler:
If Source.Cells.Count > 1 Then
Exit Sub
End If
If InStr(Source.Formula, "=") > 0 Then
Exit Sub
End If
sFormat = Source.NumberFormat
sFormula = Source.Formula
sText = Source.Text
sValue2 = Source.Value2
sValue = Source.Value
iPos = InStr(sFormat, ";")
If iPos > 0 Then sFormat = Left(sFormat, iPos - 1)
If InStr("m/d/yy|m/d/yyyy|mm/dd/yy|mm/dd/yyyy|mm/dd/yy", sFormat) > 0 Then
If IsDate(Source.Value2) Then
Exit Sub
End If
If IsNumeric(Source.Value2) Then
s = CStr(Source.Value2)
If Len(s) = 5 Then s = "0" & s
If Len(s) = 6 Then
s = Left(s, 2) & "/" & Mid(s, 3, 2) & "/" & Right(s, 2)
App.EnableEvents = False
If IsDate(s) Then Source.Value = s 'else source is unchanged
App.EnableEvents = True
End If
If Len(s) = 7 Then s = "0" & s
If Len(s) = 8 Then
s = Left(s, 2) & "/" & Mid(s, 3, 2) & "/" & Right(s, 4)
App.EnableEvents = False
If IsDate(s) Then Source.Value = s 'else source is unchanged
App.EnableEvents = True
End If
End If
End If
If InStr(sFormat, "0.00") > 0 Then
If IsNumeric(Source.Formula) Then
s = Source.Formula
If InStr(".", s) = 0 Then
s = Left(s, Len(s) - 2) & "." & Right(s, 2)
App.EnableEvents = False
Source.Formula = CDbl(s)
App.EnableEvents = True
End If
End If
End If
ErrHandler:
App.EnableEvents = True
End Sub
Do you know how I can get this to work for copied dates as well as edited dates? Thanks for your help.
Actually, the event Worksheet_Change is called when copy/pasting, so it should work.
Just tested with:
Private Sub Worksheet_Change(ByVal Target As Range)
MsgBox "Test"
End Sub