Excel Visual Basic,如何停止因许多API调用而冻结?

问题描述 投票:1回答:1

我使用Visual Basic和Excel从API获取一些数据。我在For-Each循环的每次迭代中运行大约100个API调用,每次迭代将填充一行数据。

问题是,我的excel在完成大约4-5行后冻结了!

我认为这个问题的最佳解决方案是在每次API调用之间有大约3秒的延迟。这也可以防止我的API出现速率限制错误。

这是我目前的代码 -

For Each BidRow In Range("A2:A102")
        MyRequest.Open "GET", "https://api.someapi.com/values/" & Range("B" & RowNo)
        MyRequest.Send
        Set JsonBid = JsonConverter.ParseJson(MyRequest.ResponseText)
        Range("D" & RowNo).Value = JsonBid("key")   
        RowNo = RowNo + 1
Next BidRow

JsonConverter只是另一个模块。

无论如何,我不知道在Visual Basic中做任何延迟3000毫秒的方法,在使用settimeout()函数的Javascript中很容易做到这一点。或者我可能需要一些异步编码技术。我现在迷失了很多东西!

不知道怎么解决这个问题?

excel vba excel-vba
1个回答
2
投票

您可以使用此子项暂停指定数量的“整个”秒:

Sub Pause(delaySeconds As Integer)
    Dim startTime As Single
    startTime = Timer
    Do While Timer < startTime + delaySeconds
        DoEvents    ' Yield to other processes
    Loop
End Sub

例如,Pause(3)将暂停3秒钟。


但是,您确定Excel以不可恢复的方式“冻结”吗?我使用了很多API,我知道当我循环几百次时,看起来确实看起来像是崩溃了,但是有点耐心,这个过程确实完成了。

如果你在100 × 3 seconds = 5 minutes之前添加了一行,而不是暂停(并通过Next BidRow延长你的sub的执行时间):

DoEvents

编辑重新:每秒60次调用的API限制...

如果提供API的网站每分钟限制为60次,那么您的100次通话应该在不少于100秒的时间内运行。我打赌你低于那个但你可以通过计时程序来确保。

循环之前,您可以添加:

Dim LoopStart as Single

LoopStart = Timer

...然后在循环完成后,添加一行:

MsgBox "Loop finished in " & Round(Timer - LoopStart,0) & " seconds."

如果超出限制,大多数API只会返回一个错误,并在一两秒内正常恢复。我确信有一些例外,取决于您使用的API的精细打印,理论上该网站可能会从您的信用卡收取过多的电话(需要事先商定)或可能禁止你的知识产权经过多次滥用(我从未见过)。

例如,Google Maps Geocoding API有一个非常慷慨的“标准”限制:

每天2,500免费请求,以及

每秒50个请求。

默认情况下,超过此值的调用将返回(临时)错误,除非您使Enable Billing解锁更高的配额:

每天2,500个免费请求,然后,您需要支付0.50美元/ 1000个额外请求,每天最多100,000个

(Qazxswpoi)


您可以确保循环的每次迭代至少需要一秒钟,如下所示:

Source