Excel-DNA 从另一个异步 xll 函数调用 xll 函数(HRESULT 异常:0x800AC472)

Excel-DNA calling xll function from another async xll function (Exception from HRESULT: 0x800AC472)

我正在使用 excel-DNA 制作插件,一个插件处理与 API 的通信,另一个处理输入和路由。第二个插件需要分开,因为其他插件使用它来 post 到相同的 api,它用于保存有关地址和用户的信息。

在 VBA 中,我使用 Application.Run() 来 运行 其他文件函数,所以我假设 ExcelDnaUtil.Application.run() 以相同的方式工作,它确实如此。问题是异步函数在用户输入单元格或选择多个单元格时尝试使用 application.run 时出现错误 0x800AC472。

我尝试使用此线程中的想法通过循环直到函数成功(下面的示例)来解决问题 HRESULT 800ac472 from set operations in Excel 但是当有人打开格式化或函数向导时错误仍然出现 window.

Public Shared Function AsyncTest(a As Integer, b As Integer) As Object
    Return ExcelAsyncUtil.Run("AsyncTest", New Object() {a, b}, Function() SyncTest(a, b))
End Function

<MethodImpl(MethodImplOptions.Synchronized)>
Public Shared Function SyncTest(a As Integer, b As Integer) As Object
    Try
        Dim Package = String.Concat({"<Model><a>", a, "</a><b>", b, "</b></Model>"})

        Dim xlApp As Object
        xlApp = ExcelDnaUtil.Application
        Dim failed as boolean = false
        Do
            Try
                Return xlApp.Run("PostToApiXmlToJson", Package, "api/test/add")  

            Catch e As System.Runtime.InteropServices.COMException
                If e.ErrorCode = -2146777998 Then
                    failed = True
                    System.Threading.Thread.Sleep(10)
                End If
                Debug.Write(String.Concat({"ErrorCode: #### ", e.ErrorCode, " #### PostToAPI"}))
            End Try

            count = count + 1

            Loop Until failed = False Or count > 100

        Catch err As Exception
            Return err.Message
        End Try
    End Function

那么从另一个 xll 调用函数有不同的方法吗?

或者有没有办法告诉函数在空闲之前不要计算?

或者有没有办法告诉Excel这个函数还没有完成计算再试一次?

是否有人需要更多信息来提供帮助?

任何帮助将不胜感激

当您 运行 AsyncTest 时,SyncTest 将在 ThreadPool 线程上 运行(由于 Task.Run)。从那里您正在从 Excel.

进行 COM 调用

通常,Excel 加载项 永远不会 从除主计算线程之外的任何线程调用 Excel。 Excel COM 对象模型(基本上)是单线程的,因此所有 COM 调用最终都必须在主线程上执行。来自另一个线程的任何调用都可能失败并出现 COM 错误,就像您看到的那样。

Excel-DNA 有一个辅助方法,允许您将委托安排在主 Excel 线程上 运行 - 您调用 ExcelAsyncUtil.QueueAsMacro(...)。一旦 Excel 准备就绪,这将有委托 运行,并且在该上下文中的 COM 和 C API 调用都将起作用,因为委托将在主线程上 运行宏观背景。 ExcelAsyncUtil.QueueAsMacro 可以随时从任何线程调用。