Независимые макросы таймера в таблицах Excel - PullRequest
3 голосов
/ 28 июня 2019

Таким образом, я использовал простой макрос таймера, который я нашел в Интернете, который в основном использует кнопки запуска и остановки, чтобы отслеживать время. Однако я хочу использовать таймеры, чтобы они работали независимо на каждом листе. Поэтому, если у меня есть 2 листа, если я запускаю таймер на одном листе, он продолжает работать на этом листе, и я могу переключиться на второй лист и запустить таймер на этом листе отдельно. В настоящее время работает макрос так, что запуск таймера на одном листе сохраняет время работы на обоих листах и ​​останавливается, если на любом листе нажата любая из кнопок остановки. Вот что у меня сейчас:

Sub StartTimer()
Dim Start As Single, RunTime As Single
Dim ElapsedTime As String
Dim counter As Long

'Set the control cell to 0 and make it green
Range("C1").Value = 0
Range("A1").Interior.Color = 5296274  'Green

counter = 0
Start = Timer 'Set start time.
Debug.Print Start
Do While Range("C1").Value = 0

    DoEvents 'Yield to other processes.
    RunTime = Timer 'Current elapsed time
    ElapsedTime = Format((RunTime - Start) / 86400, "hh:mm:ss")
    'Display currently elapsed time in A1
    Range("A1").Value = ElapsedTime
    Application.StatusBar = ElapsedTime

Loop

Range("A1").Value = ElapsedTime
Range("A1").Interior.Color = 192 'Dark red
Application.StatusBar = False

End Sub

Sub StopTimer()

    'Set the control cell to 1
    Range("C1").Value = 1

End Sub

Sub ResetTimer()
    If Range("C1").Value > 0 Then

    'Set the control cell to 1
    Range("A1").Value = Format(0, "hh:mm:ss")

    End If

End Sub

Ответы [ 2 ]

2 голосов
/ 28 июня 2019

Вы можете сделать это, отслеживая, какие рабочие листы имеют таймеры выполнения. Я использовал Dictionary с ранним связыванием , поэтому вам придется добавить ссылку на библиотеку, чтобы использовать приведенный ниже пример кода.

Идея состоит в том, что у вас есть "список", из которых рабочие листы в вашей рабочей книге имеют активные таймеры. В терминах Dictionary это означает, что если на листе есть таймер, то в Dictionary есть запись. Чтобы настроить это в своем собственном модуле, я определил следующие глобальные константы и переменную:

Private Const FIXED_CELL As String = "C20"
Private Const STATUS_CELL As String = "D20"
Private Const UPDATE_INTERVAL As String = "00:00:01"
Private sheetTimers As Dictionary

Словарь sheetTimers будет использоваться всеми подпрограммами в модуле. Константы - хорошая идея, потому что она дает вам одно место для внесения изменений.

Настройка в вашей рабочей книге заключается в создании кнопок «Пуск» и «Стоп» на нескольких рабочих листах, а также нескольких ячеек для отображения прошедшего времени. Каждой кнопке присваивается соответствующий Public Sub.

enter image description here

В каждом из подпрограмм имеется код, который помогает отслеживать таймеры и управлять настройкой следующего события UpdateAllTimers для обновления истекшего времени. При необходимости вы можете изменить пример кода, чтобы добавить цвет ячейки и другие функции.

Option Explicit

Private Const ELAPSED_CELL As String = "C5"
Private Const STATUS_CELL As String = "D5"
Private Const UPDATE_INTERVAL As String = "00:00:01"
Private sheetTimers As Dictionary
Private timerIsActive As Boolean

Public Sub UpdateAllTimers()
    If sheetTimers Is Nothing Then
        timerIsActive = False
    Else
        'Debug.Print sheetTimers.Count & " timers are running"
        If sheetTimers.Count > 0 Then
            Dim sheetName As Variant
            For Each sheetName In sheetTimers.Keys
                UpdateElapsedTime sheetName, sheetTimers(sheetName), Now()
            Next sheetName
            Application.OnTime Now() + TimeValue(UPDATE_INTERVAL), "UpdateAllTimers"
            timerIsActive = True
        Else
            timerIsActive = False
        End If
    End If
End Sub

