【问题标题】:Outlook VBA - Run a code every half an hourOutlook VBA - 每半小时运行一次代码
【发布时间】:2012-08-28 18:55:31
【问题描述】:

我想每半小时在 Outlook(VBA) 中运行一个特定代码。

当代码运行时,Outlook 用户也不应该受到干扰。它应该只在后端运行。

有一个名为Application_Reminder 的事件。它在 Outlook 中每次出现提醒时运行。但这仍然涉及用户交互。我想要一个完整的后端程序。

【问题讨论】:

  • 看看这个:stackoverflow.com/questions/9226311/schedule-outlook-2003-macro/…>
  • 当 Reminder 事件触发时,运行您的代码,在 30 分钟后安排另一个任务提醒,然后取消该事件。
  • 我听说可以使用 Timer 事件。任何人都可以分享代码来使用计时器实现这一点吗?

标签: vba outlook


【解决方案1】:

http://www.outlookcode.com/threads.aspx?forumid=2&messageid=7964

将以下代码放入 ThisOutlookSession 模块(工具->宏->VB 编辑器):

Private Sub Application_Quit()
  If TimerID <> 0 Then Call DeactivateTimer 'Turn off timer upon quitting **VERY IMPORTANT**
End Sub

Private Sub Application_Startup()
  MsgBox "Activating the Timer."
  Call ActivateTimer(1) 'Set timer to go off every 1 minute
End Sub

将以下代码放入新的 VBA 模块中

Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerfunc As Long) As Long
Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long

Public TimerID As Long 'Need a timer ID to eventually turn off the timer. If the timer ID <> 0 then the timer is running

Public Sub ActivateTimer(ByVal nMinutes As Long)
  nMinutes = nMinutes * 1000 * 60 'The SetTimer call accepts milliseconds, so convert to minutes
  If TimerID <> 0 Then Call DeactivateTimer 'Check to see if timer is running before call to SetTimer
  TimerID = SetTimer(0, 0, nMinutes, AddressOf TriggerTimer)
  If TimerID = 0 Then
    MsgBox "The timer failed to activate."
  End If
End Sub

Public Sub DeactivateTimer()
Dim lSuccess As Long
  lSuccess = KillTimer(0, TimerID)
  If lSuccess = 0 Then
    MsgBox "The timer failed to deactivate."
  Else
    TimerID = 0
  End If
End Sub

Public Sub TriggerTimer(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idevent As Long, ByVal Systime As Long)
  MsgBox "The TriggerTimer function has been automatically called!"
End Sub

关键点:

1) 此定时器功能不需要打开特定的窗口;它在后台运行

2) 如果您在应用关闭时不停用计时器,它可能会崩溃

3) 该示例显示了在启动时激活的计时器,但它可以很容易地被不同的事件调用

4) 如果您在启动时没有看到提示计时器已激活的消息框,则说明您的宏安全设置过高

5) 要在时间间隔的一次迭代后停用计时器添加: If TimerID 0 Then Call DeactivateTimer 在 sub TriggerTimer 中的 msgbox 语句之后

别人推荐的

“需要注意的一点,如果你不检查TimerID是否与TriggerTimer中的idevent相同,你会得到每隔一段时间,而不是你要求的时间。”

Public Sub TriggerTimer(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idevent As Long, ByVal Systime As Long)
    'keeps calling every X Minutes unless deactivated
    If idevent = TimerID Then
        MsgBox "The TriggerTimer function has been automatically called!"
    End If
End Sub

【讨论】:

  • 工作谢谢。虽然 Public Sub ActivateTimer(ByVal nMinutes As Long) 应该更改为 As Double,但我被困在一个循环中,因为我使用了四舍五入为 0 的一分钟。
  • +1 @niton 刚刚在一个烦人的解决方案中使用了这段代码,因为工作中的 Outlook 保留限制了我不得不编写的解决方案。 garrett.ms/2019/02/11/…
【解决方案2】:

对于 Win64,我需要将其更改为:

Declare PtrSafe Function SetTimer Lib "user32" (ByVal hwnd As LongLong, ByVal nIDEvent As LongLong, ByVal uElapse As LongLong, ByVal lpTimerfunc As LongLong) As LongLong
Declare PtrSafe Function KillTimer Lib "user32" (ByVal hwnd As LongLong, ByVal nIDEvent As LongLong) As LongLong

Public TimerID As LongLong 'Need a timer ID to eventually turn off the timer. If the timer ID <> 0 then the timer is running

Public Sub TriggerTimer(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idevent As Long, ByVal Systime As Long)
  MsgBox "The TriggerTimer function has been automatically called!"
End Sub


Public Sub DeactivateTimer()
Dim lSuccess As LongLong
  lSuccess = KillTimer(0, TimerID)
  If lSuccess = 0 Then
    MsgBox "The timer failed to deactivate."
  Else
    TimerID = 0
  End If
End Sub

Public Sub ActivateTimer(ByVal nMinutes As Long)
  nMinutes = nMinutes * 1000 * 60 'The SetTimer call accepts milliseconds, so convert to minutes
  If TimerID <> 0 Then Call DeactivateTimer 'Check to see if timer is running before call to SetTimer
  TimerID = SetTimer(0, 0, nMinutes, AddressOf TriggerTimer)
  If TimerID = 0 Then
    MsgBox "The timer failed to activate."
  End If
End Sub

【讨论】:

    【解决方案3】:

    更正 64 位的上层答案:

    Declare PtrSafe Function SetTimer Lib "user32" (ByVal hwnd As LongLong, ByVal nIDEvent As LongLong, ByVal uElapse As LongLong, ByVal lpTimerfunc As LongLong) As LongLong
    Declare PtrSafe Function KillTimer Lib "user32" (ByVal hwnd As LongLong, ByVal nIDEvent As LongLong) As LongLong
    
    Public TimerID As LongLong 'Need a timer ID to eventually turn off the timer. If the timer ID <> 0 then the timer is running
    
    Public Sub TriggerTimer(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idevent As Long, ByVal Systime As Long)
      MsgBox "The TriggerTimer function has been automatically called!"
    End Sub
    
    
    Public Sub DeactivateTimer()
    Dim lSuccess As LongLong              '<~ Corrected here
      lSuccess = KillTimer(0, TimerID)
      If lSuccess = 0 Then
        MsgBox "The timer failed to deactivate."
      Else
        TimerID = 0
      End If
    End Sub
    
    Public Sub ActivateTimer(ByVal nMinutes As Long)
      nMinutes = nMinutes * 1000 * 60 'The SetTimer call accepts milliseconds, so convert to minutes
      If TimerID <> 0 Then Call DeactivateTimer 'Check to see if timer is running before call to SetTimer
      TimerID = SetTimer(0, 0, nMinutes, AddressOf TriggerTimer)
      If TimerID = 0 Then
        MsgBox "The timer failed to activate."
      End If
    End Sub
    

    【讨论】:

    • Max 在上面的答案中解决了这个问题,所以不再需要了吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-03
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 2012-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多