如何让 VBA 宏在后台连续运行?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31210921/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 09:43:55  来源:igfitidea点击:

How to get VBA Macro to run continuously in the background?

vbaexcel-vbaexcel

提问by Charles Clayton

I want to monitor a value and get an email notifications when certain conditions are met. I have a macro like so:

我想监视一个值并在满足某些条件时收到电子邮件通知。我有一个像这样的宏:

Do While True

    Worksheet.Calculate

    If Value > 10 Then
        SendEmail
    End If

    Sleep 60*CLng(1000)

Loop

However, when I run this, it clogs up the entire program and will turn unresponsive if I try to do anything.

但是,当我运行它时,它会阻塞整个程序并且如果我尝试做任何事情都会变得无响应。

Is there anyway to accomplish this but have it run in the background or at least not crash the program?

有没有办法做到这一点,但让它在后台运行或至少不会使程序崩溃?

What I was doing before was using VBScript to open a not-visible spreadsheet and the VBScript ran continuously in the background monitoring the condition and worked fine, but my client really wants a GUI and for it to be in the program itself.

我之前所做的是使用 VBScript 打开一个不可见的电子表格,VBScript 在后台持续运行,监控情况并且工作正常,但我的客户确实想要一个 GUI 并且它在程序本身中。

Any thoughts?

有什么想法吗?

回答by ChipsLetten

Use the Application.OnTimemethod to schedule code that will run in one minute.

使用该Application.OnTime方法来安排将在一分钟内运行的代码。

Your code will look something like this (Untested):

您的代码将如下所示(未经测试):

Sub CreateNewSchedule()
    Application.OnTime EarliestTime:=DateAdd("n", 1, Now), Procedure:="macro_name", Schedule:=True
End Sub

Sub macro_name()

    If Value > 10 Then
        SendEmail
    Else
        CreateNewSchedule
    End If

End Sub

You might want to store the time of the next schedule in a global variable so that the Workbook_BeforeCloseevent can cancel the next schedule. Otherwise Excel will re-open the workbook.

您可能希望将下一个计划的时间存储在全局变量中,以便Workbook_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

You can then continue to use Excel between the scheduled times.

然后,您可以在预定时间之间继续使用 Excel。

回答by Orphid

I think you need to specifically process the application event stack with a DoEventscall. This allows user interactions with the spreadsheet to occur, where normally the macro would take precedence. You code would look something like:

我认为您需要使用DoEvents调用专门处理应用程序事件堆栈。这允许用户与电子表格进行交互,通常宏优先。你的代码看起来像:

Do While True

    If Value > 10 Then
        SendEmail
    End If

    Sleep 60*CLng(1000)

    DoEvents
Loop

You could also construct a GUI with HTA if you wanted to remain with VBScript.

如果您想继续使用 VBScript,也可以使用 HTA 构建 GUI。