Sub StartTimer()
    '--- first time initialization ONLY
    If sheetTimers Is Nothing Then Set sheetTimers = New Dictionary

    '--- find or create the entry for the ACTIVE worksheet
    Dim thisSheet As Worksheet
    Dim thisSheetName As String
    Set thisSheet = ActiveSheet
    thisSheetName = thisSheet.Name
    If sheetTimers.Exists(thisSheetName) Then
        ResetTimer
    Else
        sheetTimers.Add thisSheetName, Now()
        thisSheet.Range(ELAPSED_CELL).value = TimeValue("00:00:00")
        thisSheet.Range(STATUS_CELL).value = "Running"
    End If

    If Not timerIsActive Then
        Application.OnTime Now() + TimeValue(UPDATE_INTERVAL), "UpdateAllTimers"
    End If
End Sub

Sub StopTimer()
    If sheetTimers Is Nothing Then
        timerIsActive = False
    Else
        '--- update the elapsed time value one last time and delete the
        '    entry in the dictionary
        Dim thisSheet As Worksheet
        Set thisSheet = ActiveSheet

        Dim thisSheetName As String
        thisSheetName = thisSheet.Name
        If sheetTimers.Exists(thisSheetName) Then
            UpdateElapsedTime thisSheetName, sheetTimers(thisSheetName), Now()
            sheetTimers.Remove thisSheetName
            thisSheet.Range(STATUS_CELL).value = "Stopped"
        Else
            '--- do nothing, this sheet's timer was never started
        End If
    End If
End Sub

Private Sub UpdateElapsedTime(ByVal sheetName As String, _
                              ByVal startTime As Date, _
                              ByVal endTime As Date)
    Dim elapsedTime As Range
    Set elapsedTime = ThisWorkbook.Sheets(sheetName).Range(ELAPSED_CELL)
    elapsedTime.NumberFormat = "hh:mm:ss.0"    'optional
    elapsedTime.value = endTime - startTime
End Sub

Sub ResetTimer()
    '--- update the start time value on for the active worksheet
    '    entry in the dictionary
    Dim thisSheet As Worksheet
    Set thisSheet = ActiveSheet

    Dim thisSheetName As String
    thisSheetName = thisSheet.Name
    If sheetTimers.Exists(thisSheetName) Then
        sheetTimers(thisSheetName) = Now()
        UpdateElapsedTime thisSheetName, sheetTimers(thisSheetName), Now()
        sheetTimers.Remove thisSheetName
    Else
        '--- do nothing, this sheet's timer was never started
    End If
End Sub
1 голос
/ 28 июня 2019

Самый простой способ - создать новый «модуль класса».Затем вы можете создавать объекты для каждого листа.Вот хорошее объяснение модулей класса .

Таким образом, у вас будет такой код в обычном модуле:

'vba
Public Timer1 As New TimerClass
Sub StartTimer1
Call Timer1.StartTimer(ThisWorkbook.Sheets(1))
End Sub

Затем скопируйте весь свой код таймера вмодуль класса.Измените имя этого на «TimerClass».В модуле класса измените «Sub» на «Public Sub».(Это так, что ваш модуль класса может быть вызван другим модулем.)

Вы захотите указать, какой лист будут использовать объекты.Хороший способ сделать это - включить параметр для вашего кода.Я также удалил функциональность строки состояния, потому что в противном случае строка состояния будет меняться несколькими объектами, и это не будет соответствовать цели.Вы можете добавить его обратно, если хотите.Таким образом, ваш обновленный код в модуле класса с именем «TimerClass» будет выглядеть примерно так:

Public Sub StartTimer(Sht As Worksheet)
Dim Start As Single, RunTime As Single
Dim ElapsedTime As String
Dim counter As Long

'Set the control cell to 0 and make it green
Sht.Range("C1").Value = 0
Sht.Range("A1").Interior.Color = 5296274  'Green

counter = 0
Start = Timer 'Set start time.
Debug.Print Start
Do While Sht.Range("C1").Value = 0

    DoEvents 'Yield to other processes.
    RunTime = Timer 'Current elapsed time
    ElapsedTime = Format((RunTime - Start) / 86400, "hh:mm:ss")
    'Display currently elapsed time in A1
    Sht.Range("A1").Value = ElapsedTime

Loop

Sht.Range("A1").Value = ElapsedTime
Sht.Range("A1").Interior.Color = 192 'Dark red

End Sub

Public Sub StopTimer(Sht As Worksheet)

    'Set the control cell to 1
    Sht.Range("C1").Value = 1

End Sub

Public Sub ResetTimer(Sht As Worksheet)
    If Sht.Range("C1").Value > 0 Then

    'Set the control cell to 1
    Sht.Range("A1").Value = Format(0, "hh:mm:ss")

    End If

End Sub
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...