Hi Patrick,
I don't use context in any sense more technical than the 'surrounding
conditions in which the code is running'. I'm basically trying to
explain the Excel behaviour that I've seen and that has been reported.
I know of no documentation or resources that give more detail on the
behaviour we're discussing here.
-----
Let me start with an example in the VBA world:
If you create a user-defined function in VBA and it is called from a
worksheet formula, the function will not be able to set other parts of
the sheet. So a function like this will fail when called from a
worksheet formula
Function MyTest() As String
Range("B2").Value = "XXX
MyTest = "Hello"
End Function
Also, if MyTest were to call any other Function or Sub that tries to
set values on the sheet, that set would fail too.
Why does this fail?
I guess Excel has somehow remembered that it is busy calling a
function from a worksheet, so it has some internal flag or something
set that prevents the Range setter from working. So I'd say that when
Excel is calling your function while calculating a worksheet formula,
your code is running in a 'context' where setting values elsewhere in
the sheet is prohibited.
So already in VBA you have a case whether it is not true that 'any
feature was available anywhere'. The execution path to your
Range(...).Value setter determines whether it is a valid call or not.
------
Now Excel seems to also go into a special internal state when it calls
a user-defined function or macro in an .xll - a state where Excel is
ready to accept calls on the C API.
However, in the ribbon event handlers it seems Excel is not in a state
where it can accept calls on the C API.
Where else might Excel not be ready to accept C API calls?
* Certainly from any thread that is not the main Excel thread you
can't just call the C API (except for some restricted calls in the
multithreaded function evaluation).
* I think if you make some kind of UI on the main thread, say a
Windows Forms form or WPF window, and have event handlers for the
control, your event handlers can't call the C API.
* If you're in any of the RTD server methods, it seems you can't call
the C API.
As discussed previously, you can always use the COM interface to call
Application.Run to run a macro, and in this case Excel will know it is
running a macro and will be ready to accept C API calls.
How do you know if you're using the C API or the COM object model?
In Excel-DNA the ExcelReference and XlCall types define the C API. Any
part of the COM object model (that you know from VBA) reached through
ExcelDnaUtil.Application is part of the COM object model, and so
should be safe within your ribbon handlers.
-------
Do you ever have to use the C API - can't you always just use the COM
object model?
Here's a bit of a discussion about the different ways to interface
with Excel:
http://msdn.microsoft.com/en-us/library/bb687829.aspx.
Excel-DNA add-ins are Xll add-ins and are registered using the C API -
because this is the only way of providing high-performance well-
integrated user-defined functions to Excel. But Excel-DNA also has
support for integrating with the COM object model. So Excel-DNA gives
you access to the full range of Excel extensibility.
For user-defined functions (called from a worksheet formula), only the
C API is supported. In my experience the COM object model used
carefully seems to work OK, but it is not supported by Microsoft - see
http://support.microsoft.com/kb/301443.
For macros (I mean anything run from a menu or ribbon handler, or via
Application.Run) the COM object model is supported and is probably
what I'd recommend for manipulating Excel. This is what your code
ported from VBA (using late-binding, the PIA or NetOffice) is doing.
The COM object model is richer than the C API - there are many
features of Excel not exposed through the C API.
However, sometimes the C API gives better performance at getting data
into or out of the sheet - see the story here:
http://stackoverflow.com/questions/3840270/fastest-way-to-interface-between-live-unsaved-excel-data-and-c-sharp-objects/3868370#3868370.
Rarely you might need some specialised information that is only
provided through the C API - this is the case for example when trying
to retrieve the .xll's path, which is a concept the COM object model
doesn't know about.
----
For the simplest add-ins that just add some user-defined functions to
Excel, none of this is important. If you are some macros from VBA,
mostly you can continue to use the COM object model and all will be
fine.
But at some level of sophistication you'll have to deal with the
complexity of the mix of interfaces Excel presents. Current versions
of Excel just do not offer a well-documented, comprehensive
programming interface. With Excel-DNA I try to make it possible to
access both the C API and COM interfaces from .NET, as completely and
flexibly as possible.
----
None of this talk about calling Excel from other threads yet. There
are some issues particular to calling the Excel COM object model from
another thread.
Anyway, I'm also still learning about this. So any additional
information would be very welcome.
I hope this answers your current questions.
Regards,
Govert