10

我正在使用 Application.Ontime 事件从单元格中提取时间字段,并安排一个子例程在该时间运行。我的 Application.Ontime 事件在 Workbook_BeforeSave 事件上运行。因此,如果用户多次(更改所需时间 + 保存工作簿),则会创建多个 Application.Ontime 事件。从理论上讲,我可以使用唯一的时间变量来跟踪每个事件。但是有没有办法检查/解析/取消挂起的事件?

Private Sub Workbook_BeforeSave
    SendTime = Sheets("Email").Range("B9")
    Application.OnTime SendTime, "SendEmail"
End Sub

Private Sub Workbook_BeforeClose
    Application.OnTime SendTime, "SendEmail", , False
End Sub

因此,如果我:
将 B9 更改为 12:01,将工作簿
更改 B9 保存为 12:03,将工作簿
更改 B9 保存为 12:05,将工作簿
更改 B9 保存为 12:07,保存工作簿

我最终触发了多个事件。我只希望触发一个事件(最近安排的一个)

如何取消 Workbook_BeforeClose 事件上的所有待处理事件(或至少枚举它们)?

4

4 回答 4

3

我不认为您可以遍历所有未决事件或一次性取消它们。我建议设置一个模块级别或全局布尔值,指示是否触发您的事件。所以你最终会得到这样的东西:

Dim m_AllowSendMailEvent As Boolean
Sub SendMail()
If Not m_AllowSendMailEvent Then Exit Sub

'fire event here

End Sub

编辑:

将此添加到工作表模块的顶部,该模块包含包含您所追求的日期/时间值的范围:

' Most recently scheduled OnTime event. (Module level variable.)
Dim PendingEventDate As Date

' Indicates whether an event has been set. (Module level variable.)
Dim EventSet As Boolean

Private Sub Worksheet_Change(ByVal Target As Range)

Dim SendTimeRange As Range

' Change to your range.
Set SendTimeRange = Me.Range("B9")

' If the range that was changed is the same as that which holds
' your date/time field, schedule an OnTime event.
If Target = SendTimeRange Then

    ' If an event has previously been set AND that time has not yet been
    ' reached, cancel it. (OnTime will fail if the EarliestTime parameter has
    ' already elapsed.)
    If EventSet And Now > PendingEventDate Then

        ' Cancel the event.
        Application.OnTime PendingEventDate, "SendEmail", , False

    End If

    ' Store the new scheduled OnTime event.
    PendingEventDate = SendTimeRange.Value

    ' Set the new event.
    Application.OnTime PendingEventDate, "SendEmail"

    ' Indicate that an event has been set.
    EventSet = True

End If

End Sub

这是一个标准模块:

Sub SendEmail()

    'add your proc here

End Sub
于 2011-01-05T01:24:58.373 回答
1

每次调用 Application.Ontime 时保存事件设置为运行的时间(您可以将其保存在工作表或模块范围的动态数组中)

每次您的事件触发时,删除相应的保存时间

要取消所有挂起的事件,请通过调用 Application.Ontime 与 schedule = false 的剩余保存时间进行迭代

于 2011-01-05T09:39:42.920 回答
1

根据已经给出的一些建议,我想我可能有一个可行的解决方案。

简而言之,我们创建了一个全局数组,并且每次用户点击saveSendTime 时都会将其写入数组。这有助于跟踪我们所有的预定时间。

当工作簿关闭时,我们循环遍历数组并删除所有计划的时间。

我对此进行了测试,它似乎可以在 Excel 2003 上运行。让我知道你的进展情况。

Dim scheduleArray() As String //Set as global array to hold times

Private Sub Workbook_BeforeSave
    SendTime = Sheets("Email").Range("B9")
    AddToScheduleArray SendTime
    Application.OnTime SendTime, "SendEmail"
End Sub

Private Sub Workbook_BeforeClose
    On Error Resume Next
    Dim iArr As Integer, startTime As String

    For iArr = 0 To UBound(scheduleArray) - 1 //Loop through array and delete any existing scheduled actions 
        startTime = scheduleArray(iArr)
        Application.OnTime TimeValue(startTime), "SendEmail", , False
    Next iArr
End Sub

Sub AddToScheduleArray(startTime As String)
    Dim arrLength As Integer

    If Len(Join(scheduleArray)) < 1 Then
        arrLength = 0
    Else
        arrLength = UBound(scheduleArray)
    End If

    ReDim Preserve scheduleArray(arrLength + 1) //Resize array
    scheduleArray(arrLength) = startTime //Add start time
End Sub
于 2011-01-10T19:27:22.340 回答
1

或者您可以创建一些单元格(如算盘),例如:

如果我使用 application.ontime:

if range("V1") < 1 then

    Application.OnTime dTime, "MyMacro"

    range("V1")=range("V1") + 1

 end if

如果我想停止计数...

   Application.OnTime dTime, "MyMacro", , False

   range("V1")=range("V1") - 1
于 2011-11-15T09:23:44.373 回答