VBA : 当宏为 运行 时禁用列表框
VBA : Disabling Listbox while macro is running
问题
我有一个宏(我称之为 launch_macro
),它是通过双击用户窗体列表框 (ListBox1_DblClick
) 启动的。
我的问题是,如果用户在宏仍然 运行 时再次双击,宏将在第一次执行完成后立即再次启动,而不管我是在宏为 运行.
时禁用 ListBox
代码和测试
Private sub ListBox1_DblClick(Byval Cancel as MSForms.ReturnBoolean)
(....Logging...)
If Not Cancel Then
Me.ListBox1.Enabled = False
(...DisplayStatusBar / ScreenUpdating / ListBox1.BackColor...)
launch_macro
(...DisplayStatusBar / ScreenUpdating / ListBox1.BackColor...)
Me.ListBox1.Enabled = True
End If
End sub
似乎 Excel records/queues ListBox1_DblClick 事件(用于将来执行),而关联的 ListBox 是禁用。为什么 ?我该如何防止这种情况?
我也试过没有成功:
- 锁定 :
Me.ListBox1.Locked = True
- Doevents : 在
Me.ListBox1.Enabled = False
之后添加 DoEvents
- 启用事件 :
Application.EnableEvents = False
- macroLaunched 变量 :使用变量检查宏是否已经启动(
macroLaunched = True
在 ListBox1_DblClick
事件的开始和 macroLaunched = False
最后)。这不起作用,因为第二次执行是在第一个事件结束 之后 启动的(因此变量被设置回 False
)。 (并且在 Dbl_Click 事件范围之外将变量设置回 False 是不可接受的,因为用户需要能够立即再次启动宏(但不是在第一次执行仍在 运行 )).
- 添加延迟(仅用于测试目的):我在 launch_macro 之后添加了 10 秒的延迟 (Application.Wait)。然后我在 1 秒内双击了两次。第二次执行仍然启动。我通过日志检查:第二个 ListBox1.Dbl_Click 事件是 'recorded' 第一个事件后 Excel 12 秒。
注意 : 我使用的是 Office 标准版 2013
当前 'solution'
这个技巧改编自A.S.H答案(以减少延迟):
Private sub ListBox1_DblClick(Byval Cancel as MSForms.ReturnBoolean)
Static nextTime As Single
If Timer < nextTime then
Log_macro "Event canceled because Timer < nextTime : " & Timer
Exit Sub
End if
(....Logging...)
If Not Cancel Then
(...DisplayStatusBar / ScreenUpdating / ListBox1.BackColor...)
launch_macro
(...DisplayStatusBar / ScreenUpdating / ListBox1.BackColor...)
End If
nextTime = Timer + 0.5
Log_macro "nextTime = " & nextTime
End sub
它 'does the trick' 但我仍然不喜欢 ListBox1 仍然启用并且 Excel 仍在排队事件,因此我需要估计用户可能 Dbl_Click (取决于宏需要多长时间)来估计我需要多少延迟(目前 0.5s 能够处理(和记录)至少 10 个取消的事件)。此外,当宏为 运行.
时,Excel 似乎不太喜欢(在性能方面)排队事件
好吧,我会post我的建议,我希望你试一试,因为它可能被误解了。这个想法是,一旦宏完成,我们在再次处理双击事件之前设置 n 秒(比如 2 秒)的延迟。这样,在宏执行期间排队的 dbl-clicks 将在这两秒内被处理而不会产生任何影响。
Private Sub ListBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Static NextTime As Variant ' Will set a barrier for launching again the macro
If Not IsEmpty(NextTime) Then If Now < NextTime Then Exit Sub
ListBox1.Enabled = False
' Any event code
launch_macro
' ...
ListBox1.Enabled = True
NextTime = Now + TimeSerial(0, 0, 2) ' dbl-click events will have no effects during next 2 seconds
End Sub
您可以使用变量将代码的关键部分锁定一段时间。
下面的示例锁定了 Excel 工作簿的 Sheet2 中 Test() 函数的关键部分。
Option Explicit
Private booIsRunning As Boolean
Private Sub Test()
If Not booIsRunning Then
booIsRunning = True
Debug.Print "Hello."
Application.OnTime Now + TimeValue("00:00:02"), "Sheet2.UnlockTest"
End If
End Sub
Public Sub UnlockTest()
booIsRunning = False
End Sub
问题
我有一个宏(我称之为 launch_macro
),它是通过双击用户窗体列表框 (ListBox1_DblClick
) 启动的。
我的问题是,如果用户在宏仍然 运行 时再次双击,宏将在第一次执行完成后立即再次启动,而不管我是在宏为 运行.
时禁用 ListBox代码和测试
Private sub ListBox1_DblClick(Byval Cancel as MSForms.ReturnBoolean)
(....Logging...)
If Not Cancel Then
Me.ListBox1.Enabled = False
(...DisplayStatusBar / ScreenUpdating / ListBox1.BackColor...)
launch_macro
(...DisplayStatusBar / ScreenUpdating / ListBox1.BackColor...)
Me.ListBox1.Enabled = True
End If
End sub
似乎 Excel records/queues ListBox1_DblClick 事件(用于将来执行),而关联的 ListBox 是禁用。为什么 ?我该如何防止这种情况?
我也试过没有成功:
- 锁定 :
Me.ListBox1.Locked = True
- Doevents : 在
Me.ListBox1.Enabled = False
之后添加 - 启用事件 :
Application.EnableEvents = False
- macroLaunched 变量 :使用变量检查宏是否已经启动(
macroLaunched = True
在ListBox1_DblClick
事件的开始和macroLaunched = False
最后)。这不起作用,因为第二次执行是在第一个事件结束 之后 启动的(因此变量被设置回False
)。 (并且在 Dbl_Click 事件范围之外将变量设置回 False 是不可接受的,因为用户需要能够立即再次启动宏(但不是在第一次执行仍在 运行 )). - 添加延迟(仅用于测试目的):我在 launch_macro 之后添加了 10 秒的延迟 (Application.Wait)。然后我在 1 秒内双击了两次。第二次执行仍然启动。我通过日志检查:第二个 ListBox1.Dbl_Click 事件是 'recorded' 第一个事件后 Excel 12 秒。
DoEvents
注意 : 我使用的是 Office 标准版 2013
当前 'solution'
这个技巧改编自A.S.H答案(以减少延迟):
Private sub ListBox1_DblClick(Byval Cancel as MSForms.ReturnBoolean)
Static nextTime As Single
If Timer < nextTime then
Log_macro "Event canceled because Timer < nextTime : " & Timer
Exit Sub
End if
(....Logging...)
If Not Cancel Then
(...DisplayStatusBar / ScreenUpdating / ListBox1.BackColor...)
launch_macro
(...DisplayStatusBar / ScreenUpdating / ListBox1.BackColor...)
End If
nextTime = Timer + 0.5
Log_macro "nextTime = " & nextTime
End sub
它 'does the trick' 但我仍然不喜欢 ListBox1 仍然启用并且 Excel 仍在排队事件,因此我需要估计用户可能 Dbl_Click (取决于宏需要多长时间)来估计我需要多少延迟(目前 0.5s 能够处理(和记录)至少 10 个取消的事件)。此外,当宏为 运行.
时,Excel 似乎不太喜欢(在性能方面)排队事件好吧,我会post我的建议,我希望你试一试,因为它可能被误解了。这个想法是,一旦宏完成,我们在再次处理双击事件之前设置 n 秒(比如 2 秒)的延迟。这样,在宏执行期间排队的 dbl-clicks 将在这两秒内被处理而不会产生任何影响。
Private Sub ListBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Static NextTime As Variant ' Will set a barrier for launching again the macro
If Not IsEmpty(NextTime) Then If Now < NextTime Then Exit Sub
ListBox1.Enabled = False
' Any event code
launch_macro
' ...
ListBox1.Enabled = True
NextTime = Now + TimeSerial(0, 0, 2) ' dbl-click events will have no effects during next 2 seconds
End Sub
您可以使用变量将代码的关键部分锁定一段时间。 下面的示例锁定了 Excel 工作簿的 Sheet2 中 Test() 函数的关键部分。
Option Explicit
Private booIsRunning As Boolean
Private Sub Test()
If Not booIsRunning Then
booIsRunning = True
Debug.Print "Hello."
Application.OnTime Now + TimeValue("00:00:02"), "Sheet2.UnlockTest"
End If
End Sub
Public Sub UnlockTest()
booIsRunning = False
End Sub