我有一个VBA函数,该函数应该从用户单元中获取一些信息,使用该信息发出POST请求,然后在输出单元中打印响应。
要求用户一次只能发出约2000个请求,因此我认为使请求异步进行有助于提高性能。
就目前而言,我有一个函数ConnectToAPI发出异步请求,然后将响应传递给回调函数。我遇到的问题是数据存在于回调函数中,但我需要在查询函数中才能返回它。
Function Query(ID, quote, field)
Application.Volatile
Query = ConnectToAPI(ID)
Some logic with parsed data from callback
End Function
Function ConnectToAPI(ID)
Dim Request As New WebRequest
Dim Client As New WebClient
Client.BaseUrl = "http://www.endpoint.com"
Dim Wrapper As New WebAsyncWrapper
Dim Wrapper.Client = Client
Dim Body As New Dictionary
Body.Add "ID", ID
Set Request.Body = Body
Request.Method = HttpPost
ConnectToAPI = Wrapper.ExecuteAsync Request, "CallbackFunction"
End Function
Function CallbackFunction
Callback = Parsed Data
End function
所以最终在查询功能中,我想写
查询=(从回调中解析的数据)
如何将回调中的数据传递回查询?
单元格中具有查询功能很重要。数据经常更新,因此我们希望客户能够计算工作簿以获取最新数据。
根据我目前的情况,我的想法是回调将数据传递回ConnectToAPI,然后将其传递给Query。但是,我的函数返回0,我认为这可能是一旦函数尝试返回解析后的数据将不可用。
作为参考,我正在使用VBA-Web库 https://github.com/VBA-tools/VBA-Web
答案 0 :(得分:1)
VBA-Web/src/WebAsyncWrapper.cls
WebAsyncWrapper.ExecuteAsync
有一个可选参数:CallbackArgs
。使用此参数可以将ID或单元格地址传回给您。
ExecuteAsync
有一个示例回调函数,该函数接收一个参数数组。
这里是如何将信息返回给函数进行处理。
Sub ConnectToAPI(ID As Variant, quote As Variant, field As Variant, CellAddress As Variant)
Dim Request As New WebRequest
Dim Client As New WebClient
Client.BaseUrl = "http://www.endpoint.com"
Dim Wrapper As New WebAsyncWrapper
Dim Body As New Dictionary
Body.Add "ID", ID
Set Request.Body = Body
Request.Method = HttpPost
Set Wrapper.Client = Client
Wrapper.ExecuteAsync Request, "Callback", Array(ID, CellAddress)
End Sub
Public Function Callback(Response As WebResponse, Args As Variant)
Dim ID As Variant, CellAddress As Variant
ID = Args(0)
CellAddress = Args(1)
With Worksheets("Web Requests")
.Range(CellAddress).Value = Response
.Range(CellAddress).Offset(0, 1).Value = ID
End With
End Function
MSDN - Application.Volatile Method (Excel)
将用户定义的功能标记为易失性。每当在工作表上的任何单元格中进行计算时,都必须重新计算volatile函数。仅当输入变量更改时,才会重新计算非易失性函数。如果该方法不在用于计算工作表单元格的用户定义函数中,则该方法无效。
我不建议尝试使用可以用作工作表函数的UDF来返回Web请求。 Application.Volatile
将导致每次更改值时刷新所有2000个查询。当第一个查询更新时,所有其他查询将刷新。这将导致无限循环并使应用程序崩溃。
Function Query(ID, quote, field)
Application.Volatile
Query = ConnectToAPI(ID)
Some logic with parsed data from callback
End Function
使用Worksheet_Change
事件将使用户能够更新信息,而不会出现与Application.Volatile
相关的问题。
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Columns("A")) Is Nothing Then
If Target.Count = 1 Then
Debug.Print Target.Value, Target.Address
End If
End If
End Sub
答案 1 :(得分:0)
我最终用API调用的响应值填充了字典,然后在回调中递归调用了查询函数。
查询检查响应值是否在字典中,如果存在,则返回它。如果没有,它将连接到api,回调将值放入字典中,并再次调用查询函数。