Hi Caspar,
Yes, Excel-DNA can save you.
I'll lay out three approaches for you to consider:
1. Since your original code was a C XLL, easiest might be to just use
the C API from your C# add-in. In Excel-DNA this is very easy, since
you don't have to deal with XLOPERS or anything - all the marshaling
between XLOPERS and .NET types and the memory management is done
automatically. The C API is exposed through the
(ExcelDna.Integration.)XlCall.Excel method. This means you can port
the patterns that worked well in the old .xll to your new C# add-in,
and expect similar performance and stability.
However, you don't really describe how you implemented the "writes to
INPUT_OUTPUT_RANGE in another thread" in the old .xll. Since the C API
can only be called from the main Excel thread, you probably have some
ON.TIME handler that periodically checks shared data, but that causes
other problems. Whatever you do in the old .xll you'll be able to do
in the new C# add-in, probably more easily.
2. One way to initiate work on the main thread from another thread is
to run a macro via the COM interface, by calling Application.Run. If
you get COM to do the cross-apartment marshaling for your Application
interface, COM will also give the cross-thread marshaling you need to
safely have Application.Run running on the main thread, from which you
can change that cell and the rest follows. An example of using this
mechanism to update some cells from a separate thread is implemented
in the Distribution\Samples\ArrayResizer.dna sample. With Excel-DNA
you'll get a version of the Application interface that you can use
from a particular thread by calling the ExcelDnaUtil.Application
property from the thread where you want to use it. One major issue to
watch out for is that the cross-thread COM call can always fail since
the main Excel thread might be busy. So you need some error handling
with retry in the execution path running on the other thread - the
sample implements this too.
3. The best and most scalable approach, but also a bit more work and
with its own quirks, is to implement your notification as an RTD
server. This integrates very well into Excel's calculation
and dependency model, but there are still some issues to look out
for. For example, you have the same cross-thread problem when making
the call back to Excel. The typical way to deal with this is to set up
a _Windows_ timer on the main Excel thread which essentially polls for
updates, and notifies Excel periodically if there are changes. Excel
then takes care of calling the function again etc. Excel-DNA makes RTD
easier by (mostly) allowing you to deploy it without any COM
registration on the client, and also no administrator right needed to
deploy. All registration is done as-needed in the user's part of the
registry. The RTD servers can be wrapper in your own friendly-looking
functions, so you might even be able to get rid of the
INPUT_OUTPUT_RANGE, and just have a self-updating function.
There are some example RTD servers in the Distribution\Samples\RTD
directory, and the FinAnSu add-in (
http://code.google.com/p/finansu/)
implements an RTD server to provide updating real-time web quotes.
I don't know of any way in Excel to mark cells as 'clean', so you
should implement some sort caching for any slow functions.
I hope this gives you some ideas, and I look forward to more detailed
questions and hearing how you approach it.
Regards,
Govert
> posted this:
http://stackoverflow.com/questions/7879468/global-keyboard-hook-for-e...