异步VBA功能

时间:2018-07-17 19:33:09

标签: excel vba asynchronous

我有一个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

2 个答案:

答案 0 :(得分:1)

VBA-Web/src/WebAsyncWrapper.cls

enter image description here

WebAsyncWrapper.ExecuteAsync有一个可选参数:CallbackArgs。使用此参数可以将ID或单元格地址传回给您。

ExecuteAsync有一个示例回调函数,该函数接收一个参数数组。

enter image description here

这里是如何将信息返回给函数进行处理。

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,回调将值放入字典中,并再次调用查询函数。