+ Reply to Thread
Results 1 to 8 of 8

How to Keep Running Stopwatch running when using other sheets and other workbooks

Hybrid View

  1. #1
    Registered User
    Join Date
    10-30-2019
    Location
    Boston, MA
    MS-Off Ver
    365
    Posts
    3

    How to Keep Running Stopwatch running when using other sheets and other workbooks

    Hi All,
    I am new to VBA and most of what I know comes from the internet. I have created a worksheet that will allow our team to track how much time they are spending on certain tasks by use of active stopwatch timers. The timers keep cumulative time by what I am sure is a really primitive method. Each time the timer stops it adds the time to another sheet that then feeds back into the active sheet to keep the total time worked. However, the timers are stopping when I try to do other work. I need the timers to continue even when someone is working on other sheets and workbooks (with macros). The intention is for someone to open this and start the timer and then go about their work. I attached the file.
    Attached Files Attached Files

  2. #2
    Forum Moderator Leith Ross's Avatar
    Join Date
    01-15-2005
    Location
    San Francisco, Ca
    MS-Off Ver
    2000, 2003, & 2010
    Posts
    23,259

    Re: How to Keep Running Stopwatch running when using other sheets and other workbooks

    Hello CloudNine1234,

    Welcome to the forum!

    Please either post the VBA Project password or post another workbook that is unlocked.
    Sincerely,
    Leith Ross

    Remember To Do the Following....

    1. Use code tags. Place [CODE] before the first line of code and [/CODE] after the last line of code.
    2. Thank those who have helped you by clicking the Star below the post.
    3. Please mark your post [SOLVED] if it has been answered satisfactorily.


    Old Scottish Proverb...
    Luathaid gu deanamh maille! (Rushing causes delays!)

  3. #3
    Registered User
    Join Date
    10-30-2019
    Location
    Boston, MA
    MS-Off Ver
    365
    Posts
    3

    Re: How to Keep Running Stopwatch running when using other sheets and other workbooks

    Oops. Sorry about that. The passwords are all “contracts”

  4. #4
    Registered User
    Join Date
    10-30-2019
    Location
    Boston, MA
    MS-Off Ver
    365
    Posts
    3

    Re: How to Keep Running Stopwatch running when using other sheets and other workbooks

    Hi again, I know everyone is super busy, but if anyone could help me that would be amazing. This tracker is super important for me and if I can get it to work it be great!

  5. #5
    Forum Expert
    Join Date
    01-23-2013
    Location
    USA
    MS-Off Ver
    Microsoft 365 aka Office 365
    Posts
    3,863

    Re: How to Keep Running Stopwatch running when using other sheets and other workbooks

    Hi #9,

    There are several ways to create timers to do what you want. I have tried 5 that I know of and they all fail in Office 365 (cause Excel to hang up or crash) when you try to enter data into a cell.

    Having said that, I was successful by manually (CommandButton) turning off the timer while entering data into a cell. Then I used another CommandButton to turn the timer back on. The Elapsed time was correct.

    A second method is to have the Workbook in a separate instance of Excel. See https://excelgorilla.com/excel/gener...stances-excel/

    Lewis

  6. #6
    Forum Expert
    Join Date
    01-23-2013
    Location
    USA
    MS-Off Ver
    Microsoft 365 aka Office 365
    Posts
    3,863

    Re: How to Keep Running Stopwatch running when using other sheets and other workbooks

    I was successful in doing what you want. I will post the solution in the next reply.

    In this reply I will post code for five different timing methods.

    See the attached file for five different timing methods implemented on a Spreadsheet and also in a UserForm. Each method has pros and cons listed in the file.
    a. Software loop
    b. API Sleep() function
    c. Application.Wait
    d. Application.OnTime
    e. API SetTimer function

    NOTE: The SetTimer method will cause Excel to crash if VBA code is modifying cells at the same time the User is updating the Spreadsheet.
    The use of formulas to implement API SetTimer (courtesy of Jaafar Tribak) is a workaround to this problem
    See May 27, 2009 post #3 in https://www.mrexcel.com/board/thread...t-cell.392397/
    Thank you Jaafar

    The code below is for Spreadsheet implementations. For UserForm implementation see the attached file.
    In an ordinary code module (e.g. ModOneSecondDelayExamples):
    Option Explicit
    
    'NOTE: This has NOT BEEN tested using 64 bit Excel
    
    #If VBA7 And Win64 Then
        ' 64 bit Excel
        'The following line is supposed to be RED in 32 bit Excel
        Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
    #Else
        ' 32 bit Excel
        Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
    #End If
    
    'NOTE: This has not been tested in 64 bit Excel
    
    #If VBA7 And Win64 Then
      'All of the Win64 lines are supposed to be RED in 32 bit Excel
    
      ' Returns an unsigned long pointer (nIDEvent) if the timer is created. Failure returns a zero.
      Public Declare PtrSafe Function SetTimer _
          Lib "User32.dll" _
              (ByVal HWnd As LongPtr, _
               ByVal nIDEvent As LongPtr, _
               ByVal uElapse As Long, _
               ByVal lpTimerFunc As LongPtr) _
          As LongPtr
    
      Public Declare PtrSafe Function KillTimer _
          Lib "User32.dll" _
              (ByVal HWnd As LongPtr, _
               ByVal nIDEvent As LongPtr) _
          As Long
    
      Public lTimerIdAddress As LongPtr
    
    #Else
    
      ' Returns an unsigned long pointer (nIDEvent) if the timer is created. Failure returns a zero.
      Public Declare Function SetTimer _
          Lib "User32.dll" _
              (ByVal HWnd As Long, _
               ByVal nIDEvent As Long, _
               ByVal uElapse As Long, _
               ByVal lpTimerFunc As Long) _
          As Long
    
      Public Declare Function KillTimer _
          Lib "User32.dll" _
              (ByVal HWnd As Long, _
               ByVal nIDEvent As Long) _
          As Long
    
      Public lTimerIdAddress As Long
    
    #End If
    
    
    'Global Constants
    Private Const sGblMacroNameADDRESS = "B18"
    Private Const sGblStatusADDRESS = "B20"
    Private Const sGblBaselineDateAndTimeADDRESS = "B22"
    Private Const sGblElapsedTimeADDRESS = "B24"
    
    'Global Variables
    Private myGblTargetCellRange As Range
    
    Sub TenSecondTimerUsingALoop()
      'This demonstrates of use of a loop to simulate a Timer
      'When used with an active Spreadsheet processing sometimes stops in Windows 10 when something is typed in a Cell
      '
      'NOTE: 'Application.EnableEvents = False' does not help
      
      Dim myBaselineDateAndTime As Date
    
      Dim i As Long
      Dim j As Long
      Dim k As Long
      
      i = 0
      
      myBaselineDateAndTime = Now()
      ThisWorkbook.Sheets("Sheet1").Range(sGblMacroNameADDRESS).Value = "TenSecondTimerUsingALoop()"
      ThisWorkbook.Sheets("Sheet1").Range(sGblStatusADDRESS).Value = "In Progress"
      ThisWorkbook.Sheets("Sheet1").Range(sGblBaselineDateAndTimeADDRESS).Value = myBaselineDateAndTime
      
      'Loop for 10 Counts
      While i < 10
    
        'Display the Elapsed Time on the Spreadsheet
        ThisWorkbook.Sheets("Sheet1").Range(sGblElapsedTimeADDRESS).Value = Now() - myBaselineDateAndTime
      
        'Increment the Counter
        'Output to the Immediate Window (CTRL G in the Debugger)
        'Wait one second approximately on my computer (each computer is different)
        'NOTE: There is a large amount of overhead time in 'DoEvents'
        i = i + 1
        For j = 1 To 100
          For k = 1 To 160
            DoEvents
          Next k
        Next j
      Wend
    
      ThisWorkbook.Sheets("Sheet1").Range(sGblStatusADDRESS).Value = "Done"
    
    End Sub
    
    
    Sub TenSecondTimerUsingSleep()
      'This demonstrates of API 'Sleep' Routine
      'When used with an active Spreadsheet processing stops in Windows 10 when something is typed in a Cell
      '
      'NOTE: 'Application.EnableEvents = False' does not help
    
      Dim myBaselineDateAndTime As Date
    
      Dim i As Long
      
      i = 0
      
      myBaselineDateAndTime = Now()
      ThisWorkbook.Sheets("Sheet1").Range(sGblMacroNameADDRESS).Value = "TenSecondTimerUsingSleep()"
      ThisWorkbook.Sheets("Sheet1").Range(sGblStatusADDRESS).Value = "In Progress"
      ThisWorkbook.Sheets("Sheet1").Range(sGblBaselineDateAndTimeADDRESS).Value = myBaselineDateAndTime
      
      'Loop for 10 Counts
      While i < 40
    
        'Display the Elapsed Time on the Spreadsheet
        ThisWorkbook.Sheets("Sheet1").Range(sGblElapsedTimeADDRESS).Value = Now() - myBaselineDateAndTime
        
        'Increment the Counter
        'Wait one second
        i = i + 1
        DoEvents
        Sleep 250            '250 milliseconds = 1/4 Second
        DoEvents
    
      Wend
    
      ThisWorkbook.Sheets("Sheet1").Range(sGblStatusADDRESS).Value = "Done"
    
    End Sub
    
    Sub TenSecondTimerUsingApplicationDotWait()
      'This demonstrates the Use of Application.Wait
      'When used with an active Spreadsheet the Windows 10 'Circle of Hell' is always present
    
      Dim myBaselineDateAndTime As Date
    
      Dim i As Long
      
      i = 0
    
      myBaselineDateAndTime = Now()
      ThisWorkbook.Sheets("Sheet1").Range(sGblMacroNameADDRESS).Value = "TenSecondTimerUsingApplicationDotWait()"
      ThisWorkbook.Sheets("Sheet1").Range(sGblStatusADDRESS).Value = "In Progress"
      ThisWorkbook.Sheets("Sheet1").Range(sGblBaselineDateAndTimeADDRESS).Value = myBaselineDateAndTime
      
      'Loop for 10 Counts
      While i <= 10
    
        'Display the Elapsed Time on the Spreadsheet
        ThisWorkbook.Sheets("Sheet1").Range(sGblElapsedTimeADDRESS).Value = Now() - myBaselineDateAndTime
      
        'Increment the Counter
        'Output to the Immediate Window (CTRL G in the Debugger)
        'Wait one second
        i = i + 1
        Application.Wait (Now() + TimeValue("0:00:01"))
    
      Wend
    
      ThisWorkbook.Sheets("Sheet1").Range(sGblStatusADDRESS).Value = "Done"
    
    End Sub
    
    Sub TenSecondTimerUsingApplicationDotOnTime()
      'This demonstrates the Use of Application.OnTime
      'When used with an active Spreadsheet there is screen Flicker but data CAN be entered in Cells (processsing halts until cell is released)
    
      Static myBaselineDateAndTime As Date
    
      Static i As Long
      
      'Reset the Counter if i is Greater than 10
      'so the routine can run if executed more than once
      If i > 10 Then
        i = 0
      End If
      
      If i = 0 Then
        myBaselineDateAndTime = Now()
        ThisWorkbook.Sheets("Sheet1").Range(sGblMacroNameADDRESS).Value = "TenSecondTimerUsingApplicationDotOnTime()"
        ThisWorkbook.Sheets("Sheet1").Range(sGblStatusADDRESS).Value = "In Progress"
        ThisWorkbook.Sheets("Sheet1").Range(sGblBaselineDateAndTimeADDRESS).Value = myBaselineDateAndTime
      End If
    
      'Display the Elapsed Time on the Spreadsheet
      ThisWorkbook.Sheets("Sheet1").Range(sGblElapsedTimeADDRESS).Value = Now() - myBaselineDateAndTime
      
      'Increment the Counter
      'Output to the Immediate Window (CTRL G in the Debugger)
      i = i + 1
      Debug.Print i, Now()
        
      'Schedule the Event Handler (this routine) in one second
      'unless the counter is 10 or more
      If i <= 10 Then
        Application.OnTime (Now + TimeValue("0:00:01")), "TenSecondTimerUsingApplicationDotOnTime"
      Else
        ThisWorkbook.Sheets("Sheet1").Range(sGblStatusADDRESS).Value = "Done"
      End If
    
    End Sub
    
    
    Sub StopAPITimer()
      'This stops the API Timer
      
      KillTimer 0, lTimerIdAddress
      
      ThisWorkbook.Sheets("Sheet1").Range(sGblStatusADDRESS).Value = "Done"
      
      'Remove the Formula from the Elapsed Time so it does not get updated
      ThisWorkbook.Sheets("Sheet1").Range(sGblElapsedTimeADDRESS).Value = ThisWorkbook.Sheets("Sheet1").Range(sGblElapsedTimeADDRESS).Value
      
    End Sub
    
    
    Sub StartAPITimerExample()
      'This is called by the User to Start the API Timer
      '
      'The use of formulas to implement API Timer is courtesy of Jaafar Tribak
      'See May 27, 2009 post #3 in https://www.mrexcel.com/board/threads/problems-with-running-clock-in-worksheet-cell.392397/
      'Thank you Jaafar
      
      Const iTimerRepeatRateMILLISECONDS As Long = 1000   '1000 milliseconds = one second
      
      Dim myBaselineDateAndTime As Date
      
      'Stop the Clock if it is running
      Call StopAPITimer
        
      myBaselineDateAndTime = Now()
      ThisWorkbook.Sheets("Sheet1").Range(sGblMacroNameADDRESS).Value = "APITimerOneSecondDelayExampleEventHandler()"
      ThisWorkbook.Sheets("Sheet1").Range(sGblStatusADDRESS).Value = "In Progress"
      ThisWorkbook.Sheets("Sheet1").Range(sGblBaselineDateAndTimeADDRESS).Value = myBaselineDateAndTime
      
      'Put a formula in the 'Clock in Cell' Address (of the form '=TEXT(NOW()- B22,"hh:mm:ss")'
      Set myGblTargetCellRange = ThisWorkbook.Sheets("Sheet1").Range(sGblElapsedTimeADDRESS)
      myGblTargetCellRange.Formula = "=TEXT(NOW()- " & sGblBaselineDateAndTimeADDRESS & ",""hh:mm:ss"")"
      
      'This starts a timer that will repeat until stopped
      lTimerIdAddress = SetTimer(0, 0, iTimerRepeatRateMILLISECONDS, AddressOf APITimerOneSecondDelayExampleEventHandler)
      
    End Sub
    
    Sub APITimerOneSecondDelayExampleEventHandler()
      'This demonstrates the Use of a Windows API Timer
      'When used with an active Spreadsheet processing stops and Excel crashes
    
      'Update the Cells with Formulas that need to be Updated
      'When Deleting Sheets 'Runtime Error 50290        Application-defined or object-defined error'
      On Error Resume Next
      ThisWorkbook.Sheets("Sheet1").Range(sGblElapsedTimeADDRESS).Calculate
      If Err.Number <> 0 Then
        'Output to the Immediate Window (CTRL G in the Debugger) when there is a Runtime Error
        Debug.Print "APITimerOneSecondDelayExampleEventHandler()", Err.Number, Err.Description, Now()
      End If
      On Error GoTo 0
      
    End Sub
    Lewis

  7. #7
    Forum Expert
    Join Date
    01-23-2013
    Location
    USA
    MS-Off Ver
    Microsoft 365 aka Office 365
    Posts
    3,863

    Re: How to Keep Running Stopwatch running when using other sheets and other workbooks

    I was successful in modifying your spreadsheet to allow Modifying the spreadsheet (including UNDO) without stopping the timers and without crashing Excel.
    The use of formulas to implement API Timer is courtesy of Jaafar Tribak
    See May 27, 2009 post #3 in https://www.mrexcel.com/board/thread...t-cell.392397/
    Thank you Jaafar
    Please note that 'real time' code is difficult to debug, so there may still exist some unwanted 'side effects'. Please let me know if you have any problems.

    Notes:
    a. Implemented two timers only - Client Tasks 1 and 2.
    Multiple Timers can run simultaneously or there is a limit of one 'Active Timer' only - chosen by a PERMANENT VBA change. See Sub LogicallyStopAllTimers() for instructions.
    Whether one or multiple Logical Timers, there is only one SetTimer() Timer running.
    b. Sub AdjustValue() in code module ModOriginal was changed to xAdjustValue() to avoid a conflict with a modified routine in code module ModNew.
    c. The remainder of Sheet2 Code module VBA was NOT changed - Reset should work exactly as before.
    d. Client Timer1 and Timer2 code was commented out in Code Module ModOriginal.
    e. When Deleting Sheets Runtime Error Occurs (50290 = Application-defined or object-defined error) but is trapped by the software.

    How the software works:
    a. One API Timer is used using API code SetTimer() and KillTimer().
    SetTimer() creates a timer that repeats at a specified interval until stopper by KillTimer().
    b. Your data design was left intact as much as possible. VBA code affects Sheet 'Data_tab' as follows using 'Client Timer 1' as an example:
    (1) Cell X3 = No change
    (2) Column W = No change
    (3) Cell V3 contains the formula '=NOW() - Data_tab!U3' when Timer1 is active
    (3) Cell V3 = the VALUE that was in cell V3 when STOP was Clicked
    (4) CellU3 = the Baseline (when Start was Clicked) Date and Time when Timer1 is active
    (4) CellU3 = BLANK when Timer1 is NOT active
    c. Sub APITimerEventHandler() runs each wake cycle of the generic timer (approximately at 1 second intervals)
    APITimerEventHandler() causes 'Calculate' to occur for each active timer (e.g. Cell V3 for Client Timer1.
    The use of 'Calculate' instead of writing to the spreadsheet directly allows Spreadsheet changes including Adding Sheets and UNDO while the Timer is running.
    It is recommended that Suspend/Resume be used when Deleting Sheets.
    d. Modifying VBA while the Timer is active can cause Excel to crash. The use of the 'Suspend' and 'Resume' CommandButtons can stop this from happening.
    e. Occassionally Runtime Error '50290 Application-defined or object-defined error' occurs. 'On Error Resume Next' (i.e. ignoring the error) seems to mitigate the problem.

    Important code excerpts follow. See the attached file for complete code:
    Option Explicit
    
    'The use of formulas to implement API Timer is courtesy of Jaafar Tribak
    'See May 27, 2009 post #3 in https://www.mrexcel.com/board/threads/problems-with-running-clock-in-worksheet-cell.392397/
    'Thank you Jaafar
    
    'NOTE: This has NOT BEEN tested using 64 bit Excel
    
    #If VBA7 And Win64 Then
        ' 64 bit Excel
        'The following line is supposed to be RED in 32 bit Excel
        Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
    #Else
        ' 32 bit Excel
        Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
    #End If
    
    'NOTE: This has not been tested in 64 bit Excel
    
    #If VBA7 And Win64 Then
      'All of the Win64 lines are supposed to be RED in 32 bit Excel
    
      ' Returns an unsigned long pointer (nIDEvent) if the timer is created. Failure returns a zero.
      Public Declare PtrSafe Function SetTimer _
          Lib "User32.dll" _
              (ByVal HWnd As LongPtr, _
               ByVal nIDEvent As LongPtr, _
               ByVal uElapse As Long, _
               ByVal lpTimerFunc As LongPtr) _
          As LongPtr
    
      Public Declare PtrSafe Function KillTimer _
          Lib "User32.dll" _
              (ByVal HWnd As LongPtr, _
               ByVal nIDEvent As LongPtr) _
          As Long
    
      Public lTimerIdAddress As LongPtr
    
    #Else
    
      ' Returns an unsigned long pointer (nIDEvent) if the timer is created. Failure returns a zero.
      Public Declare Function SetTimer _
          Lib "User32.dll" _
              (ByVal HWnd As Long, _
               ByVal nIDEvent As Long, _
               ByVal uElapse As Long, _
               ByVal lpTimerFunc As Long) _
          As Long
    
      Public Declare Function KillTimer _
          Lib "User32.dll" _
              (ByVal HWnd As Long, _
               ByVal nIDEvent As Long) _
          As Long
    
      Public lTimerIdAddress As Long
    
    #End If
    
    Type TimerDataStructureType
      sElapsedTimeCell As String
      sAdjustmentCell As String
    End Type
    
    Public Const FIVE_MINUTES As Double = 5# / 86400#
    
    Public Const sColorACTIVE = "Green"
    Public Const sColorINACTIVE = "Pink"
    Public Const sColorSUSPENDED = "Orange"
    
    Public Const sApiTimerSuspendedCELL = "F17"
    Public Const sActiveTimerInfoCELL = "F21"
    Public Const sActiveTimerCountInfoCELL = "F22"
    
    
    Public bGblAPITimerSuspended As Boolean
    Public iGblActiveClientTimerCount As Long
    
    Public Const sGblClientTimer1CELL = "I9"
    Public Const sGblClientTimer2CELL = "I10"
    Public Const sGblClientTimer3CELL = "I11"
    Public Const sGblClientTimer4CELL = "I12"
    Public Const sGblClientTimer5CELL = "I13"
    
    Public bGblActiveClientTimer1 As Boolean
    Public bGblActiveClientTimer2 As Boolean
    Public bGblActiveClientTimer3 As Boolean
    Public bGblActiveClientTimer4 As Boolean
    Public bGblActiveClientTimer5 As Boolean
    
    
    
    
    Sub StopAPITimer()
      'This stops the API Timer
      
      'Stop the Timer
      KillTimer 0, lTimerIdAddress
      
    End Sub
    
    
    Sub StartAPITimer()
      'This is called by the User to Start the API Timer
      
      Const iTimerRepeatRateMILLISECONDS As Long = 1000   '1000 milliseconds = one second
      
      'Stop the Clock if it is running
      Call StopAPITimer
      
      'This starts a timer that will repeat until stopped
      lTimerIdAddress = SetTimer(0, 0, iTimerRepeatRateMILLISECONDS, AddressOf APITimerEventHandler)
      
    End Sub
    
    Sub SuspendAPITimer()
      'This stops the API Timer
      
      Dim track As Worksheet
      Set track = ThisWorkbook.Sheets("Tracker")
      
      If iGblActiveClientTimerCount = 0 Then
        bGblAPITimerSuspended = False
        MsgBox "NOTHING DONE.  There are NO Active Timers."
      ElseIf bGblAPITimerSuspended = True Then
        MsgBox "NOTHING DONE.  The API Timer is ALREADY Suspended."
      Else
        bGblAPITimerSuspended = True
        Call StopAPITimer
        Sleep 100
        track.Range(sApiTimerSuspendedCELL).Value = "API Timer is Suspended"
        Call ColorAllActiveTimersOnSheetTrack(sColorSUSPENDED)
      End If
      
      'Clear Object Pointers
      Set track = Nothing
      
    End Sub
    
    Sub SuspendAPITimerNoMessages()
      'This stops the API Timer with No Messages
      
      If iGblActiveClientTimerCount = 0 Then
        bGblAPITimerSuspended = False
      ElseIf bGblAPITimerSuspended = True Then
        'do nothing
      Else
        bGblAPITimerSuspended = True
        Call StopAPITimer
        Sleep 100
        On Error Resume Next     'START HERE
        If Err.Number <> 0 Then  'START HERE
          Debug.Print "SuspendAPITimerNoMessages()", Err.Number, Err.Description, Now()
        End If
        Call ColorAllActiveTimersOnSheetTrack(sColorSUSPENDED)
      End If
      
    End Sub
    
    
    Sub ResumeAPITimer()
      'This is called by the User to Start the API Timer
        
      If iGblActiveClientTimerCount = 0 Then
        bGblAPITimerSuspended = False
        MsgBox "NOTHING DONE.  There are NO Active Timers to Resume."
      ElseIf bGblAPITimerSuspended = True Then
        bGblAPITimerSuspended = False
        ThisWorkbook.Sheets("Tracker").Range(sApiTimerSuspendedCELL).Value = ""
        Call StartAPITimer
        Call ColorAllActiveTimersOnSheetTrack(sColorACTIVE)
      Else
        MsgBox "NOTHING DONE.  The API Timer is ALREADY Active."
      End If
      
    End Sub
    Sub ResumeAPITimerNoMessages()
      'This is called by the User to Start the API Timer with No Messages
      
      If iGblActiveClientTimerCount = 0 Then
        bGblAPITimerSuspended = False
        'MsgBox "NOTHING DONE.  There are NO Active Timers to Resume."
      ElseIf bGblAPITimerSuspended = True Then
        bGblAPITimerSuspended = False
        ThisWorkbook.Sheets("Tracker").Range(sApiTimerSuspendedCELL).Value = ""
        Call StartAPITimer
        Call ColorAllActiveTimersOnSheetTrack(sColorACTIVE)
      Else
        'MsgBox "NOTHING DONE.  The API Timer is ALREADY Active."
      End If
      
    End Sub
    
    Sub StopAllTimersAndUpdateAllTimerData()
      'This Stops all Timers and makes sure all data is properly updated
    
      Call StopTimer1
      Call StopTimer2
    
    End Sub
    
    Sub LogicallyStopAllTimers()
      'This is used to logically 'Stop All Timers' if only one Timer is allowed to Run at a time
      '
      'NOTE: If MORE THAN ONE time is allowed to run at a time comment out ALL the code below
      
    'Set the CONDITIONAL COMPILATION CONSTANT below to 'True'  to allow MULTIPLE SIMULTANEOUS TIMERS
    'Set the CONDITIONAL COMPILATION CONSTANT below to 'False' to allow only ONE TIMER to be running
    #Const ALLOW_MULTIPLE_SIMULTANEOUS_TIMERS = False
    #If ALLOW_MULTIPLE_SIMULTANEOUS_TIMERS = True Then
      ThisWorkbook.Sheets("Tracker").Range(sActiveTimerInfoCELL).Value = "MULTIPLE simultaneous Timers ARE ALLOWED"
    #Else
      Call StopAllTimersAndUpdateAllTimerData
      ThisWorkbook.Sheets("Tracker").Range(sActiveTimerInfoCELL).Value = "Only One Timer is Allowed to be Running"
    #End If
    
    End Sub
    
    
    Sub APITimerEventHandler()
      'This processes Timer Events
      
      Dim myCurrentDateAndTime As Date
      
      'Debug.Print "APITimerEventHandler()", Format(Now(), "hh:mm:ss."), Timer 'Output to Immediate Window (CTRL G in the Debugger)
      DoEvents
      
      'Get the Current Date and Time
      myCurrentDateAndTime = Now()
    
      'Process Timer1
      If bGblActiveClientTimer1 = True Then
        'DoEvents      'Yield to other processes
        On Error Resume Next 'START HERE
        ThisWorkbook.Sheets("Data_Tab").Range("V3").Calculate
        If Err.Number <> 0 Then
          Debug.Print "APITimerEventHandler() Timer1", Err.Number, Err.Description, Now()
        End If
      End If
    
      'Process Timer2
      If bGblActiveClientTimer2 = True Then
        'DoEvents      'Yield to other processes
        On Error Resume Next 'START HERE
        ThisWorkbook.Sheets("Data_Tab").Range("AA3").Calculate
        If Err.Number <> 0 Then
          Debug.Print "APITimerEventHandler() Timer2", Err.Number, Err.Description, Now()
        End If
      End If
          
    MYEXIT:
      'Resume Normal Error Processing
      On Error GoTo 0
      
    
    End Sub
    
    
    Sub AdjustValue()
      Dim track As Worksheet
      Dim data As Worksheet
        
      Dim btnName As String
      Dim targetCell As String
      Dim addAmount As Integer
        
      'Suspend the API Timer with No Messages
      Call SuspendAPITimerNoMessages
      
      Set data = ThisWorkbook.Sheets("Data_tab")
      Set track = ThisWorkbook.Sheets("Tracker")
      
      If track.Range("G2").Value = "" Then
        MsgBox ("Please Fill In Assignment Date in G2")
        GoTo MYEXIT
      Else
        btnName = Application.Caller
        targetCell = Mid(btnName, 5, Len(btnName))
        addAmount = IIf(Left(btnName, 3) = "ADD", 1, -1)
    
        data.Range(targetCell).Value = _
        data.Range(targetCell).Value + addAmount
      End If
        
    MYEXIT:
      'Resume the API Timer with No Messages
      Call ResumeAPITimerNoMessages
        
      'Clear Object pointers
      Set data = Nothing
      Set track = Nothing
    
    End Sub
    Additional remarks and suggestions:
    a. File with passwords take a lot of extra time to debug. Do not implement passwords until debugging is completed.
    b. To prevent typos from ruining days and weeks of work 'Option Explicit' is NEEDED at the top of each code module. This prevents errors caused by missspellings and FORCES every variable to be DECLARED (e.g. Dim i as Integer). https://www.excel-easy.com/vba/examp...-explicit.html

    Lewis

    Due to space limitations some code is continued in the next reply.
    Attached Files Attached Files

  8. #8
    Forum Expert
    Join Date
    01-23-2013
    Location
    USA
    MS-Off Ver
    Microsoft 365 aka Office 365
    Posts
    3,863

    Re: How to Keep Running Stopwatch running when using other sheets and other workbooks

    Additional code in the same code module as in the previous reply:
    Sub StartTimer1()
        
      Dim data As Worksheet
      Dim track As Worksheet
        
      Dim Start As Double
      Dim RunTime As Double
      Dim ElapsedTime As String
        
      'Create Worksheet Objects
      Set data = ThisWorkbook.Sheets("Data_tab")
      Set track = ThisWorkbook.Sheets("Tracker")
      
      'Logically STOP All Timers if ONLY one timer is allowed to run at a time
      'IF MORE THAN ONE is allowed to run a a timer see Sub LogicallyStopAllTimers() for instructions
      Call LogicallyStopAllTimers
      
      'Resume if the Timer is Suspended
      If bGblAPITimerSuspended = True And bGblActiveClientTimer1 = True Then
        Call ResumeAPITimer
        GoTo MYEXIT
      End If
    
    
      'Exit if the Timer is already Active
      If bGblActiveClientTimer1 = True Then
        GoTo MYEXIT
      End If
      
      'Prevents user from pushing button without first filling in Assigned Date
      If track.Range("G2").Value = "" Then
        MsgBox ("Please Fill In Assignment Date in G2")
        GoTo MYEXIT
      End If
      
      'Set the Flag to Indicate the Timer is Active
      'Increment the Count of Active Timers
      bGblActiveClientTimer1 = True
      iGblActiveClientTimerCount = iGblActiveClientTimerCount + 1
      
      'Color the Elapsed Time Cell as Active
      Call ChangeCellBackgroundColor(sColorACTIVE, sGblClientTimer1CELL)
      
      'Clear the Timer is Suspended Flag
      bGblAPITimerSuspended = False
      track.Range(sApiTimerSuspendedCELL).Value = ""
      
      'Put the Baseline Date and Time in the 1st Cell on Row 3 on the Data Tab
      'Create the Formula for the Next Cell on the Data Tab
      data.Range("U3").Value = Now()
      data.Range("V3").Formula = "=NOW() - Data_tab!U3"
    
      
      'If the Active Count is 1 (One) - Start the API Timer
      If iGblActiveClientTimerCount = 1 Then
        Call StartAPITimer
      End If
           
      'Display an Active Timer Count
      If iGblActiveClientTimerCount = 1 Then
        track.Range(sActiveTimerCountInfoCELL).Value = "There is 1 Active Timer"
      Else
        track.Range(sActiveTimerCountInfoCELL).Value = "There are " & iGblActiveClientTimerCount & " Active Timers"
      End If
      
    MYEXIT:
      'Clear Object pointers
      Set data = Nothing
      Set track = Nothing
    
    End Sub
     
    Sub StopTimer1()
        
      Dim data As Worksheet
      Dim track As Worksheet
        
      'Create Worksheet Objects
      Set data = ThisWorkbook.Sheets("Data_tab")
      Set track = ThisWorkbook.Sheets("Tracker")
      
      'Exit if the Timer is NOT Active
      If bGblActiveClientTimer1 = False Then
        GoTo MYEXIT
      End If
      
      'Prevents user from pushing button without first filling in Assigned Date
      If track.Range("G2").Value = "" Then
        MsgBox ("Please Fill In Assignment Date in G2")
        GoTo MYEXIT
      End If
      
      'Clear the Flag to Indicate the Timer is NOT Active
      'Decrement the Count of Active Timers
      bGblActiveClientTimer1 = False
      iGblActiveClientTimerCount = iGblActiveClientTimerCount - 1
         
      'Color the Elapsed Time Cell as Active
      Call ChangeCellBackgroundColor(sColorINACTIVE, sGblClientTimer1CELL)
      
      'If the Active Count is 0 (Zero) - Stop the API Timer
      If iGblActiveClientTimerCount = 0 Then
        Call StopAPITimer
      
        'Clear the Timer is Suspended Flag
        bGblAPITimerSuspended = False
        track.Range(sApiTimerSuspendedCELL).Value = ""
      
      End If
      
      'Change the Elapsed Time (2nd Column on Row 3) Since Start from a formula to a value
      'Add the Value at the Bottom of the 'Stop' Column
      'Clear the 1st Column on Row 3 (Baseline Date and Time)
      'Clear the 2nd Column on Row 3 (Elapsed Time)
      data.Range("V3").Value = data.Range("V3").Value
      data.Range("W10000").End(xlUp).Offset(1, 0).Value = data.Range("V3").Value
      data.Range("U3").Value = ""
      data.Range("V3").Value = 0
      
      'Display an Active Timer Count
      If iGblActiveClientTimerCount = 1 Then
        track.Range(sActiveTimerCountInfoCELL).Value = "There is 1 Active Timer"
      Else
        track.Range(sActiveTimerCountInfoCELL).Value = "There are " & iGblActiveClientTimerCount & " Active Timers"
      End If
        
    MYEXIT:
      'Clear Object pointers
      Set data = Nothing
      Set track = Nothing
    
    End Sub
    
    Sub StartTimer2()
        
      Dim data As Worksheet
      Dim track As Worksheet
        
      Dim Start As Double
      Dim RunTime As Double
      Dim ElapsedTime As String
        
      'Create Worksheet Objects
      Set data = ThisWorkbook.Sheets("Data_tab")
      Set track = ThisWorkbook.Sheets("Tracker")
      
      'Logically STOP All Timers if ONLY one timer is allowed to run at a time
      'IF MORE THAN ONE is allowed to run a a timer see Sub LogicallyStopAllTimers() for instructions
      Call LogicallyStopAllTimers
      
      'Resume if the Timer is Suspended
      If bGblAPITimerSuspended = True And bGblActiveClientTimer2 = True Then
        Call ResumeAPITimer
        GoTo MYEXIT
      End If
    
    
      'Exit if the Timer is already Active
      If bGblActiveClientTimer2 = True Then
        GoTo MYEXIT
      End If
      
      'Prevents user from pushing button without first filling in Assigned Date
      If track.Range("G2").Value = "" Then
        MsgBox ("Please Fill In Assignment Date in G2")
        GoTo MYEXIT
      End If
      
      'Set the Flag to Indicate the Timer is Active
      'Increment the Count of Active Timers
      bGblActiveClientTimer2 = True
      iGblActiveClientTimerCount = iGblActiveClientTimerCount + 1
      
      'Color the Elapsed Time Cell as Active
      Call ChangeCellBackgroundColor(sColorACTIVE, sGblClientTimer2CELL)
      
      'Clear the Timer is Suspended Flag
      bGblAPITimerSuspended = False
      track.Range(sApiTimerSuspendedCELL).Value = ""
      
      'Put the Baseline Date and Time in the 1st Cell on Row 3 on the Data Tab
      'Create the Formula for the Next Cell on the Data Tab
      data.Range("Z3").Value = Now()
      data.Range("AA3").Formula = "=NOW() - Data_tab!Z3"
    
      
      'If the Active Count is 1 (One) - Start the API Timer
      If iGblActiveClientTimerCount = 1 Then
        Call StartAPITimer
      End If
           
      'Display an Active Timer Count
      If iGblActiveClientTimerCount = 1 Then
        track.Range(sActiveTimerCountInfoCELL).Value = "There is 1 Active Timer"
      Else
        track.Range(sActiveTimerCountInfoCELL).Value = "There are " & iGblActiveClientTimerCount & " Active Timers"
      End If
      
    MYEXIT:
      'Clear Object pointers
      Set data = Nothing
      Set track = Nothing
    
    End Sub
     
    Sub StopTimer2()
        
      Dim data As Worksheet
      Dim track As Worksheet
        
      'Create Worksheet Objects
      Set data = ThisWorkbook.Sheets("Data_tab")
      Set track = ThisWorkbook.Sheets("Tracker")
      
      'Exit if the Timer is NOT Active
      If bGblActiveClientTimer2 = False Then
        GoTo MYEXIT
      End If
      
      'Prevents user from pushing button without first filling in Assigned Date
      If track.Range("G2").Value = "" Then
        MsgBox ("Please Fill In Assignment Date in G2")
        GoTo MYEXIT
      End If
      
      'Clear the Flag to Indicate the Timer is NOT Active
      'Decrement the Count of Active Timers
      bGblActiveClientTimer2 = False
      iGblActiveClientTimerCount = iGblActiveClientTimerCount - 1
         
      'Color the Elapsed Time Cell as Active
      Call ChangeCellBackgroundColor(sColorINACTIVE, sGblClientTimer2CELL)
      
      'If the Active Count is 0 (Zero) - Stop the API Timer
      If iGblActiveClientTimerCount = 0 Then
        Call StopAPITimer
      
        'Clear the Timer is Suspended Flag
        bGblAPITimerSuspended = False
        track.Range(sApiTimerSuspendedCELL).Value = ""
      
      End If
      
      'Change the Elapsed Time (2nd Column on Row 3) Since Start from a formula to a value
      'Add the Value at the Bottom of the 'Stop' Column
      'Clear the 1st Column on Row 3 (Baseline Date and Time)
      'Clear the 2nd Column on Row 3 (Elapsed Time)
      data.Range("AA3").Value = data.Range("AA3").Value
      data.Range("AB10000").End(xlUp).Offset(1, 0).Value = data.Range("AA3").Value
      data.Range("Z3").Value = ""
      data.Range("AA3").Value = 0
      
      'Display an Active Timer Count
      If iGblActiveClientTimerCount = 1 Then
        track.Range(sActiveTimerCountInfoCELL).Value = "There is 1 Active Timer"
      Else
        track.Range(sActiveTimerCountInfoCELL).Value = "There are " & iGblActiveClientTimerCount & " Active Timers"
      End If
      
    MYEXIT:
      'Clear Object pointers
      Set data = Nothing
      Set track = Nothing
    
    End Sub
    Lewis

+ Reply to Thread

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. Create running stopwatch/timer with 1 button (start/stop). No reset button.
    By leeroy2612 in forum Excel Programming / VBA / Macros
    Replies: 6
    Last Post: 05-26-2021, 12:59 AM
  2. 30 Day Running or Rolling total (Multiple Sheets/Workbooks)
    By MuayThaiChick in forum Excel General
    Replies: 3
    Last Post: 02-18-2017, 05:31 PM
  3. code works running in visual basic editor but not when running from Excel macro
    By smporco in forum Excel Programming / VBA / Macros
    Replies: 4
    Last Post: 11-06-2016, 05:44 PM
  4. Cannot open other files while running stopwatch macro
    By isabela1214 in forum Hello..Introduce yourself
    Replies: 8
    Last Post: 09-03-2015, 12:00 AM
  5. Cannot Open New Spreadsheets While Stopwatch Macro is Running
    By isabela1214 in forum Excel Programming / VBA / Macros
    Replies: 3
    Last Post: 07-27-2015, 03:45 PM
  6. Running stopwatch in background while working on other workbooks
    By Heidi K. in forum Excel Programming / VBA / Macros
    Replies: 1
    Last Post: 04-15-2014, 06:14 AM
  7. Error 424 when running stopwatch
    By marreco in forum Excel Programming / VBA / Macros
    Replies: 3
    Last Post: 10-14-2012, 09:24 AM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts

Search Engine Friendly URLs by vBSEO 3.6.0 RC 1