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
可以随时从任何线程调用。
我正在使用 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.
通常,Excel 加载项 永远不会 从除主计算线程之外的任何线程调用 Excel。 Excel COM 对象模型(基本上)是单线程的,因此所有 COM 调用最终都必须在主线程上执行。来自另一个线程的任何调用都可能失败并出现 COM 错误,就像您看到的那样。
Excel-DNA 有一个辅助方法,允许您将委托安排在主 Excel 线程上 运行 - 您调用 ExcelAsyncUtil.QueueAsMacro(...)
。一旦 Excel 准备就绪,这将有委托 运行,并且在该上下文中的 COM 和 C API 调用都将起作用,因为委托将在主线程上 运行宏观背景。 ExcelAsyncUtil.QueueAsMacro
可以随时从任何线程调用。