如何使用Application.OnTime来延迟循环

时间:2013-09-22 23:03:03

标签: vba timer

所以我正在编写一个引用bloomberg单元格公式的代码...因此,循环通常比数据加载时跳得更快。我认为如果我能以某种方式延迟循环的迭代,这可以相对容易地解决...这将给予单元时间填充。这是我到目前为止所写的内容,我不确定如何写出最后一行。

x = 1


If x < TixCollection.count Then

    ' runs report if ADR Close is active
    If Sheets("Input").Range("L2").value = "x" Then
        Call build_singleEquity(x)
            'Set pat = New pattern

            Application.OnTime Now + TimeValue("00:00:10"), "pattern_recogADR"

            If Sheets("Input").Range("L5").value = "x" Then
                Dim sht_name As String
                sht_name = TixCollection(x).ADR & "_ADRclose"
                Call Sheet_SaveAs(path_ADRclose, sht_name, "SingleEquityHistoryHedge")
            End If
    End If


    'runs report if ORD Close is active
    If Sheets("Input").Range("L9").value = "x" Then
        Call build_ordCloseTrade(x)



            If Sheets("Input").Range("L13").value = "x" Then

                Dim sht_name1 As String
                sht_name1 = TixCollection(x).ADR & "_ORDclose"
                Call Sheet_SaveAs(path_ORDclose, sht_name1, "OrdCloseTrade")
            End If
    End If


Application.OnTime Now + TimeValue("00:00:15"), x = x + 1 'want to write something like this but syntax is wrong 

1 个答案:

答案 0 :(得分:3)

Application.OnTime基本上安排一个事件在特定时间/之后运行。它允许您安排一个事件在代码执行完毕后运行并清除堆栈。这就是为什么它是Application级方法。

OnTime方法暂停或延迟任何内容,它只是一个调度程序。因此,其余的代码将继续执行,并且无论代码依赖于等待OnTime的任务的结果,您都会遇到错误。

从理论上讲,我认为您可能会为了您的目的而以迂回的方式使用此方法,但我认为您可能更适合使用WinAPI Sleep函数。这也为您提供了更大的粒度(您可以指定毫秒)。

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

您可以通过调用:

从任何子例程或函数调用它
Sleep 5000 'pause for 5000ms, (5 seconds)

<强>更新

我注意到您的代码实际上并不包含Loop结构。我想我明白你要做什么。这是对它的抨击:

Do While x < TixCollection.count Then  `or consider: Do While x <= TixCollection.Count

    ' runs report if ADR Close is active
    If Sheets("Input").Range("L2").value = "x" Then
        Call build_singleEquity(x)
            'Set pat = New pattern

            Sleep 10000
            Call pattern_recogADR

            If Sheets("Input").Range("L5").value = "x" Then
                Dim sht_name As String
                sht_name = TixCollection(x).ADR & "_ADRclose"
                Call Sheet_SaveAs(path_ADRclose, sht_name, "SingleEquityHistoryHedge")
            End If
    End If


    'runs report if ORD Close is active
    If Sheets("Input").Range("L9").value = "x" Then
        Call build_ordCloseTrade(x)
            If Sheets("Input").Range("L13").value = "x" Then

                Dim sht_name1 As String
                sht_name1 = TixCollection(x).ADR & "_ORDclose"
                Call Sheet_SaveAs(path_ORDclose, sht_name1, "OrdCloseTrade")
            End If
    End If

x = x+1
Sleep 15000  'Wait for 15 seconds  
Loop

很难判断是否真的需要Sleep(之前的OnTime次调用),因为我不确定哪一个(或两者都是)引入了错误条件。

您需要确保将Sleep函数的代码放在vba项目中。

更新

假设睡眠功能或Application.Wait方法对您不起作用,您可以尝试的另一件事是简单的Do/While循环。虽然我无法复制你的病情,但这似乎是最可靠的。

Dim newTime As Date
newTime = Now + TimeValue("00:00:10")
Do While Not Now >= newTime
    DoEvents
Loop

最后一个选项是禁用并手动强制计算,如下所示。我的理解是应用程序很忙,并且在计算事件发生时不会执行代码。但是,考虑到这一点,我不确定这些方法中的任何一种是否适合您,因为虽然您表示它正在等待Excel工作表计算,但我认为这不可能,工作表事件优先于运行代码,所以我认为客户端仍然会发生一些事情,除非他们通过API提供某种方法(类似于.Busy返回一个布尔值等),否则你可能无法可靠地捕获它们。

Dim appCalc as Long: appCalc = Application.Calculation
Application.Calculation = appCalc  '# disable automatic calculation
Call build_singleEquity(x)
Application.Calculate 'Force calculation
Application.Calculation = xlCalculationAutomatic  '# return to normal/previous property
Call pattern_recogAD