VBA Macro On Timer 样式每隔设定的秒数运行代码,即 120 秒

Posted

技术标签:

【中文标题】VBA Macro On Timer 样式每隔设定的秒数运行代码,即 120 秒【英文标题】:VBA Macro On Timer style to run code every set number of seconds, i.e. 120 seconds 【发布时间】:2010-02-23 16:09:32 【问题描述】:

我需要每 120 秒运行一段代码。我正在寻找一种在 VBA 中执行此操作的简单方法。我知道可以从Auto_Open 事件中获取计时器值,以防止必须使用幻数,但我不知道如何触发计时器以每 120 秒运行一次。

如果可以避免的话,我真的不想在睡眠中使用无限循环。


编辑

基于提供的答案的交叉帖子位于:Excel VBA Application.OnTime. I think its a bad idea to use this... thoughts either way?

【问题讨论】:

【参考方案1】:

当工作簿首次打开时,执行以下代码:

alertTime = Now + TimeValue("00:02:00")
Application.OnTime alertTime, "EventMacro"

然后在工作簿中添加一个名为“EventMacro”的宏来重复它。

Public Sub EventMacro()
    '... Execute your actions here'
    alertTime = Now + TimeValue("00:02:00")
    Application.OnTime alertTime, "EventMacro"
End Sub

【讨论】:

感谢这段代码 :) 需要这个尽快工作,这是我转到的第一页 :) 耶 您好,Excel sheet id最小化或打开另一个excel sheet时会报错吗? @ArunCheriyan 我看不出有什么理由。为什么,你看到一个错误?如果是这样,请尝试提出一个新问题并参考这个问题。 不是无限递归吗?几千/百万/十亿次函数调用后不会导致堆栈溢出吗? @BerryTsakala - Application.OnTime“从头开始”调用 Sub - 在新堆栈的顶部。它不像普通的递归方法调用。由于每个调用都有自己的堆栈 - 不可能发生堆栈溢出。【参考方案2】:

是的,您可以为此使用Application.OnTime,然后将其放入循环中。它有点像一个闹钟,当您希望它再次响起时,您可以一直按下贪睡按钮。以下内容每三秒更新一次 Cell A1 的时间。

Dim TimerActive As Boolean
Sub StartTimer()
    Start_Timer
End Sub

Private Sub Start_Timer()
    TimerActive = True
    Application.OnTime Now() + TimeValue("00:00:03"), "Timer"
End Sub

Private Sub Stop_Timer()
    TimerActive = False
End Sub

Private Sub Timer()
    If TimerActive Then
        ActiveSheet.Cells(1, 1).Value = Time
        Application.OnTime Now() + TimeValue("00:00:03"), "Timer"
    End If
End Sub

您可以将StartTimer 过程放入您的Auto_Open 事件中并更改在Timer 过程中所做的事情(现在它只是用ActiveSheet.Cells(1, 1).Value = Time 更新A1 中的时间)。

注意:您需要模块中的代码(除了StartTimer),而不是工作表模块。如果您在工作表模块中有它,则代码需要稍作修改。

【讨论】:

sub Timer 看起来像一个无限递归函数;除非 OnTime 的句柄保留在 sub 之外,否则 sub 将保持对其调用者的无限引用【参考方案3】:

在工作簿事件中:

Private Sub Workbook_Open()
    RunEveryTwoMinutes
End Sub

在一个模块中:

Sub RunEveryTwoMinutes()
    //Add code here for whatever you want to happen
    Application.OnTime Now + TimeValue("00:02:00"), "RunEveryTwoMinutes"
End Sub

如果您只想在工作簿打开之后执行第一段代码,那么只需在 Workbook_Open 事件中添加 2 分钟的延迟

【讨论】:

谢谢你,我搜索了我的错误原因。没有将宏放在模块中。现在我的代码也可以工作了。感谢您的解释。 :)【参考方案4】:

(这是从 MS Access 帮助文件中转述的。我确信 XL 也有类似的东西。)基本上,TimerInterval 是一个表单级属性。设置后,使用子 Form_Timer 执行您的预期操作。

Sub Form_Load()
    Me.TimerInterval = 1000 '1000 = 1 second
End Sub

Sub Form_Timer()
    'Do Stuff
End Sub

【讨论】:

感谢您的建议,但我不想将其作为表单的一部分。 为了将来参考,遗憾的是 Excel 没有 具有 TimerInterval 属性。据我所知,只有 MS Access 具有该表单属性,其他使用 VBA 的 MS 产品都没有等效项。【参考方案5】:

我发现使用OnTime 会很痛苦,尤其是在以下情况下:

    您正在尝试编码并且窗口上的焦点被中断 每次触发事件。 您打开了多个工作簿,关闭了应该使用计时器的工作簿,它不断触发并重新打开工作簿(如果您忘记正确终止事件)。

This article by Chip Pearson 非常有启发性。我现在更喜欢使用 Windows 计时器,而不是 OnTime

【讨论】:

根据 CPearson 文章,您只需停止计时器(取消挂起的 OnTime 事件)。这将消除您描述的“工作簿关闭时的事件触发”问题。此外,该文章还对使用 Windows 计时器和更改可能导致 Excel 崩溃的单元格值提出警告。 OnTime 需要的代码更少,在使用时正确处理即可。【参考方案6】:

我的解决方案:

Option Explicit
Public datHora As Date

Function Cronometro(action As Integer) As Integer 
'This return the seconds between two >calls
Cronometro = 0
  If action = 1 Then 'Start
    datHora = Now
  End If
  If action = 2 Then 'Time until that moment
    Cronometro = DateDiff("s", datHora, Now)
  End If
End Function

如何使用?简单...

dummy= Cronometro(1) ' This starts the timer

seconds= Cronometro(2) ' This returns the seconds between the first call and this one

【讨论】:

以上是关于VBA Macro On Timer 样式每隔设定的秒数运行代码,即 120 秒的主要内容,如果未能解决你的问题,请参考以下文章

如何在设定的时间段内使用计时器

vba如何启动数字键盘

有没有办法使用 vba/macro 一次将多个配置上传到 alm 中的测试用例?

xlwings: Write Excel macro using python instead of VBA

delphi7中怎样使用Timer这个组件?

EXCEL vba 合并相同单元格