I have:
A VSTO Excel Add-In;
An override object RequestComAddInAutomationService() which returns an instance of a class which is annotated as
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
and implements an interface which is annotated
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
Accessing the Globals.ThisAddIn.Application.COMAddIns.Item("MyAddinName").Object from the addin process I am able to get the above mentioned class;
Accessing Marshal.GetActiveObject("Excel.Application").COMAddIns.Item("MyAddinName").Object in c# code which is called (Excel DNA) from a VBA macro I usually am able to get the above mentioned class. But on certain machines this reference is null.
Anyone knows what could be the reason?
Make sure the COMAddins are available in Developer => Com Add-Ins button in both the machine first.
In your Excel-DNA add-in, you should always get the right Application object with a call to ExcelDnaUtil.Application. Otherwise, with bad code like GetActiveObject(...) you might get another Excel instance running on that machine.
Related
Here is scenario:
I have a VB6 project. It contains a method which receives parameter of type variant by ref.
Function GetFilledInfo(data As Variant)
This method fills the received parameter with a structure. This structure is defined in my VB6 project as follows.
Public Type DATASTRUCTMAIN
structChild As DATASTRUCTCHILD
End Type
Public Type DATASTRUCTCHILD
m_bComputeRanges As Long
End Type
I have a C# program which calls this method by referring the ActiveX dll generated by VB6 project.
I want to declare structure that is defined in VB6 inside my C# program and want to get it filled by using VB6 method.
How can I do this?
Thanks in advance.
I can't help noticing that you are only passing a Long (unless you have truncated those structure definitions for brevity). In that case, just change the VB6 so that it exposes a function that returns a Long!
If you have a real structure...
Move the structure definition to a public class in your VB6 project. Then the structure definition will become publicly available through COM for any clients who reference your VB6 project.
Hopefully you will be able to use it in your C# project and you will be able to declare instances of the structure. You do have a reference to the VB6 component in the Project References in your C# project, right? Not too familiar with .Net COM interop, so not sure about this.
If you have any problems declaring instances of the structure in your C# project, you could change the VB6 structure into a class? Apparently structures can be problematic in COM interop
I am trying to evaluate Excel DNA to use it in one of my excel add-in. I use C# functions (.NET 4.0) and want to invoke these functions from Excel. The reason I am interested is, the users of my addin are non-admins and hence would be a breakthrough, if I can find a solution not to do a regasm on my .NET dll, to get my addin working.
I understand that if it is like a worksheet function (with simple return types and arguments), as in: private string Add (int a, double b)
I can easily wrap expose them using excel dna. Also, I understand that, I can also call these simple functions using Application.Run from VBA.
But, if I have a complex type involved in the API and want to use this from VBA then do I require to regasm that assembly and types? example as in this:
private MyType AddLogic (myType1 A, myType2 B)
Or is there any way in Excel DNA, that I can also consume such kinds of functions in VBA without any regasm or regsvr32 ?
Thanks
Mani
You are referring to the built-in COM server support in Excel-DNA. There are a few options, all of them work fine for users without administrator rights.
You can register the COM types at runtime in your AutoOpen - they will then be available late-bound from VBA (so everything in VBA calling those COM types will be 'Variant' and you get no intellisense).
You can register the COM types with regsvr32, using the .xll as your COM server. The Excel-DNA registers its types in the HKEY_LOCAL_USER part of the registry, which the user can always write to.Then the VBA project that uses the COM-exposed types will run even if the .xll add-in is not loaded.
To add type library information for the COM-exposed types, you will have to do the regsvr32 registration, which again works without admin rights, and then you get intellisense etc. in VBA.
In none of these cases do you use RegAsm - which registers managed assemblies for runtime activation - since the native Excel-DNA .xll mediates the COM activation of your .NET types itself.
If you are not interested in providing worksheet functions, ribbons etc. you probably don't need Excel-DNA for this. You can register .NET assemblies for use by non-admin from VBA by just making a .reg script which will right the registry entries in HKEY_LOCAL_USER instead of HKEY_CLASSES_ROOT. I mean to say that the non-admin registration of Excel-DNA is no special magic. The main reason for integration of this feature in Excel-DNA is to ensure that those objects are activated in the same AppDomain as the rest of the Excel-DNA add-in, which is tricky and sometimes important.
So I want to capture some key-commands in our Docuement-level Excel VSTO addin. I can't seem to find a way to do it, other than to use VBA and have our addin talk to the VBA. Any help/examples would be greatly appreciated.
I am using Excel 2007.
One method involves using the 3rd party solution from Addin-Express. Their product includes the ability to add a keyboard shortcut as a property to the ribbon menu commands.
The other way is to make use of low level keyboard hooks, through some Win32 API's which is generally referred to as windows subclassing. Here is an excellent explanation with code sample of how to do it. Note that the only "extra" thing you need to do to get this code to "work" in VSTO is moving the SetHook() method to the Startup event, and the UnhookWindowsHookEx() method to the Shutdown event.
Check out the article on MSDN here by Stephen Toub.
Finally there is the use of the OnAction property of the Addin class. This method requires the use of some VBA (in terms of a callback method that points back to the underlying .net addin), and works ok so long as you are willing to distribute some VBA in your solution (i.e. a xls or doc w/ vba project, or perhaps a native addin). Note you will also need to mark comvisible = true, and expose the GetAutomationServiceObject method so that your VBA can reference your addin from VBA code.
see here for a thread on it...
You can only do this through API calls to subclass Excel and watch for key commands. This is older, but it still applies.
We have an existing add-in that we publish to users via click once. We would now like to use this as a vehicle to publish some of our existing C# methods directly into Excel so that the users can call them as a UDF.
For example - I have an assembly called MyAssembly, that has a class called MyClass with a public method called MyMethod. I also have an excel addin which adds some item to the ribbon for some custom functionality. I would now like to publish MyAssembly with my existing addin so that a person who has the addin installed can enter =MyMethod into a cell and have my custom method run.
How would one go about doing this?
I solved this quite comprehensively by using ExcelDna, an open source XLL implementation which is very simple to use, and pretty much avoids the whole COM debacle all together. So far it has matched our requirements perfectly...
http://groups.google.com/group/exceldna
you have not been very verbose about what you want to do. What do you mean with "users can call them"?
If you mean that add-in methods should be exposed to VBA you can find two articles on that here:
http://blogs.msdn.com/andreww/archive/2008/08/13/comaddins-race-condition.aspx
http://blogs.msdn.com/andreww/archive/2008/08/11/why-your-comaddin-object-should-derive-from-standardolemarshalobject.aspx
A sample I'm working on calls CoCreateInstance for class Microsoft_Office Excel Worksheet. It fails with HRESULT of 0x80040514 ("Class not registered"). Other Excel classes (Excel.Application) are registered on the system, but not the one for Worksheet .....Is it possible to register this class?
Update: I'm using Microsoft's DSOFramer sample project. It first tries to bind using an IMoniker class. If that fails, it calls CoCreateInstance for the clsid. This may work for other MS Office objects, but when it's Excel, the class is for the Worksheet. I modified the sample to CoCreateInstance _Application, then got the workbooks, then called the Workbooks::Open for the target file, which returns a Worksheet object. I then returned that pointer and merged back with the original sample code path. All working now.
I believe that you may have a botched install. I have found that when my progIds are corrupted like that if I repair the installation that it will register that class.
Though my question back to you is, why are you trying to create a sheet object? Seems like you can get one from off of a Workbook object. In fact I feel this is probably what you'll need to do anyway.