Reputation: 112
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 but the errors still come when someone opens a formatting or function wizard 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
So is there a different way of calling a function from another xll?
Or is there a way of telling the function not to calculate until the function is free?
Or is there a way of telling Excel that this function hasn't finished calculating try again?
Does anyone need any more information to help?
Any help will be appreciated
Upvotes: 0
Views: 1151
Reputation: 16907
When you run AsyncTest
, the SyncTest
will run on a ThreadPool thread (due to Task.Run
). From there you are making a COM call from Excel.
As a rule, an Excel add-in should never call into Excel from any thread except the main calculation thread. The Excel COM object model is (basically) single-threaded, so all COM calls eventually have to execute on the main thread. Any call from another thread might fail with a COM error like the one you see.
Excel-DNA has a helper method that allows you to schedule a delegate to be run on the main Excel thread - you call ExcelAsyncUtil.QueueAsMacro(...)
. This will have the delegate run once Excel is ready, and both COM and C API calls in that context will work, since the delegate will run on the main thread in a macro context. ExcelAsyncUtil.QueueAsMacro
can be called from any thread at any time.
Upvotes: 1