Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vba Excel Visual Basic,如何停止由于许多API调用而冻结?_Vba_Excel - Fatal编程技术网

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

Vba Excel Visual Basic,如何停止由于许多API调用而冻结?,vba,excel,Vba,Excel,我正在使用Visual Basic和excel从API获取一些数据。我在每个循环的每个迭代中运行大约100个API调用,每个迭代将填充一行数据 问题是,我的excel在完成大约4-5行后会冻结 我认为解决这个问题的最好办法是在每次API调用之间有大约3秒的延迟。这也将防止API中的速率限制错误 这是我目前的密码- For Each BidRow In Range("A2:A102") MyRequest.Open "GET", "https://api.someapi.com/v

我正在使用Visual Basic和excel从API获取一些数据。我在每个循环的每个迭代中运行大约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只是另一个模块

无论如何,我不知道在VisualBasic中如何实现3000毫秒的延迟,在Javascript中使用settimeout()函数很容易做到这一点。或者我必须在这里学习一些异步编码技术。我现在在尝试很多事情时都迷路了


你知道怎么解决这个问题吗

您可以使用此sub暂停指定的“整”秒数:


编辑re:API每秒调用60次的限制

如果提供API的站点限制为每分钟60次调用,则100次调用应在不少于100秒的时间内运行。我打赌你在这以下,但你可以通过确定手术时间来确定

在循环之前,您可以添加:

Dim LoopStart as Single

LoopStart = Timer
…然后在循环完成后,添加一行:

MsgBox "Loop finished in " & Round(Timer - LoopStart,0) & " seconds."
如果超出限制,大多数API只会返回一个错误,并在一两秒钟内恢复正常。我敢肯定,根据你使用的API的细节,也会有例外。理论上,该网站可能会向你的信用卡收取过多的电话费(这需要事先商定),或者可能会在重复滥用后禁止你的IP(我从未见过)

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

每天2500个免费请求,以及

每秒50个请求

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

一天2500个免费请求,然后, 您将按每1000个额外请求收取0.50美元的账单,每天最多100000美元

()


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

For Each BidRow In Range("A2:A102")
    loopStart = Timer 'reset timer for each loop
    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
    Do While Timer < loopStart + 1
        DoEvents    ' Yield to other processes if under 1 second has passed
    Loop
Next BidRow
范围(“A2:A102”)内的每个投标行的

loopStart=每个循环的计时器重置计时器
我的请求。打开“获取”https://api.someapi.com/values/“&范围(“B”和行号)
我的请求。发送
设置JsonBid=JsonConverter.ParseJson(MyRequest.ResponseText)
范围(“D”和行号)。值=JsonBid(“键”)
RowNo=RowNo+1
当计时器<循环启动+1时执行
如果超过1秒,则DoEvents向其他进程的让步
环
下一个比德罗

可能的重复项您是否尝试在范围(“A2:A102”)行中的每个BidRow的
之后添加
DoEvents
应用程序。ontime会满足您的需要。我的问题是UI只是暂停,直到执行完成,它并没有完全停止工作。我认为解决方法是在API调用之间使用延迟。但是仅仅添加一行名为DoEvents的代码就非常有效!谢谢顺便问一下,是否需要一些延迟?因为我使用的是公共API,他们说他们将API调用的速率限制为一分钟60次。
MsgBox "Loop finished in " & Round(Timer - LoopStart,0) & " seconds."
For Each BidRow In Range("A2:A102")
    loopStart = Timer 'reset timer for each loop
    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
    Do While Timer < loopStart + 1
        DoEvents    ' Yield to other processes if under 1 second has passed
    Loop
Next BidRow