如何让多个无模式 VBA 表单在 Excel 上同时运行?
当工作簿长时间处于非活动状态时,我有一个使用 UserForm.Show(False) 弹出的无模式表单。表单有一个超时计数器,如果在计数器达到零之前它没有被用户中断(用户表单卸载),那么工作簿就会关闭。在 UserForm_Activate 中有一个 Do While - 带有 DoEvents 的循环以显示表单中的剩余时间。
这适用于单个打开的工作簿。但是,如果我复制 xlsm 文件并打开它们,那么在指定的空闲时间之后,两个工作簿都会打开它们的超时表单,但只有最后一个的计数器会运行。打开第二个表格后,第一个表格的计数器将停止。
有什么方法可以让两种无模式表单都运行?
表 1
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
LastEdit = Int(Timer)
End Sub
本工作簿
Option Explicit
Private Sub Workbook_BeforeClose(Cancel As Boolean)
On Error Resume Next
Application.OnTime EarliestTime:=NextCheck, Procedure:="TimeOut", Schedule:=False
End Sub
Private Sub Workbook_Open()
NextCheck = DateAdd("s", CheckInterval, Now)
Application.OnTime EarliestTime:=NextCheck, Procedure:="TimeOut", Schedule:=True
Debug.Print "NextCheck for " & ThisWorkbook.Name & " - " & NextCheck
LastEdit = Int(Timer)
End Sub
用户窗体1
Option Explicit
Private Start As Single
Private CountDownActive As Boolean
Private Sub cmdContinue_Click()
On Error Resume Next
Application.OnTime EarliestTime:=NextCheck, Procedure:="TimeOut", Schedule:=False
LastEdit = Int(Timer)
CountDownActive = False
Unload Me
End Sub
Private Sub UserForm_Activate()
Debug.Print ThisWorkbook.Name & " - CountDownActive: " & CountDownActive
If Not CountDownActive Then StartCountDown
End Sub
Private Sub UserForm_Terminate()
On Error Resume Next
Application.OnTime EarliestTime:=NextCheck, Procedure:="TimeOut", Schedule:=False
LastEdit = Int(Timer)
NextCheck = DateAdd("s", CheckInterval, Now)
Application.OnTime EarliestTime:=NextCheck, Procedure:="TimeOut", Schedule:=True
Debug.Print "NextCheck for " & ThisWorkbook.Name & " - " & NextCheck
End Sub
Private Sub StartCountDown()
CountDownActive = True
Start = Timer
Do While Timer - Start < CountDownTime And Timer - LastEdit > TotalIdleTime - CountDownTime
Me.Caption = Format(TimeSerial(0, 0, CountDownTime - Timer + Start), "nn:ss") & " remaining until closing '" & ThisWorkbook.Name & "'..."
DoEvents
Loop
If Timer - LastEdit > TotalIdleTime - CountDownTime Then
Application.DisplayAlerts = False
ThisWorkbook.Close False
Application.DisplayAlerts = True
End If
CountDownActive = False
Unload Me
End Sub
模块1
Option Explicit
Public LastEdit As Single
Public NextCheck As Date
Public Const CheckInterval = 60 ' "00:01:00"
Public Const TotalIdleTime = 180 ' "00:03:00"
Public Const CountDownTime = 120 ' "00:02:00"
Private Function TimeOut()
On Error Resume Next
Dim IdleTimerForm As Object
Select Case Timer - LastEdit
Case Is < TotalIdleTime - CountDownTime
Application.OnTime EarliestTime:=NextCheck, Procedure:="TimeOut", Schedule:=False
NextCheck = DateAdd("s", CheckInterval, Now)
Application.OnTime EarliestTime:=NextCheck, Procedure:="TimeOut", Schedule:=True
Debug.Print "NextCheck for " & ThisWorkbook.Name & " - " & NextCheck
Case Else
Application.OnTime EarliestTime:=NextCheck, Procedure:="TimeOut", Schedule:=False
Call AppActivate(Application.Caption)
ThisWorkbook.Activate
Set IdleTimerForm = New UserForm1
IdleTimerForm.Show vbModeless
End Select
End Function
还有一个问题是,当用户表单计数器之一达到零并卸载表单时,它将从每个当前打开的工作簿中卸载该用户表单的所有实例。