Мне нужен был видимый таймер обратного отсчета, который мог бы оставаться поверх других окон и работать без проблем, независимо от того, вносились ли изменения в рабочую книгу или минимизировалось ли окно Excel. Итак, я адаптировал креативный код @ don-kirkby выше для своих собственных целей и решил поделиться результатом.
Приведенный ниже код требует создания модуля и пользовательской формы, как указано в комментариях, или вы можете загрузить .xlsm
внизу этого ответа.
Я использовал Windows Timer API для более точного и плавного обратного отсчета (а также настраиваемого до ~ 100 миллисекунд разрешения таймера , в зависимости от вашего процессора. Есть даже «тик-ток» " звук . ⏰
Вставьте новый модуль и сохраните его как modUserFormTimer
. Добавьте две кнопки управления формой к рабочему листу, помеченные Таймер запуска и Таймер остановки и , назначенные процедуры btnStartTimer_Click
и btnStopTimer_Click
,
Option Explicit 'modUserFormTimer
Public Const showTimerForm = True 'timer runs with/without the userform showing
Public Const playTickSound = True 'tick tock (a WAV sounds could be embedded: `https:// goo.gl/ ReuUyd`)
Public Const timerDuration = "00:00:20" 'could also Insert>Object a WAV for tick or alarm
Public Const onTimerStart_MinimizeExcel = True 'minimize Excel? (countdown remains visible)
Public Const onTimerStart_MaximizeExcel = True 'maximize Excel when timer completes?
'timer could be on top of other applications; instructions here: `https:// goo.gl/ AgmWrM`
'safe for 32 or 64 bit Office:
Private Declare PtrSafe Function SetTimer Lib "User32" (ByVal hWnd As Long, ByVal nIDEvent As Long, _
ByVal uElapse As Long, ByVal lpTimerFunc As LongPtr) As Long
Private Declare PtrSafe Function KillTimer Lib "User32" (ByVal hWnd As Long, ByVal nIDEvent As Long) As Long
Public Declare PtrSafe Function Beep Lib "kernel32" (ByVal dwFreq As Long, ByVal dwDuration As Long) As Long
Public schedTime As Date 'this is the "major" timer set date
Private m_TimerID As Long
Public Sub OnTimerTask()
'the procedure that runs on completion of the "major timer" (timer won't reschedule)
Unload frmTimer
''''''''''''''''''''''''''''''
MsgBox "Do Something!" ' < < < < < Do Something Here
''''''''''''''''''''''''''''''
End Sub
Public Sub btnStartTimer_Click()
schedTime = Now() + TimeValue(timerDuration)
InitTimerForm
End Sub
Public Sub btnStopTimer_Click()
'clicking the 'x' on the userform also ends the timer (disable the close button to force continue)
schedTime = 0
frmTimer.UserForm_Terminate
End Sub
Public Sub InitTimerForm()
'run this procedure to start the timer
frmTimer.OnTimer
Load frmTimer
If showTimerForm Then
If onTimerStart_MinimizeExcel Then Application.WindowState = xlMinimized
frmTimer.Show 'timer will still work if userform is hidden (could add a "hide form" option)
End If
End Sub
Public Sub StartTimer(ByVal Duration As Long)
'Begin Millisecond Timer using Windows API (called by UserForm)
If m_TimerID = 0 Then
If Duration > 0 Then
m_TimerID = SetTimer(0, 0, Duration, AddressOf TimerEvent)
If m_TimerID = 0 Then
MsgBox "Timer initialization failed!", vbCritical, "Timer"
End If
Else
MsgBox "The duration must be greater than zero.", vbCritical, "Timer"
End If
Else
MsgBox "Timer already started.", vbInformation, "Timer"
End If
End Sub
Public Sub StopTimer()
If m_TimerID <> 0 Then 'check if timer is active
KillTimer 0, m_TimerID 'it's active, so kill it
m_TimerID = 0
End If
End Sub
Private Sub TimerEvent()
'the API calls this procedure
frmTimer.OnTimer
End Sub
Затем создайте форму пользователя, сохраните ее как frmTimer
. Добавьте текстовое поле с именем txtCountdown
. Установите для свойства ShowModal
значение False
. Вставьте следующее в окно кода формы:
Option Explicit 'code for userform "frmTimer"
'requires a textbox named "txtCountdown" and "ShowModal" set to False.
Dim nextTriggerTime As Date
Private Sub UserForm_Initialize()
ScheduleNextTrigger
End Sub
Public Sub UserForm_Terminate()
StopTimer
If schedTime > 0 Then
schedTime = 0
End If
If onTimerStart_MaximizeExcel Then Application.WindowState = xlMaximized 'maximize excel window
Unload Me
End Sub
Private Sub ScheduleNextTrigger() 'sets the "minor" timer (for the countdown)
StartTimer (1000) 'one second
End Sub
Public Sub OnTimer()
'either update the countdown, or fire the "major" timer task
Dim secLeft As Long
If Now >= schedTime Then
OnTimerTask 'run "major" timer task
Unload Me 'close userForm (won't schedule)
Else
secLeft = CLng((schedTime - Now) * 60 * 60 * 24)
If secLeft < 60 Then 'under 1 minute (don't show mm:ss)
txtCountdown = secLeft & " sec"
Else
'update time remaining in textbox on userform
If secLeft > 60 * 60 Then
txtCountdown = Format(secLeft / 60 / 60 / 24, "hh:mm:ss")
Else 'between 59 and 1 minutes remain:
txtCountdown = Right(Format(secLeft / 60 / 60 / 24, "hh:mm:ss"), 5)
End If
End If
If playTickSound Then Beep 16000, 65 'tick sound
End If
End Sub
Загрузите демоверсию .xksm.
здесь . Есть множество способов, которые могут быть настроены или адаптированы к конкретным потребностям. Я собираюсь использовать его для расчета и отображения статистики в реальном времени с популярного сайта вопросов и ответов в углу моего экрана ...
Обратите внимание , что, поскольку он содержит макросы VBA, файл может отключить ваш антивирусный сканер (как и любой другой нелокальный файл с VBA). Если вы обеспокоены, не загружайте, а вместо этого соберите его самостоятельно с предоставленной информацией.)