I'm using excel-DNA to make the addins, one addin handles communication to an API and another handles the inputs and routes. The second addin needs to be separate as other addins use it to post to the same api, and it is used to hold information about the address and user.
In VBA i used Application.Run() to run other files functions so I assumed the ExcelDnaUtil.Application.run() worked the same way, which it did. The issue is that the async functions, when they are trying to use application.run when the user is entering in a cell or selecting multiple cell and they get an error 0x800AC472.
I tried to solve the problem by looping until the function was successful (example below) using the ideas from this thread HRESULT 800ac472 from set operations in Excel 使用preventDefault,但当有人打开格式或功能向导窗口时,错误仍然存在。
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这个功能还没有完成再次计算?
是否有人需要更多信息来提供帮助?
任何帮助将不胜感激
答案 0 :(得分:1)
运行AsyncTest
时,SyncTest
将在ThreadPool线程上运行(由于Task.Run
)。从那里你正在用Excel进行COM调用。
作为一项规则,Excel加载项应该从不从除主计算线程之外的任何线程调用Excel。 Excel COM对象模型(基本上)是单线程的,因此所有COM调用最终都必须在主线程上执行。来自另一个线程的任何调用可能会因为您看到的COM错误而失败。
Excel-DNA有一个帮助方法,允许您安排在主Excel线程上运行的委托 - 您调用ExcelAsyncUtil.QueueAsMacro(...)
。这将在Excel准备好后运行委托,并且该上下文中的COM和C API调用都将起作用,因为委托将在宏上下文中的主线程上运行。 ExcelAsyncUtil.QueueAsMacro
可以随时从任何线程调用。