如何使VBA宏在后台连续运行?
我想监控一个值,并在满足某些条件时收到电子邮件通知。我有这样一个宏:如何使VBA宏在后台连续运行?,vba,excel,Vba,Excel,我想监控一个值,并在满足某些条件时收到电子邮件通知。我有这样一个宏: Do While True Worksheet.Calculate If Value > 10 Then SendEmail End If Sleep 60*CLng(1000) Loop 但是,当我运行这个程序时,它会阻塞整个程序,如果我尝试执行任何操作,它将变得无响应 有没有办法做到这一点,但让它在后台运行,或者至少不会使程序崩溃 我之前所做的是使用VBScr
Do While True
Worksheet.Calculate
If Value > 10 Then
SendEmail
End If
Sleep 60*CLng(1000)
Loop
但是,当我运行这个程序时,它会阻塞整个程序,如果我尝试执行任何操作,它将变得无响应
有没有办法做到这一点,但让它在后台运行,或者至少不会使程序崩溃
我之前所做的是使用VBScript打开一个不可见的电子表格,VBScript在后台连续运行,监控情况,工作正常,但我的客户确实希望有一个GUI,并将其放在程序中
有什么想法吗?我认为您需要通过调用专门处理应用程序事件堆栈。这允许用户与电子表格进行交互,通常宏优先。您的代码看起来像:
Do While True
If Value > 10 Then
SendEmail
End If
Sleep 60*CLng(1000)
DoEvents
Loop
如果您想继续使用VBScript,还可以使用HTA构建GUI。使用
Application.OnTime
方法调度将在一分钟内运行的代码
您的代码将如下所示(未经测试):
您可能希望将下一个计划的时间存储在全局变量中,以便工作簿\u BeforeClose
事件可以取消下一个计划。否则Excel将重新打开工作簿
Public nextScheduledTime As Date
Sub CreateNewSchedule()
nextScheduledTime = DateAdd("n", 1, Now)
Application.OnTime EarliestTime:=nextScheduledTime , Procedure:="macro_name", Schedule:=True
End Sub
Sub macro_name()
If Value > 10 Then
SendEmail
Else
CreateNewSchedule
End If
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
On Error Resume Next
Application.OnTime EarliestTime:=nextScheduledTime, Procedure:="macro_name", Schedule:=False
End Sub
然后,您可以在计划时间之间继续使用Excel。如果您需要监视单元格的值,则不需要连续运行代码,而是使用工作表的更改事件。@MátéJuhász我认为该值不会自行更改。需要提示它。我将更新示例代码。我仍然可以使用工作表的更改事件吗?请看这里:,它可能对您有用。另一种方法是设置一个宏,以便在电子表格更改时运行。是的,老实说,这是一个更好的解决方案,因为我认为,由于sleep命令,您仍然会在这里得到一些应用程序锁定。我建议你把它贴出来作为这个问题的答案——我会投赞成票:-)。唯一的问题是,如果没有用户交互,但是需要发送邮件。在这种情况下,如果sleep命令实际上没有计时,您可以将其减少到33毫秒或一些不可注意的时间。@HolmesIV,请参阅上面评论中的我的回答。谢谢。您的
CreateNewSchedule
函数工作正常。我不知道那个功能
Public nextScheduledTime As Date
Sub CreateNewSchedule()
nextScheduledTime = DateAdd("n", 1, Now)
Application.OnTime EarliestTime:=nextScheduledTime , Procedure:="macro_name", Schedule:=True
End Sub
Sub macro_name()
If Value > 10 Then
SendEmail
Else
CreateNewSchedule
End If
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
On Error Resume Next
Application.OnTime EarliestTime:=nextScheduledTime, Procedure:="macro_name", Schedule:=False
End Sub