You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: Ribbon/Readme.md
+99Lines changed: 99 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,6 +4,8 @@ This sample shows how to add a ribbon UI extension with the Excel-DNA add-in, an
4
4
5
5
## Initial setup
6
6
7
+
The initial setup will create a new add-in with a simple test function (it's a useful indicator to show that the add-in is loaded into the Excel session).
8
+
7
9
1. Create new Class Library project.
8
10
2. Install `ExcelDna.AddIn` package.
9
11
3. Add a small test function:
@@ -25,6 +27,8 @@ namespace Ribbon
25
27
26
28
## Add the ribbon controller
27
29
30
+
Next we add a class to implement the ribbon UI extension, with a simple button.
31
+
28
32
1. Add a reference to the `System.Windows.Forms` assembly (we'll use that for showing our messages).
29
33
30
34
2. Add a new class for the ribbon controller (maybe `RibbonController.cs`), with this code for a button and handler:
@@ -103,3 +107,98 @@ Other ribbon-related resources:
103
107
*[Ron de Bruin's Excel Tips](http://www.rondebruin.nl/win/s2/win003.htm)
In this step we add access to the Excel COM object model, to show how C# code can use the familiar object model to manipulate Excel.
113
+
114
+
1. Add a reference to the Primary Interop Assembly (PIA) for Excel. The easiest way to do this is to install the `ExcelDna.Interop` NuGet package. This will install the interop assemblies that correspond to Excel 2010, so are suitable for add-ins that support Excel 2010 and later.
3. Update the ribbon handler to call our data writer:
167
+
168
+
```cs
169
+
publicvoidOnButtonPressed(IRibbonControlcontrol)
170
+
{
171
+
MessageBox.Show("Hello from control "+control.Id);
172
+
DataWriter.WriteData();
173
+
}
174
+
```
175
+
176
+
4. Press F5 to load and press the ribbon button to run the `WriteData` code.
177
+
178
+
### Getting the root `Application` object
179
+
180
+
A key call in the above code is to retrieve the root `Application` object that matches the Excel instance that is hosting the add-in. We call `ExcelDnaUtil.Application`, which returns an object that is always the correct `Application` COM object. Code that attempts to get the `Application` object in other ways, e.g. by calling `new Application()` might work in some cases, but there is a danger that the Excel instance returned is not that instance hosting the add-in.
181
+
182
+
Once the root `Application` object is retrieved, the object model is accessed normally as it would be from VBA.
183
+
184
+
* Don't confuse the types `Microsoft.Office.Interop.Excel.Application` that we use here with the WinForms type `System.Windows.Forms.Application`. You might use a namespace alias to distinguish these in your code.
185
+
186
+
### Interop assembly versions
187
+
188
+
Each version of Excel adds some extensions to the object model (and rarely, but sometimes removes some parts). The changes might be entire classes and interfaces, methods on an interface or parameters or a method. Most add-ins are expected to run on different Excel versions, so some care is needed to make sure only object models features available on all the target versions are used.
189
+
190
+
The simplest approach is to pick a minimum Excel version to support, and use the COM object model definitions (PIA asemblies) from that version. Such code will work against the chosen version, and any any other version (newer or older) that implements the same parts of the object model. Since most Excel versions only add to the object model, this means that add-in will work correctly with newer versions too. This is similar to developing a VBA extension on Excel 2010, which might then fail on older versions if the VBA code uses methods not available on the running version.
191
+
192
+
In this example we've installed the 'ExcelDna.Interop' NuGet package, which includes the interop assemblies for Excel 2010. This means features added in Excel 2013 and later will not be shown in the object model IntelliSense, ensuring that the add-in only uses features available on the minimum version.
193
+
194
+
### Correct COM / .NET interop usage
195
+
196
+
There is a lot of misinformation on the web about using the COM object model from .NET.
197
+
198
+
* To ensure that the Excel process always correctly exits, Excel add-ins should *only call the Excel COM object model from the main Excel thread, in a macro of callback context*. Never attempt to access the COM object model from multiple threads - since the Excel COM object model is single-threaded (technically a Single-Threaded Apartment) there can be no performance benefit in trying to access Excel from multiple threads.
199
+
200
+
* An Excel add-in should never call `Marshal.ReleaseComObject(...)` or `Marshal.FinalReleaseComObject(...)` when doing Excel interop. It is a confusing anti-pattern, but any information about this, including from Microsoft, that indicates one should manually release COM references from .NET is incorrect. The .NET runtime and garbage collector correctly keep track of and clean up COM references.
201
+
202
+
* Any guidance that mentions 'double-dots' is misleading. Sometimes this indicates that expressions calling into the object model should not chain object model access, i.e. to avoid code like `myWorkbook.Sheets[1].Range["A1"].Value = "abc". Such code is fine - just ignore any 'two dots' guidance.
203
+
204
+
* I've posted some more details on these issues (in the context of automating Excel from another application) in a [Stack Overflow answer](http://stackoverflow.com/a/38111294/44264).
0 commit comments