<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">Excel Programming  </title><subtitle type="html">An Excel Programmability blog by Gabhan Berry</subtitle><id>http://blogs.msdn.com/gabhan_berry/atom.xml</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/gabhan_berry/default.aspx" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/gabhan_berry/atom.xml" /><generator uri="http://communityserver.org" version="2.1.61025.2">Community Server</generator><updated>2008-02-05T20:02:00Z</updated><entry><title>Custom Task Panes</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/gabhan_berry/archive/2008/08/13/custom-task-panes.aspx" /><id>http://blogs.msdn.com/gabhan_berry/archive/2008/08/13/custom-task-panes.aspx</id><published>2008-08-14T01:29:00Z</published><updated>2008-08-14T01:29:00Z</updated><content type="html">&lt;P&gt;A Custom Task Pane (CTP) is a user interface component&amp;nbsp;in Office which is used to provide a non-modal window. Some of Excel's features, such as the PivotTable field list and Reseach tool, use CTPs.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;CTPs are exposed to customer extensions via the Office extensibility COM libraries.&amp;nbsp;Any Excel developer can develop their own CTP and have it work just like the built-in CTPs. &lt;/P&gt;
&lt;P&gt;Despite what some people think,&amp;nbsp;you do not need&amp;nbsp;VSTO to build a CTP.&lt;/P&gt;
&lt;P&gt;In this post I will develop an Excel feature called: &lt;EM&gt;annotations&lt;/EM&gt;. Annotations (as implemented here) are basically free-from textual comments that can be added to a workbook. They are added into the file but are not displayed on the grid. You can use them to store notes or commentary&amp;nbsp;in&amp;nbsp;the workbook. They are displayed and edited in a Custom Task Pane as shown below. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/8862220/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/8862220/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;The annotations&amp;nbsp;are stored within the CustomXMLParts collection of the workbook. CustomXMLParts are a new feature in Excel 2007 which enable Excel developers to store their own XML within a workbook. I will cover CustomXMLParts in my next post. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;What are Custom Task Panes?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;A CTP is a simple window that contains an ActiveX control. Excel manages the CTP window (creates it, destroys it, handles its window messages etc.) and the ActiveX control&amp;nbsp;provides all the features. The CTP is really just a container, but a container&amp;nbsp;that is nicely integrated into&amp;nbsp;Excel.&amp;nbsp;A CTP can be docked&amp;nbsp;inside&amp;nbsp;the main Excel&amp;nbsp;window or can float. The user can resize it, move it&amp;nbsp;and close it and all of this is handled for us by Excel. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Building a Custom Task Pane&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Creating a CTP itself is very simple. CTP functionality is provided&amp;nbsp;via a COM interface called &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ICustomTaskPaneConsumer&lt;/SPAN&gt;&lt;/FONT&gt;. From a .NET point of view, this interface is implemented&amp;nbsp;in &lt;FONT face="Courier New"&gt;Microsoft.Office.Core&lt;/FONT&gt;.&amp;nbsp;When Excel loads our COM addin it performs a &lt;FONT face="Courier New"&gt;QueryInterface &lt;/FONT&gt;call to see whether or not our addin implements the &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;ICustomTaskPaneConsumer &lt;/FONT&gt;&lt;/SPAN&gt;interface.&amp;nbsp;If&amp;nbsp;it does, Excel calls the &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;ICustomTaskPaneConsumer&lt;/FONT&gt;&lt;/SPAN&gt;.&lt;FONT face="Courier New"&gt;CTPFactoryAvailable &lt;/FONT&gt;method. It is&amp;nbsp;in this&amp;nbsp;method that our addin creates the CTP. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Let's take a look at the code.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;public&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: blue"&gt;class&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;Connect&lt;/SPAN&gt; : &lt;SPAN style="COLOR: #2b91af"&gt;Object&lt;/SPAN&gt;, Extensibility.&lt;SPAN style="COLOR: #2b91af"&gt;IDTExtensibility2&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;IRibbonExtensibility&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;ICustomTaskPaneConsumer&lt;/SPAN&gt; {&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp; public&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; CTPFactoryAvailable(&lt;SPAN style="COLOR: #2b91af"&gt;ICTPFactory&lt;/SPAN&gt; CTPFactoryInst) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;_ctpFactory = CTPFactoryInst;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;CustomTaskPane&lt;/SPAN&gt; ctp = _ctpFactory.CreateCTP(&lt;SPAN style="COLOR: #a31515"&gt;"ExcelExtensions.AnnotationsCtrl"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #a31515"&gt;"Annotations"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value);&lt;/SPAN&gt;&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _annotationsExt = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;AnnotationsExtension&lt;/SPAN&gt;(ctp, _application);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;The &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;Connect&lt;/FONT&gt;&lt;/SPAN&gt; class implements the &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ICustomTaskPaneConsumer&lt;/SPAN&gt; &lt;/FONT&gt;interface. Its implementation of the &lt;FONT face="Courier New"&gt;CTPFactoryAvailable&lt;/FONT&gt; method does two things. Firstly, it stores the &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;ICTPFactory&lt;/FONT&gt;&lt;/SPAN&gt; object passed to it by Excel and secondly it creates a CTP using the &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;ICTPFactory&lt;/FONT&gt;&lt;/SPAN&gt;.&lt;FONT face="Courier New"&gt;CreateCTP&lt;/FONT&gt; method. The first parameter to the &lt;FONT face="Courier New"&gt;CreateCTP&lt;/FONT&gt; method is the ProgId of the ActiveX control that the CTP is to host. The CTP will create an instance of this ActiveX control and place it within the CTP window.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="Courier New"&gt;CreateCTP&lt;/FONT&gt; returns a &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;CustomTaskPane&lt;/FONT&gt;&lt;/SPAN&gt; object which we store for later use. The &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;CustomTaskPane&lt;/FONT&gt;&lt;/SPAN&gt; object is how our addin can interact with the CTP window itself. In the example above, we store the &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;CustomTaskPane&lt;/FONT&gt;&lt;/SPAN&gt; object inside an&amp;nbsp; &lt;SPAN style="COLOR: #2b91af"&gt;AnnotationsExtension&lt;/SPAN&gt;&amp;nbsp;object but we can actually store it anywhere we like. The &lt;SPAN style="COLOR: #2b91af"&gt;AnnotationsExtension &lt;/SPAN&gt;object is a class inside our addin - the details of this class&amp;nbsp;will be&amp;nbsp;covered in the next post - for now, all we need to know is that it is a conceptual wrapper of our CTP. &lt;/P&gt;
&lt;P mce_keep="true"&gt;So, the basic workflow in creating a Custom Task Pane is as follows:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/8862191/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/8862191/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Displaying a Custom Task Pane&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;So far we have created a CTP. We have a reference to it and the CTP knows which ActiveX control it is hosting. However, we need to explcitly display the CTP in order for it to be visible. &lt;/P&gt;
&lt;P mce_keep="true"&gt;We do this via the &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;CustomTaskPane&lt;/FONT&gt;&lt;/SPAN&gt;.&lt;FONT face="Courier New"&gt;Visible&lt;/FONT&gt; property. Setting this property to true or false will display or hide the CTP (notice that the CTP is hidden - not destroyed). &lt;/P&gt;
&lt;P mce_keep="true"&gt;This makes sense because we'd typically want to show or hide our CTP based on some user action, like a user clicking a button on the Ribbon. In this example we'll add an Annotations button onto the Review tab of the Ribbon. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;tab&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;idMso&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt;TabReview&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-tab-count: 4"&gt;&amp;nbsp; &lt;/SPAN&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;group&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;id&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt;AnnotationsGroup&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;label&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;Notes&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;insertBeforeMso&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;GroupComments&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-tab-count: 5"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;toggleButton&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;id&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt;AnnotationsButton&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;onAction&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;OnAnnotationsClicked&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;label&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;Annotations&lt;/SPAN&gt;"&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-tab-count: 7"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;imageMso&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt;ExchangeFolder&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;supertip&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt;Add new and view existing annotations.&lt;/SPAN&gt;" &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;size&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt;large&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;/&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-tab-count: 4"&gt;&amp;nbsp; &lt;/SPAN&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;group&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #a31515; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;tab&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;
&lt;P mce_keep="true"&gt;We then implement the OnAnnotationsClicked event handler in our COM addin. &lt;/P&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt;&lt;FONT color=#000000&gt; OnAnnotationsClicked(&lt;/FONT&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IRibbonControl&lt;/SPAN&gt;&lt;FONT color=#000000&gt; Control, &lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;bool&lt;/SPAN&gt;&lt;FONT color=#000000&gt; IsPressed) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;_annotationsExt.Visible = IsPressed;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;}&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P mce_keep="true"&gt;
&lt;P mce_keep="true"&gt;Because we added a toggleButton control to the Ribbon, our event handler gets passed a boolean which indicates whether the toggleButton is pressed or not. All we need to do is set the Visible property of the CTP equal to this value.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Writing the ActiveX Control&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;We now have enough code to create and display a CTP when a button on the Ribbon is pressed. The final bit (and the harder bit) is writing the ActiveX control ... this is the thing that actually implements our custom features.&lt;/P&gt;
&lt;P mce_keep="true"&gt;In this example, our ActiveX control reads and write annotations to the CustomXMLParts collection of the active workbook. I'll be covering the CustomXMLParts collection, how it is stored&amp;nbsp;in the new Office XML file formats and how the ActiveX control works next time.&lt;/P&gt;
&lt;P mce_keep="true"&gt;What's great is that the CTP&amp;nbsp;can host any ActiveX control. So even though the CTP itself is native code, we can&amp;nbsp;write our ActiveX control in .NET code and it all works. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Summary&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;To create a Custom Task Pane using managed code:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Add a reference to Microsoft.Office.Core;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Implement the &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ICustomTaskPaneConsumer&lt;/SPAN&gt; &lt;/FONT&gt;interface on your addin class (i.e., the&amp;nbsp;&lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Connect&lt;/SPAN&gt; &lt;/FONT&gt;class);&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;In your implementation of &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ICustomTaskPaneConsumer&lt;/SPAN&gt;&lt;/FONT&gt;.&lt;FONT face="Courier New"&gt;CTPFactoryAvailable &lt;/FONT&gt;call &lt;FONT face="Courier New"&gt;CreateCTP &lt;/FONT&gt;on the supplied &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;ICTPFactory &lt;/FONT&gt;&lt;/SPAN&gt;object;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;In the call to &lt;FONT face="Courier New"&gt;CreateCTP&lt;/FONT&gt;, specify the&amp;nbsp;ProgId of the ActiveX control you want to host in the CTP;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Store&amp;nbsp;the&amp;nbsp;&lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;CustomTaskPane &lt;/FONT&gt;&lt;/SPAN&gt;object returned from &lt;FONT face="Courier New"&gt;CreateCTP &lt;/FONT&gt;and toggle its &lt;FONT face="Courier New"&gt;Visible &lt;/FONT&gt;property to show and hide the CTP as and when required;&amp;nbsp;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Links&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;The following link gives more information on creating Custom Task Panes:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/aa942864.aspx"&gt;http://msdn.microsoft.com/en-us/library/aa942864.aspx&lt;/A&gt;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Next Time ...&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;We'll take a look at how the Annotations ActiveX control uses the CustomXMLParts collection to store the annotations entered by the user. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8861702" width="1" height="1"&gt;</content><author><name>Gabhan Berry</name><uri>http://blogs.msdn.com/members/Gabhan+Berry.aspx</uri></author><category term="Addins" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/Addins/default.aspx" /><category term="C#" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/C_2300_/default.aspx" /><category term=".NET" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/.NET/default.aspx" /><category term="Ribbon" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/Ribbon/default.aspx" /><category term="OpenXML" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/OpenXML/default.aspx" /></entry><entry><title>How to code a .NET RefEdit Control</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/gabhan_berry/archive/2008/06/12/net-refedit-control.aspx" /><id>http://blogs.msdn.com/gabhan_berry/archive/2008/06/12/net-refedit-control.aspx</id><published>2008-06-12T06:02:00Z</published><updated>2008-06-12T06:02:00Z</updated><content type="html">&lt;P&gt;One of the controls frequently used by Excel is the reference edit box. This control is used to gather a range address from the user. The user specifies the range either by typing in&amp;nbsp;its address or by using the mouse and clicking on the actual cells they want to use. &lt;/P&gt;
&lt;P&gt;Here's a screenshot of&amp;nbsp;the inbuilt reference edit box:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/8592564/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/8592564/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Whenever the user is required to specify a range, using&amp;nbsp;the reference edit box is my preferred way to gather the address from the user because it enables (what I call) visual selection of ranges.&amp;nbsp;Range addresses can be tedious to work with whereas&amp;nbsp;visually clicking on the cells you want is a much easier and more efficient way of working. &amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Custom solutions can also use visual range selection because&amp;nbsp;Excel ships a control called the RefEdit control. This control is implemented&amp;nbsp;in&amp;nbsp;REFEDIT.DLL&amp;nbsp;located in the Office folder (on my laptop this is: C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE12) and mimics the inbuilt reference edit control.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Well that's the good news ... now the bad: the REFEDIT.DLL cannot be used from managed code. In fact, it can only be used from VBA. Years ago, that wasn't a problem because most solutions were VBA based. However, these days we live in a .NET world and more and more solutions are being written in managed code.&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;So, what are the options if we want to use the RefEdit control from managed code? &lt;/P&gt;
&lt;P mce_keep="true"&gt;The way I see it, there are three options. Firstly, we could write an XLA containing a VBA userform on which we place the RefEdit control. We would then have to link the managed code and the VBA userform via macros somehow. The downsides of this option are that we&amp;nbsp; create a mixed code solution i.e., we have some VBA and some managed code. This may or may not be an issue for us. &lt;/P&gt;
&lt;P mce_keep="true"&gt;The second option is to buy a commercial RefEdit control that can be used&amp;nbsp;by .NET WinForms. Actually, I don't know if such a thing exists but let's assume that it does. &lt;/P&gt;
&lt;P mce_keep="true"&gt;The third option is to write a managed code RefEdit control from scratch. This option is probably the most work and might be quite hard. However, I decided to give it a go... &lt;/P&gt;
&lt;P mce_keep="true"&gt;In this post, I present a managed code RefEdit control written in C#. I have implemented the control as a .NET UserControl which can be added into&amp;nbsp;the Visual Studio toolbox and dragged and dropped onto any WinForm just like any other .NET control.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The control I present does not behave &lt;EM&gt;exactly&lt;/EM&gt; like Excel's reference edit boxes but I think it behaves close enough that most people wouldn't notice&amp;nbsp;the difference.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Here's a screenshot of the control in action:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/8594013/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/8594013/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;This example uses the&amp;nbsp;managed code&amp;nbsp;addin I presented in&amp;nbsp;a previous post (&lt;A class="" href="http://blogs.msdn.com/gabhan_berry/archive/2008/03/10/analysing-column-data-using-c-and-drawing-custom-bar-charts.aspx" mce_href="http://blogs.msdn.com/gabhan_berry/archive/2008/03/10/analysing-column-data-using-c-and-drawing-custom-bar-charts.aspx"&gt;here&lt;/A&gt;) but the control can be used on any WinForm.&lt;/P&gt;
&lt;P mce_keep="true"&gt;You are free to download the control and use it in your solutions. It is &lt;STRONG&gt;totally free&lt;/STRONG&gt; (in all senses of the word) and you can take the code and modify it without restriction. All I ask is that you let me know if you improve it or find any bugs so that I can incorporate those improvements for the benefit of the community.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Note: The RefEdit control also uses the&amp;nbsp;&lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ExcelUtility&lt;/SPAN&gt; &lt;/FONT&gt;class I published previously in &lt;A class="" href="http://blogs.msdn.com/gabhan_berry/archive/2008/02/06/excel-s-optional-parameters-and-missing-value-a-c-workaround.aspx" mce_href="http://blogs.msdn.com/gabhan_berry/archive/2008/02/06/excel-s-optional-parameters-and-missing-value-a-c-workaround.aspx"&gt;&lt;FONT color=#0000cc&gt;this post&lt;/FONT&gt;&lt;/A&gt;.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;How to code a RefEdit Control in C#&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Let's first think a bit about the behaviour of the RefEdit control. It does some fancy things in very subtle ways. It's one of those wonderful UI concepts that we use everyday without even thinking about its complexities. &lt;/P&gt;
&lt;P mce_keep="true"&gt;When we click on the button in the RefEdit control, the window on which the RefEdit control resides is minimised and all controls on the window are not displayed. Clicking on the button again restores the window to its original state.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/8593992/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/8593992/original.aspx"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;The other feature to note is how the visual selection works. When the&amp;nbsp;text box&amp;nbsp;in the RefEdit control has focus,&amp;nbsp;the address of the selected cells in Excel is displayed. Even if multiple, discrete ranges are selected the addresses&amp;nbsp;are displayed. The user can even&amp;nbsp;change&amp;nbsp;sheets and select ranges on different sheets. This all takes place while the window containing the RefEdit control is still visible but is in its minimised state and all the time the addresses of all the selected ranges are displayed in the RefEdit control.&lt;/P&gt;
&lt;P mce_keep="true"&gt;These two features are the killer features of the RefEdit control. If we can code these features then we are well on our way to our goal of having a managed code RefEdit control.&lt;/P&gt;
&lt;P mce_keep="true"&gt;So, let's take a look at how we do this.&lt;/P&gt;
&lt;P mce_keep="true"&gt;First, we need to have a function that can minimise its parent window and hide all controls on the window except the RefEdit control. Also, this function needs to remember the window's previous state and restore the window to that state once the user has selected their range.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;protected&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; ResizeParent() {&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Form&lt;/SPAN&gt; parentForm = (&lt;SPAN style="COLOR: #2b91af"&gt;Form&lt;/SPAN&gt;)Parent;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;foreach&lt;/SPAN&gt; (&lt;SPAN style="COLOR: #2b91af"&gt;Control&lt;/SPAN&gt; c &lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt; parentForm.Controls)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;c.Visible = _state.ParentMinimised;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;Visible = &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt; (!_state.ParentMinimised) {&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;_state.ParentClientSize = parentForm.ClientSize;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;_state.PrevX = Left;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;_state.PrevY = Top;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;_state.Anchor = Anchor;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;Anchor = &lt;SPAN style="COLOR: #2b91af"&gt;AnchorStyles&lt;/SPAN&gt;.None;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;parentForm.ClientSize = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;Size&lt;/SPAN&gt;(Width, Height); &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;Left = 0;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;Top = 0;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;_state.ParentPrevBorder = parentForm.FormBorderStyle;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;parentForm.FormBorderStyle = &lt;SPAN style="COLOR: #2b91af"&gt;FormBorderStyle&lt;/SPAN&gt;.FixedDialog;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;_state.ParentControlBox = parentForm.ControlBox;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;parentForm.ControlBox = &lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;else&lt;/SPAN&gt; {&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;parentForm.ClientSize = _state.ParentClientSize;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;Anchor = _state.Anchor;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;Left = _state.PrevX;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;Top = _state.PrevY;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;parentForm.FormBorderStyle = _state.ParentPrevBorder;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;parentForm.ControlBox = _state.ParentControlBox;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;
&lt;P mce_keep="true"&gt;Notice that the first line of code casts the control's&amp;nbsp;&lt;FONT face="Courier New"&gt;Parent&lt;/FONT&gt; to a &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;Form&lt;/FONT&gt;&lt;/SPAN&gt; object. This is our first limitation. If this cast fails then our control won't work. Why would&amp;nbsp;the cast fail? It would fail if the parent is not a &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;Form&lt;/FONT&gt;&lt;/SPAN&gt;. This means that our RefEdit control's direct parent must be a &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;Form&lt;/FONT&gt;&lt;/SPAN&gt;. In other words, we can't place our RefEdit control within another control (such as a group box); it must be placed directly on a &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;Form.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;The &lt;FONT face="Courier New"&gt;_state&lt;/FONT&gt; object is an instance of the following struct: &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;struct&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: #2b91af"&gt;RefEditState&lt;/SPAN&gt; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;Size&lt;/SPAN&gt; ParentClientSize;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;bool&lt;/SPAN&gt; ParentMinimised;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; PrevX;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; PrevY;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;FormBorderStyle&lt;/SPAN&gt; ParentPrevBorder;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;bool&lt;/SPAN&gt; ParentControlBox;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;AnchorStyles&lt;/SPAN&gt; Anchor;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Worksheet&lt;/SPAN&gt; Sheet;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;bool&lt;/SPAN&gt; UseSheetAddress;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;We use this struct to store state information&amp;nbsp;while we are minimising the parent window.&amp;nbsp;Any property of the parent window that we change during the minimising we first save in the &lt;FONT face="Courier New"&gt;_state&lt;/FONT&gt; object. If the window is to be minimised (this happens when the user clicks on the button in the RefEdit control), all controls except the RefEdit control are hidden and the window is resized so that it is fits snuggly around the RefEdit control. That is, the window is made to look like this:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/8598696/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/8598696/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;When the window is to be restored (when the user clicks on the RefEdit button again) we re-apply the settings stored in &lt;FONT face="Courier New"&gt;_state&lt;/FONT&gt;.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Updating the RefEdit Control&amp;nbsp;with the Selected Range&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;The RefEdit control now resizes and restores&amp;nbsp;its parent window whenever the user clicks on the button. Now we need to display the address of the ranges the user selects in Excel, while the user&amp;nbsp;is selecting them. &lt;/P&gt;
&lt;P mce_keep="true"&gt;So, if the user clicks $A$1 the RefEdit should display $A$1 in its text box. If the user&amp;nbsp;selects the range $A$1:$B$3 the RefEdit should display $A$1:$B$3. Also, we want to support selecting multiple ranges. So, if the user selects $A$1 and $F$3 the RefEdit control should display $A$1,$F$3. &amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;We detect which ranges the user is selecting by sinking the&amp;nbsp;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;SheetSelectionChange&lt;/SPAN&gt;&amp;nbsp;event on the &lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Application&lt;/SPAN&gt;&lt;/SPAN&gt;&amp;nbsp;object. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;private&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; SinkEvents() {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp; _con.ExcelApp.SheetSelectionChange += &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; Excel.&lt;SPAN style="COLOR: #2b91af"&gt;AppEvents_SheetSelectionChangeEventHandler&lt;/SPAN&gt;(ExcelEvent_SheetSelectionChange);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp; _con.ExcelApp.SheetActivate += &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; Excel.&lt;SPAN style="COLOR: #2b91af"&gt;AppEvents_SheetActivateEventHandler&lt;/SPAN&gt;(ExcelEvent_SheetActivate);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;
&lt;P mce_keep="true"&gt;However, we don't want to always sink these events. We only want to sink them while the RefEdit is &lt;EM&gt;active&lt;/EM&gt;. By &lt;EM&gt;active&lt;/EM&gt; I mean the user has either clicked inside the RefEdit's text box or has clicked the RefEdit's button. In other words, we only sink these events while the user is using the RefEdit control. &lt;/P&gt;
&lt;P mce_keep="true"&gt;We trap the Enter event of the RefEdit's address textbox and sink the Excel events whenever this event fires. We also save the active sheet in the _state object.&amp;nbsp;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; _addressTxt_Enter(&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt; sender, &lt;SPAN style="COLOR: #2b91af"&gt;EventArgs&lt;/SPAN&gt; e) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;SinkEvents();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt; (_state.Sheet == &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;_state.Sheet = &lt;SPAN style="COLOR: #2b91af"&gt;ExcelUtility&lt;/SPAN&gt;.ApplicationInvoke&amp;lt;Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Worksheet&lt;/SPAN&gt;&amp;gt;(_con.ExcelApp, &lt;SPAN style="COLOR: #a31515"&gt;"ActiveSheet"&lt;/SPAN&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;We detach from the events when the stops using the RefEdit control. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;private&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; UnsinkEvents() {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;_con.ExcelApp.SheetSelectionChange -= ExcelEvent_SheetSelectionChange;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;_con.ExcelApp.SheetActivate -= ExcelEvent_SheetActivate;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;private&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; _addressTxt_Leave(&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt; sender, &lt;SPAN style="COLOR: #2b91af"&gt;EventArgs&lt;/SPAN&gt; e) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp; UnsinkEvents();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;/SPAN&gt;Notice that we also sink the &lt;FONT face="Courier New"&gt;SheetActivate &lt;/FONT&gt;event. We do this because the RefEdit control allows users to select ranges on any sheet; not just the sheet that was active at the time the RefEdit was displayed. Therefore, if the user selects a range&amp;nbsp;on a different sheet we need to include the sheet name in the address of that range. For example, if Sheet1 is active when the RefEdit control is displayed but the user selects&amp;nbsp;$A$1 on Sheet2 then the RefEdit control needs to display 'Sheet2'!$A$1 ... not $A$1. &lt;/P&gt;
&lt;P mce_keep="true"&gt;One way of solving this problem is to make the RefEdit control&amp;nbsp;always include sheet names in range addresses but this makes for&amp;nbsp;long, messy addresses and&amp;nbsp;Excel's reference edit boxes don't behave like that ... so neither should our RefEdit control. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Thus, we only want to include sheet names in the addresses if we have to. If we don't have to then we should omit them.&lt;/P&gt;
&lt;P mce_keep="true"&gt;And that's why we sink the &lt;FONT face="Courier New"&gt;SheetActivate &lt;/FONT&gt;event. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Here's the code that runs when the &lt;FONT face="Courier New"&gt;SheetActivate &lt;/FONT&gt;event and the&amp;nbsp;&lt;FONT face="Courier New"&gt;SheetSelectionChange&lt;/FONT&gt; event&amp;nbsp;fire: &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;void&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; ExcelEvent_SheetSelectionChange(&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt; Sh, Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Range&lt;/SPAN&gt; Target) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; address = &lt;SPAN style="COLOR: #a31515"&gt;""&lt;/SPAN&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;try&lt;/SPAN&gt; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Worksheet&lt;/SPAN&gt; sheet = (Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Worksheet&lt;/SPAN&gt;)Sh;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt; (_state.UseSheetAddress) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;foreach&lt;/SPAN&gt; (&lt;SPAN style="COLOR: #2b91af"&gt;Object&lt;/SPAN&gt; obj &lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt; Target.Areas) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt; (address.Length &amp;gt; 0)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;address += &lt;SPAN style="COLOR: #a31515"&gt;","&lt;/SPAN&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Range&lt;/SPAN&gt; rng = (Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Range&lt;/SPAN&gt;)obj;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;address += &lt;SPAN style="COLOR: #a31515"&gt;"'"&lt;/SPAN&gt; + rng.Worksheet.Name + &lt;SPAN style="COLOR: #a31515"&gt;"'!"&lt;/SPAN&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;address += &lt;SPAN style="COLOR: #2b91af"&gt;ExcelUtility&lt;/SPAN&gt;.RangeInvoke&amp;lt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&amp;gt;(rng, &lt;SPAN style="COLOR: #a31515"&gt;"Address"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;, Excel.&lt;SPAN style="COLOR: #2b91af"&gt;XlReferenceStyle&lt;/SPAN&gt;.xlA1);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;else&lt;/SPAN&gt; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;address += &lt;SPAN style="COLOR: #2b91af"&gt;ExcelUtility&lt;/SPAN&gt;.RangeInvoke&amp;lt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&amp;gt;(Target, &lt;SPAN style="COLOR: #a31515"&gt;"Address"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;, Excel.&lt;SPAN style="COLOR: #2b91af"&gt;XlReferenceStyle&lt;/SPAN&gt;.xlA1);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;_addressTxt.Text = address;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;catch&lt;/SPAN&gt; (&lt;SPAN style="COLOR: #2b91af"&gt;Exception&lt;/SPAN&gt;) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;void&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; ExcelEvent_SheetActivate(&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt; Sh) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Worksheet&lt;/SPAN&gt; sheet = (Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Worksheet&lt;/SPAN&gt;)Sh;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt; (!_state.UseSheetAddress)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;_state.UseSheetAddress = sheet.Name != _state.Sheet.Name;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;
&lt;P mce_keep="true"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;/SPAN&gt;&lt;/P&gt;As the user selects ranges Excel fires the &lt;FONT face="Courier New"&gt;SheetSelectionChange&lt;/FONT&gt; event. If the&amp;nbsp;range that was selected is not on the sheet that was active when the RefEdit control was displayed we append the sheet name to the address, otherwise we don't. 
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Using the RefEdit Control on a WinForm&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;The RefEdit control is a normal .NET UserControl so it appears in the Visual Studio toolbox like every other UserControl. You can drag and drop it onto a WinForm as required. &lt;/P&gt;
&lt;P mce_keep="true"&gt;However, when we display a window which contains a RefEdit control&amp;nbsp;we have to&amp;nbsp;do so&amp;nbsp;in a certain, non-standard way in order for the RefEdit control to function properly. &lt;/P&gt;
&lt;P mce_keep="true"&gt;In order for the user to be able to select ranges in Excel while the window containing a RefEdit control is visible, the window must be non-modal. To display a non-modal window we normally invoke&amp;nbsp;its &lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Show()&lt;/SPAN&gt;method. We still do that, but we have to invoke the version of &lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Show()&lt;/SPAN&gt;that takes a native window handle as a parameter. This handle is the handle of the native window which is the parent window of the non-modal window. When we display a non-modal window in Excel we need to make sure that we tell the non-modal window that Excel is its parent window. This ensures that the window behaves properly (for example, when the user alt-tabs to another application).&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;The overloaded &lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Show()&lt;/SPAN&gt; method we use actually takes an &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;IWin32Window&lt;/FONT&gt;&lt;/SPAN&gt;. &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;IWin32Window&lt;/FONT&gt;&lt;/SPAN&gt; interface is defined in the .NET FCL and is used to wrap a native HWND.&amp;nbsp;We have to create a class that implements the &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;IWin32Window&lt;/FONT&gt;&lt;/SPAN&gt; interface and supply an instance of that class to the &lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Show()&lt;/SPAN&gt; method of the window containing a RefEdit control.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The following code defines a class, &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;NativeWindowWrapper&lt;/FONT&gt;&lt;/SPAN&gt;, that implements the &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;IWin32Window&lt;/FONT&gt;&lt;/SPAN&gt; interface.&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;class&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: #2b91af"&gt;NativeWindowWrapper&lt;/SPAN&gt; : &lt;SPAN style="COLOR: #2b91af"&gt;IWin32Window&lt;/SPAN&gt; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IntPtr&lt;/SPAN&gt; _handle;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; NativeWindowWrapper(&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; Hwnd) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;_handle = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;IntPtr&lt;/SPAN&gt;(Hwnd);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;IntPtr&lt;/SPAN&gt; Handle {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;get&lt;/SPAN&gt; { &lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt; _handle; }&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;We use this class when we display a window&amp;nbsp;containing a RefEdit control. We pass an instance of this class into the Show method&amp;nbsp;of the window containing the RefEdit control.&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;In the following example we are using the &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;ColumnAnalysisDisplayWindow&lt;/FONT&gt;&lt;/SPAN&gt; discussed in&amp;nbsp;a &lt;A class="" href="http://blogs.msdn.com/gabhan_berry/archive/2008/03/10/analysing-column-data-using-c-and-drawing-custom-bar-charts.aspx" mce_href="http://blogs.msdn.com/gabhan_berry/archive/2008/03/10/analysing-column-data-using-c-and-drawing-custom-bar-charts.aspx"&gt;previous blog&amp;nbsp;post&lt;/A&gt; ... but the idea is obvious: replace &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;ColumnAnalysisDisplayWindow&lt;/FONT&gt;&lt;/SPAN&gt; with your own window.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;protected&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; DisplayStatsWindow() {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ColumnAnalysisDisplayWindow&lt;/SPAN&gt; window = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;ColumnAnalysisDisplayWindow&lt;/SPAN&gt;();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;window.Show(&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;NativeWindowWrapper&lt;/SPAN&gt;(_connection.ExcelApp.Hwnd));&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt; 
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Summary&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;In this post we've talked&amp;nbsp;about how to code a RefEdit .NET control that mimics the behaviour of Excel's inbuilt reference edit box. I'm not claiming this is absolutely the best implementation we could produce, but I think it's not bad and is fairly easy to do. &lt;/P&gt;
&lt;P mce_keep="true"&gt;There are (no doubt) bugs in the code and situations where the control doesn't work that well. As I encounter and fix these prolbems I'll post updated versions of the control. If you encounter a problem, feel free to drop me a line and tell me about it.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The following points summarise this post:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;The RefEdit control mimcs Excel's reference edit controls by enabling&amp;nbsp;the user to visually select ranges;&lt;/DIV&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;The control does not behave &lt;EM&gt;exactly&lt;/EM&gt; like&amp;nbsp;Excel's reference edit boxes but is fairly close;&amp;nbsp;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;The control is&amp;nbsp;implemented as a&amp;nbsp;.NET UserControl;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;The control requires:&lt;/DIV&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;A reference to the Excel 2007 PIA;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;The ExcelUtility class defined in my ExcelExtensions COM addin (see below);&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Windows that contain an instance of the RefEdit control have to be displayed non-modally;&lt;/DIV&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;And Excel's HWND must be specified as the native owner of the containing window;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Downloading the source code&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;I have updated my ExcelExtensions addin to include the RefEdit control. &lt;/P&gt;
&lt;P mce_keep="true"&gt;All the source code is included in the ExcelExtensions download &lt;A class="" href="http://code.msdn.microsoft.com/ExcelExtensions" mce_href="http://code.msdn.microsoft.com/ExcelExtensions"&gt;found here&lt;/A&gt;. &lt;/P&gt;
&lt;P mce_keep="true"&gt;There are two downloads on the &lt;STRONG&gt;Downloads&lt;/STRONG&gt; tab. These are: &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;ExcelExtensionsSrc.zip&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;ExcelExtensions.msi&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;ExcelExtensionsSrc.zip contains the complete source code and ExcelExtensions.msi is the set up program. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8592561" width="1" height="1"&gt;</content><author><name>Gabhan Berry</name><uri>http://blogs.msdn.com/members/Gabhan+Berry.aspx</uri></author><category term="Addins" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/Addins/default.aspx" /><category term="C#" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/C_2300_/default.aspx" /><category term=".NET" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/.NET/default.aspx" /></entry><entry><title>Upcoming Topics</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/gabhan_berry/archive/2008/05/28/upcoming-topics.aspx" /><id>http://blogs.msdn.com/gabhan_berry/archive/2008/05/28/upcoming-topics.aspx</id><published>2008-05-28T03:39:00Z</published><updated>2008-05-28T03:39:00Z</updated><content type="html">&lt;P&gt;I know that posts have been few and far between (ok ..non-existant) this month. I hope this isn't something&amp;nbsp;that will be repeated ...&amp;nbsp;this month has just been &lt;STRONG&gt;crazy&lt;/STRONG&gt; busy with deadlines&amp;nbsp;(I'm sure you know that feeling...)&lt;/P&gt;
&lt;P&gt;Anyway,&amp;nbsp;I have a healthy backlog of&amp;nbsp;topics that I want to&amp;nbsp;blog about over the summer:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Multi-threaded UDFs in Excel 2007;&lt;/LI&gt;
&lt;LI&gt;RefEdit control for COM addins&amp;nbsp;written in managed code;&lt;/LI&gt;
&lt;LI&gt;C API enhancements in Excel 2007;&lt;/LI&gt;
&lt;LI&gt;PivotTable stuff&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;I get &lt;STRONG&gt;lots&lt;/STRONG&gt; of questions about PivotTable programming so there is plenty I want to talk about here;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Ribbon customisation;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;I'm at TechEd next week and am hoping that the&amp;nbsp;flight time there will give me time to get started on some of these posts. &lt;/P&gt;
&lt;P&gt;Feel free to drop me a line if&amp;nbsp;there is&amp;nbsp;something you&amp;nbsp;would like&amp;nbsp;covered.&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8555699" width="1" height="1"&gt;</content><author><name>Gabhan Berry</name><uri>http://blogs.msdn.com/members/Gabhan+Berry.aspx</uri></author></entry><entry><title>Busy Times ... and a Note about my TechEd Sessions</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/gabhan_berry/archive/2008/04/26/busy-times-and-a-note-about-my-teched-sessions.aspx" /><id>http://blogs.msdn.com/gabhan_berry/archive/2008/04/26/busy-times-and-a-note-about-my-teched-sessions.aspx</id><published>2008-04-26T02:04:00Z</published><updated>2008-04-26T02:04:00Z</updated><content type="html">&lt;P&gt;Busy times&amp;nbsp;at Microsoft has meant that I've been slower than usual in posting recently. My current expectation is to&amp;nbsp;be over my heavy workload by about mid-June. I'll continue to post in the meantime; but at a slower pace.&lt;/P&gt;
&lt;P&gt;TechEd is being held in Orlando in June this year. There are a lot of very interesting sessions being held and the key note will be done by Bill Gates. If you can make it, I'd recommend coming along. You can find out more about TechEd &lt;A class="" href="http://www.microsoft.com/events/teched2008/default.mspx" mce_href="http://www.microsoft.com/events/teched2008/default.mspx"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;I have two speaking slots at this year's show: one in the Developer track and one in the IT Professional track.&lt;/P&gt;
&lt;P&gt;In the Developer session&amp;nbsp;I'll be talking about the improvements we made to XLLs in Excel 2007. In the IT Professional session I'll be talking about the Business Intelligence capabilities of Excel 2007 and Excel Services.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8424886" width="1" height="1"&gt;</content><author><name>Gabhan Berry</name><uri>http://blogs.msdn.com/members/Gabhan+Berry.aspx</uri></author><category term="BI" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/BI/default.aspx" /><category term="XLL" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/XLL/default.aspx" /><category term="TechEd" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/TechEd/default.aspx" /></entry><entry><title>Writing Custom Excel Worksheet Functions in C#</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/gabhan_berry/archive/2008/04/07/writing-custom-excel-worksheet-functions-in-c_2D00_sharp.aspx" /><id>http://blogs.msdn.com/gabhan_berry/archive/2008/04/07/writing-custom-excel-worksheet-functions-in-c_2D00_sharp.aspx</id><published>2008-04-07T14:00:00Z</published><updated>2008-04-07T14:00:00Z</updated><content type="html">&lt;P&gt;Writing our own, custom worksheet functions is a great way to extend Excel. Before Excel 2002 we developed custom functions by either writing them&amp;nbsp;using VBA inside an XLA&amp;nbsp;or&amp;nbsp;by using C/C++ inside an XLL. Excel 2002 introduced a new type of addin called an &lt;EM&gt;automation addin&lt;/EM&gt;. An automation addin enables&amp;nbsp;Excel to&amp;nbsp;call functions on COM objects&amp;nbsp;from cells on a worksheet. In other words,&amp;nbsp;it enabled us to call COM functions just as if they were&amp;nbsp;normal, built-in Excel functions.&lt;/P&gt;
&lt;P&gt;This opened up the world of custom worksheet functions to COM developers. So, now we can now write&amp;nbsp;custom functions in any COM language; including C#.&lt;/P&gt;
&lt;P&gt;In this article we'll&amp;nbsp;write a custom worksheet function in C# called UNIQUEVALUES.&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;What&amp;nbsp;will our&amp;nbsp;Custom Function Do?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;The UNIQUEVALUES function will return an array of the unique values in a specified range. For example, if the range A1:A5 contains the values Red, Yellow, Red, Blue, Yellow, then {=UNIQUEVALUES(A1:A5)} will return the array {Red, Yellow, Blue}. &lt;/P&gt;
&lt;P mce_keep="true"&gt;The function will also be able to cope with a mixture of numerical data and text data. So, if A1:A5 contains the values: Red, 1, 1, Red then&amp;nbsp;{=UNIQUEVALUES(A1:A5)} will return the array {Red, 1}.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Because UNIQUEVALUES is a worksheet function that references the source data, whenever the values in the source range change the function automatically extracts the new unique values from the range. So we know that the values returned from the function are always up-to-date (once the worksheet has calculated).&lt;/P&gt;
&lt;P mce_keep="true"&gt;Notice that the UNIQUEVALUES function returns an array. This means that we &lt;EM&gt;array enter&lt;/EM&gt; the funtion by pressing Ctrl-Shift-Enter rather than just Enter when we type the function into the worksheet. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Coding the UNIQUEVALUES Function&lt;/STRONG&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;There are two tasks we need to do in order to make a C# class's methods be callable as worksheet functions: &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Define our worksheet functions&amp;nbsp;in&amp;nbsp;the way Excel expects;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Add the Programmable key to the registry for our class's CLSID;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;The first&amp;nbsp;task seems intriguing: &lt;EM&gt;Define our worksheet functions&amp;nbsp;in&amp;nbsp;the way Excel expects&lt;/EM&gt;. What does that mean?&lt;/P&gt;
&lt;P mce_keep="true"&gt;Well, this is where we have to remember that Excel is speaking to our automation addin via COM. So&amp;nbsp;Excel expects to be able to use COM techniques&amp;nbsp;to discover and access our functions. Once we know what these COM techniques are, we can make sure that our C# class interoperates with COM in the appropriate way. &lt;/P&gt;
&lt;P mce_keep="true"&gt;When an automation addin is loaded, Excel needs to discover which functions that addin supports. For example, our automation addin&amp;nbsp;will have a UNIQUEVALUES function that we want to use in worksheets. How does Excel discover&amp;nbsp;that our addin&amp;nbsp;supports that function and how does it discover&amp;nbsp;information about the parameters of the function? &lt;/P&gt;
&lt;P mce_keep="true"&gt;Excel discovers this information using a COM interface called ITypeInfo. &lt;/P&gt;
&lt;P mce_keep="true"&gt;ITypeInfo&amp;nbsp;is&amp;nbsp;an interface that is&amp;nbsp;used to access metadata about a&amp;nbsp;COM type. It is similar &lt;EM&gt;in concept&lt;/EM&gt; to .NET reflection, but is very different in implemenation.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Excel uses ITypeInfo to discover the names and the parameter details of the functions&amp;nbsp;exposed by our automation addin. This is how Excel knows&amp;nbsp;to call our addin whenever it&amp;nbsp;comes across&amp;nbsp;a&amp;nbsp;call to UNIQUEVALUES.&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;But Excel will only query the default interface of our COM class. So we need to make sure that the functions we want to expose as worksheet functions are defined on the default interface of our class. &lt;/P&gt;
&lt;P mce_keep="true"&gt;There are two ways of doing this in C#:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;By specifying the &lt;SPAN style="FONT-SIZE: 10pt; COLOR: #2b91af; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;ClassInterfaceType&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;.AutoDual&lt;/SPAN&gt; attribute on our C# class;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;By defining our worksheet functions on a dedicated interface and using the &lt;SPAN style="FONT-SIZE: 10pt; COLOR: #2b91af; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;ComDefaultInterface &lt;/SPAN&gt;attribute to make that interface the default interface of our class;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;To understand what the &lt;SPAN style="FONT-SIZE: 10pt; COLOR: #2b91af; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;ClassInterfaceType&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;.AutoDual &lt;/SPAN&gt;attribute value does to our COM interface, we need to understand a little more about COM interfaces.&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;In COM,&amp;nbsp;the IDispatch interface enables clients to dynamically call your functions at runtime. Instead of the compiler checking that functions exist and that the parameters types match at compile-time, IDispatch enables clients to do so&amp;nbsp;at runtime. This enables&amp;nbsp;components&amp;nbsp;to be extremely loosely coupled. This type of function call is termed: &lt;EM&gt;late-bound&lt;/EM&gt;. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Support of IDispatch is optional. COM classes do not &lt;EM&gt;have&lt;/EM&gt; to support it. However, by default, C# classes support IDispatch. In fact (unless we specify otherwise)&amp;nbsp;the default interface created for a C# class is a dispatch interface.&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Why do we need to care about this? Well, since the default interface is a dispatch interface&amp;nbsp;our worksheet functions are not &lt;EM&gt;explicitly&lt;/EM&gt; defined on the interface and are therefore not discoverable by Excel.&amp;nbsp;So, even though our C# class may have a public function named UNIQUEVALUES Excel would not be able to call it.&lt;/P&gt;
&lt;P mce_keep="true"&gt;A &lt;EM&gt;dual&lt;/EM&gt; interface allows a dispatch interface to explicitly define custom functions in addition to those already defined&amp;nbsp;by IDispatch.&amp;nbsp;The &lt;SPAN style="FONT-SIZE: 10pt; COLOR: #2b91af; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;ClassInterfaceType&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;.AutoDual &lt;/SPAN&gt;attribute turns our COM interface into a dual interface. This effectively takes all public functions defined on our class&amp;nbsp;(including those inherited from base classes) and explicitly defines them on our COM interface which in turn&amp;nbsp;makes them&amp;nbsp;discoverable&amp;nbsp;by Excel.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Thus, an easy way of getting our C# class to define Excel worksheet functions is to simply mark the class with&amp;nbsp;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #2b91af; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;ClassInterfaceType&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;.AutoDual. &lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;However, there is a downside to doing this. All public functions on our class are then available as worksheet functions, including those inherited from System.Object. This isn't ideal. It would be better if we could have more control over what gets exposed to Excel and make sure that only the functions that are intended to be worksheet functions are actually discoverable by Excel. This is the reason I prefer not to use the &lt;SPAN style="FONT-SIZE: 10pt; COLOR: #2b91af; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;ClassInterfaceType&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;.AutoDual &lt;/SPAN&gt;attribute.&lt;/P&gt;
&lt;P mce_keep="true"&gt;(There is also a problem with COM versioning when using &lt;SPAN style="FONT-SIZE: 10pt; COLOR: #2b91af; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;ClassInterfaceType&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;.AutoDual &lt;/SPAN&gt;- but we won't cover that here).&lt;/P&gt;
&lt;P mce_keep="true"&gt;Instead, I prefer to define the worksheet functions on a dedicated interface and have my C# class implement that interface. &lt;/P&gt;
&lt;P mce_keep="true"&gt;So, let's define our worksheet function interface. We'll call it &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IFunctions&lt;/SPAN&gt;&lt;/FONT&gt;. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;public&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: blue"&gt;interface&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;IFunctions&lt;/SPAN&gt; {&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;FONT color=#000000&gt;&amp;nbsp; &lt;/FONT&gt;object&lt;/SPAN&gt;[,] UNIQUEVALUES(Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Range&lt;/SPAN&gt; TargetRange);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Notice that the UNIQUEVALUES function returns a 2-d array of objects. This array will contain the unique values extracted from the specified &lt;FONT face="Courier New"&gt;Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Range&lt;/SPAN&gt;&lt;/FONT&gt; object. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Next, we define our functions class and have it implement the &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IFunctions &lt;/SPAN&gt;&lt;/FONT&gt;interface. We also use the default attribute to specify that we want the IFunctions interface to be the class's default COM interface. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;[&lt;SPAN style="COLOR: #2b91af"&gt;ComDefaultInterface&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;IFunctions&lt;/SPAN&gt;))]&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;class&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;Functions&lt;/SPAN&gt; : &lt;SPAN style="COLOR: #2b91af"&gt;IFunctions&lt;/SPAN&gt; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[,] UNIQUEVALUES(Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Range&lt;/SPAN&gt; TargetRange) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; object&lt;/SPAN&gt;[,] values = TargetRange.get_Value(System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value) &lt;SPAN style="COLOR: blue"&gt;as&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[,];&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;&amp;gt; unqVals = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;&amp;gt;();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;foreach&lt;/SPAN&gt; (&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt; obj &lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt; values) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt; (!unqVals.Contains(obj))&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;unqVals.Add(obj);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[,] resVals = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[unqVals.Count, 1];&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; idx = 0; idx &amp;lt; resVals.Length; ++idx)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;resVals[idx, 0] = unqVals[idx];&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt; resVals;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;
&lt;P mce_keep="true"&gt;The algorithm for extracting the unique values is as follows (I confess that this may not be the optimal algorithm). &lt;/P&gt;
&lt;P mce_keep="true"&gt;We extract the values in the &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Range&lt;/SPAN&gt; &lt;/FONT&gt;object into a 2-d array of &lt;FONT face="Courier New" color=#0000ff&gt;object&lt;/FONT&gt;. Because the array contains &lt;FONT face="Courier New" color=#0000ff&gt;object&lt;/FONT&gt;, we can cope with both textual data and numerical data. Next, we iterate over the array and store each value that hasn't already occurred in a &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;&amp;gt;&lt;/FONT&gt;. We then allocate a new 2-d array of &lt;FONT face="Courier New" color=#0000ff&gt;object &lt;/FONT&gt;and copy the unique values from the &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;&amp;gt; &lt;/FONT&gt;into the new array. Finally, we return the new array to Excel.&lt;/P&gt;
&lt;P mce_keep="true"&gt;
&lt;P mce_keep="true"&gt;When we return an array from a UDF Excel handles serialising the array into the worksheet in the appropriate way (as long as the user array-entered the cell formula). This means that the dimensions of the array matter. The first dimension of the array is mapped to columns. So if we return an &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[3]&lt;/FONT&gt; then Excel interprets this as &lt;EM&gt;"three columns containing one row each"&lt;/EM&gt; and places the three values adjacent to each other (i.e., each one in a different column). If we return an &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[1,3]&lt;/FONT&gt;then Excel interprets this as &lt;EM&gt;"one column containing three rows"&lt;/EM&gt; and places each value &lt;EM&gt;beneath&lt;/EM&gt; each other (i.e., each one in a different row). &lt;/P&gt;
&lt;P mce_keep="true"&gt;So, it is very easy to return an array to Excel. All we have to do is set the correct array dimensions and let Excel handle copying the values from the to the appropriate cells in the worksheet. &lt;/P&gt;
&lt;P mce_keep="true"&gt;We'll talk more about how arrays&amp;nbsp;are used in Excel worksheet functions later in the article.&lt;/P&gt;
&lt;P mce_keep="true"&gt;If we stop coding here, we'll find that Excel still can't use our class. There is one final thing we need to do: &lt;EM&gt;set the class's Programmable key in the registry&lt;/EM&gt;.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The Programmable key indicates that a COM class exposes type information for its default interface.&amp;nbsp;The key is specified&amp;nbsp;under&amp;nbsp;the COM class's HKEY_CLASSES_ROOT\CLSID\{Guid} key (where {Guid} is the guid of the COM class).&lt;/P&gt;
&lt;P mce_keep="true"&gt;There is a convenient way to set this registry key from C#. There&amp;nbsp;exist two attributes called &lt;SPAN style="FONT-SIZE: 10pt; COLOR: #2b91af; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;ComRegisterFunctionAttribute &lt;/SPAN&gt;and &lt;SPAN style="FONT-SIZE: 10pt; COLOR: #2b91af; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;ComUnregisterFunctionAttribute&lt;/SPAN&gt;. These attributes are used to mark which functions COM should call&amp;nbsp;during the COM registration/unregistration process. So all we need to do is write a function that inserts the Programmable key during registration and removes it during unregistration.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;[&lt;SPAN style="COLOR: #2b91af"&gt;ComRegisterFunctionAttribute&lt;/SPAN&gt;]&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; RegisterFunction(&lt;SPAN style="COLOR: #2b91af"&gt;Type&lt;/SPAN&gt; type) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;&amp;nbsp; Registry&lt;/SPAN&gt;.ClassesRoot.CreateSubKey(GetSubKeyName(type));&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;[&lt;SPAN style="COLOR: #2b91af"&gt;ComUnregisterFunctionAttribute&lt;/SPAN&gt;]&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; UnregisterFunction(&lt;SPAN style="COLOR: #2b91af"&gt;Type&lt;/SPAN&gt; type) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT color=#000000&gt;&amp;nbsp; &lt;/FONT&gt;Registry&lt;/SPAN&gt;.ClassesRoot.DeleteSubKey(GetSubKeyName(type), &lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;private&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; GetSubKeyName(&lt;SPAN style="COLOR: #2b91af"&gt;Type&lt;/SPAN&gt; type) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; s = &lt;SPAN style="COLOR: #a31515"&gt;@"CLSID\{"&lt;/SPAN&gt; + type.GUID.ToString().ToUpper() + &lt;SPAN style="COLOR: #a31515"&gt;@"}\Programmable"&lt;/SPAN&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt; s;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;(Notice that the registration functions are &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;static&lt;/SPAN&gt;&lt;/FONT&gt;).&lt;/P&gt;
&lt;P mce_keep="true"&gt;
&lt;P mce_keep="true"&gt;Now we've finished coding the &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;Functions&lt;/FONT&gt;&lt;/SPAN&gt; class and the UNIQUEVALUES function. We can now use from an Excel worksheet just like any other custom worksheet function.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Using UNIQUEVALUES in a Worksheet&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;The first to do is to install our &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;Functions&lt;/FONT&gt;&lt;/SPAN&gt; class as an automation addin. This enables Excel to call our custom UDFs. &lt;/P&gt;
&lt;P mce_keep="true"&gt;To install as an automation addin, we bring up the usual&amp;nbsp;Addin Manager via&amp;nbsp;Excel Options-&amp;gt;Add-Ins-&amp;gt;Manage Excel Add-ins. From this dialogue we click the Automation button and select ExcelExtensions.Functions from the list.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/8362070/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/8362070/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;To use the function, we highlight the cells which we want the unique values written into, type the =UNIQUEVALUES( ... ) where ... is the range from which we want to extract the values and then press &lt;EM&gt;ctrl-shift-enter&lt;/EM&gt;. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Note that we must press ctrl-shift-enter to tell Excel that this function returns an array. Excel automatically serialises the values returned from the function into the array of highlighted cells. If the number of values returned from the function is less than the number of cells we highlighted, Excel places #N/A in each of the extra cells. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Consider the following example.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/8365876/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/8365876/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Notice that there are only four unique values in the range D3:D9. However, because we highlighted 7 cells (i.e., E3:E9) Excel has placed #N/A in each of the 3 additional cells.&lt;/P&gt;
&lt;P mce_keep="true"&gt;If we highlight too few cells (say, 2 cells) then Excel will place the first to values returned from the function in those cells.&lt;/P&gt;
&lt;P mce_keep="true"&gt;This is normal array function behaviour in Excel. Notice that we didn't have to write anything in our code to do this; Excel does this for us automatically. &lt;/P&gt;
&lt;P mce_keep="true"&gt;If the data in D3:D9 changes, Excel fires UNIQUEVALUES and our function recalculates the new unique values. &lt;/P&gt;
&lt;P mce_keep="true"&gt;In the following screenshot, we change the first value from Red to Yellow and the unique values automatically update:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/8365918/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/8365918/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;The UNIQUEVALUES function can also be used with Excel's native functions that work with arrays. Two examples of such&amp;nbsp;functions are COUNT and INDEX. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Both COUNT and INDEX can&amp;nbsp;accept arrays as parameters. So we can use these functions&amp;nbsp;on the array returned by UNIQUEVALUES.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The formula =COUNT(UNIQUEVALUES(D3:D9)) returns the number of values in the array. The formula =INDEX(UNIQUEVALUES(D3:D9), 1, 1) returns the first value in the array; and =INDEX(UNIQUEVALUES(D3:D9), &lt;STRONG&gt;2&lt;/STRONG&gt;, 1) returns the second; and so on ... (remember that UNIQUEVALUES returns an array one column wide).&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Summary&lt;/STRONG&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;The functions that we want to expose as custom worksheet functions need to be defined on our class's default interface;&lt;/DIV&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Defining our custom worksheet functions on a dedicated interface and using &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;ComDefaultInterface &lt;/FONT&gt;&lt;/SPAN&gt;to make that interface the default is one way of doing this;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Our COM class must define the Programmable registry key under its CLSID key;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;We can return multiple values from a custom UDF by returning them in an array;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Excel handles the serialisation of the array into the worksheet;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Download&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;I have added the UNIQUEVALUES function into my ExcelExtensions add-in. This can be downloaded from the MSDN Code Gallery by clicking &lt;A class="" href="http://code.msdn.microsoft.com/ExcelExtensions" mce_href="http://code.msdn.microsoft.com/ExcelExtensions"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;P mce_keep="true"&gt;There are two downloads which can be downloaded from the Releases tab: ExcelExtensionsSrc.zip and ExcelExtensions.msi. &lt;/P&gt;
&lt;P mce_keep="true"&gt;ExcelExtensionsSrc.zip contains the complete source code and ExcelExtensions.msi is the set up program. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Over time, I'll be adding additional feature to the addin.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8346368" width="1" height="1"&gt;</content><author><name>Gabhan Berry</name><uri>http://blogs.msdn.com/members/Gabhan+Berry.aspx</uri></author><category term="Addins" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/Addins/default.aspx" /><category term="C#" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/C_2300_/default.aspx" /><category term=".NET" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/.NET/default.aspx" /><category term="Functions" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/Functions/default.aspx" /></entry><entry><title>Using Statistics in Business Intelligence</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/gabhan_berry/archive/2008/04/04/using-statistics-in-business-intelligence.aspx" /><id>http://blogs.msdn.com/gabhan_berry/archive/2008/04/04/using-statistics-in-business-intelligence.aspx</id><published>2008-04-04T19:27:00Z</published><updated>2008-04-04T19:27:00Z</updated><content type="html">&lt;P&gt;One other area I work in is Business Intelligence. These days BI is an important technology to an increasing number of companies. There are many great BI tools out there, one of which is (of course)&amp;nbsp;Excel. &lt;/P&gt;
&lt;P&gt;One of the things that&amp;nbsp;makes Excel such a useful BI tool is its richness of functionality. It has so many existing features that can be used in the BI area - one of which is its statistical analysis functions.&lt;/P&gt;
&lt;P&gt;I posted an article over on the Excel team blog illustrating one way&amp;nbsp;we can use Excel's&amp;nbsp;statistical functions to extract useful information from business data. &lt;/P&gt;
&lt;P&gt;If you're interested in statistical analysis or BI in Excel, you may find the article interesting. Click &lt;A class="" href="http://blogs.msdn.com/excel/archive/2008/04/02/statistics-and-business-data-detecting-unexpected-values.aspx" mce_href="http://blogs.msdn.com/excel/archive/2008/04/02/statistics-and-business-data-detecting-unexpected-values.aspx"&gt;here&lt;/A&gt; to view the article.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8357483" width="1" height="1"&gt;</content><author><name>Gabhan Berry</name><uri>http://blogs.msdn.com/members/Gabhan+Berry.aspx</uri></author><category term="Functions" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/Functions/default.aspx" /><category term="BI" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/BI/default.aspx" /><category term="Statistics" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/Statistics/default.aspx" /></entry><entry><title>OOXML wins ISO Vote</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/gabhan_berry/archive/2008/04/01/ooxml-wins-iso-vote.aspx" /><id>http://blogs.msdn.com/gabhan_berry/archive/2008/04/01/ooxml-wins-iso-vote.aspx</id><published>2008-04-01T19:49:00Z</published><updated>2008-04-01T19:49:00Z</updated><content type="html">&lt;P&gt;Office Open XML (OOXML), the XML file formats used by Office 2007, today won the ISO vote which paves the way for it becoming an ISO standard.&lt;/P&gt;
&lt;P&gt;This is &lt;EM&gt;very&lt;/EM&gt; exciting news indeed for Excel programmability.&amp;nbsp;Coupled with the new Open XML SDK that&amp;nbsp;we announced last week,&amp;nbsp;programming against&amp;nbsp;Excel's native file format has never been as&amp;nbsp;open.&amp;nbsp;I think this opens up quite a lot of exciting programmability scenarios, some of which I'll cover on this blog over time.&lt;/P&gt;
&lt;P&gt;More information can be found at the following links:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A class="" href="http://www.microsoft.com/presspass/press/2008/apr08/04-01OpenXMLVotePR.mspx" mce_href="http://www.microsoft.com/presspass/press/2008/apr08/04-01OpenXMLVotePR.mspx "&gt;Microsoft's press release&lt;/A&gt;;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="" href="http://www.iso.org/iso/pressrelease.htm?refid=Ref1123" mce_href="http://www.iso.org/iso/pressrelease.htm?refid=Ref1123"&gt;ISO's press release&lt;/A&gt;;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="" href="http://www.ecma-international.org/news/TC45_current_work/ISO_and_IEC_approve_Office_Open_XML.htm" mce_href="http://www.ecma-international.org/news/TC45_current_work/ISO_and_IEC_approve_Office_Open_XML.htm "&gt;ECMA's statement&lt;/A&gt;;&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8348449" width="1" height="1"&gt;</content><author><name>Gabhan Berry</name><uri>http://blogs.msdn.com/members/Gabhan+Berry.aspx</uri></author><category term="OpenXML" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/OpenXML/default.aspx" /></entry><entry><title>Open XML SDK Roadmap Announced</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/gabhan_berry/archive/2008/03/20/open-xml-sdk-roadmap-announced.aspx" /><id>http://blogs.msdn.com/gabhan_berry/archive/2008/03/20/open-xml-sdk-roadmap-announced.aspx</id><published>2008-03-20T07:06:00Z</published><updated>2008-03-20T07:06:00Z</updated><content type="html">&lt;P&gt;The new XML file formats in Office 2007 open the door to lots of exciting&amp;nbsp;programmability solutions. For example, the files can be created and consumed&amp;nbsp;without automating Excel.exe. This&amp;nbsp;really helps server-side solutions. It also&amp;nbsp;aids&amp;nbsp;batch processing of Excel files and cross-platform business solutions that exchange Office files.&lt;/P&gt;
&lt;P&gt;To enable easy access to the files, we provided the .NET Packaging API.&amp;nbsp;&amp;nbsp;But this is a low-level API which does not have any application awareness. For example, it doesn't understand Excel ranges or tables; it deals with the raw XML elements and relations.&lt;/P&gt;
&lt;P&gt;But we are working on improving this situation. &lt;/P&gt;
&lt;P&gt;The Open XML SDK is a .NET library which will provide a higher-level API for the Open XML files. It will have application awareness and will greatly benefit developer productivity. &lt;/P&gt;
&lt;P&gt;Version 1.0 will be released in May 2008. This will be&amp;nbsp;an augmentation of&amp;nbsp;last year's CTP. However,&amp;nbsp;there won't really be anything in v1.0 for Excel developers. The Excel support will come later this year.&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/8326937/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/8326937/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;Here are some links which contain more information on the SDK:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A class="" href="http://openxmldeveloper.org/archive/2008/03/13/OpenXMLSDK.aspx" mce_href="http://openxmldeveloper.org/archive/2008/03/13/OpenXMLSDK.aspx"&gt;OpenXMLDeveloper.org&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/bb448854.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/bb448854.aspx"&gt;Download the Open XML SDK&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8326952" width="1" height="1"&gt;</content><author><name>Gabhan Berry</name><uri>http://blogs.msdn.com/members/Gabhan+Berry.aspx</uri></author><category term="C#" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/C_2300_/default.aspx" /><category term=".NET" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/.NET/default.aspx" /><category term="OpenXML" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/OpenXML/default.aspx" /></entry><entry><title>Analysing Column Data using C# (... with a little Custom Drawing thrown in for fun) </title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/gabhan_berry/archive/2008/03/10/analysing-column-data-using-c-and-drawing-custom-bar-charts.aspx" /><id>http://blogs.msdn.com/gabhan_berry/archive/2008/03/10/analysing-column-data-using-c-and-drawing-custom-bar-charts.aspx</id><published>2008-03-11T01:35:00Z</published><updated>2008-03-11T01:35:00Z</updated><content type="html">&lt;P&gt;When presented with&amp;nbsp;a table of data in Excel, sometimes it is useful to be able to learn some quick facts about it.&amp;nbsp;One quick fact which is often useful is the distribution of&amp;nbsp;values within a particular column. For example, if we have a column called&amp;nbsp;Region it is useful to&amp;nbsp; know which regions occur more often than others. Perhaps 50% of the column is&amp;nbsp;North America, 30% Europe and 19% Pacific.&amp;nbsp;Excel has all the tools we need to do this but&amp;nbsp;we just need to tie them together in a way that suits us.&lt;/P&gt;
&lt;P&gt;Additionally, it would be nice if we displayed this information graphically; perhaps using some form of simple histogram to compliment the numerical values and provide a tiny bit of visualisation.&lt;/P&gt;
&lt;P&gt;In this post,&amp;nbsp;we'll&amp;nbsp;write a C# addin that does&amp;nbsp;such a thing.&lt;/P&gt;
&lt;P&gt;Here's a screenshot of the&amp;nbsp;addin we'll build. &lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/8139279/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/8139279/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Getting Started&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;We won't cover the basics of getting up-and-running with C# Excel addins in this post. I have already covered that briefly &lt;A class="" href="http://blogs.msdn.com/gabhan_berry/archive/2008/01/30/excel-and-managed-code-how-does-that-work.aspx" mce_href="http://blogs.msdn.com/gabhan_berry/archive/2008/01/30/excel-and-managed-code-how-does-that-work.aspx"&gt;here&lt;/A&gt;. Instead, we'll fast forward to the stage where we've already got our basic addin project and now we're ready to add the fun bits. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Note: This addin uses the&amp;nbsp;&lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ExcelUtility&lt;/SPAN&gt; &lt;/FONT&gt;class I published previously in &lt;A class="" href="http://blogs.msdn.com/gabhan_berry/archive/2008/02/06/excel-s-optional-parameters-and-missing-value-a-c-workaround.aspx" mce_href="http://blogs.msdn.com/gabhan_berry/archive/2008/02/06/excel-s-optional-parameters-and-missing-value-a-c-workaround.aspx"&gt;this post&lt;/A&gt;.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Designing the Custom Ribbon&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;We'll add a custom tab to the Ribbon called "Excel Extensions". On this tab, we'll place a button titled "Analyse Column" inside a group titled "Table Extensions". &lt;/P&gt;
&lt;P mce_keep="true"&gt;Here's our Ribbon XML:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;?&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;xml&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;version&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt;1.0&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;encoding&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;utf-8&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt; ?&amp;gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;customUI&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;onLoad&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt;OnRibbonLoad&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;xmlns&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;http://schemas.microsoft.com/office/2006/01/customui&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp; &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;ribbon&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;tabs&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;tab&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;id&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt;ExcelExtensionsTab&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;label&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;Excel Extensions&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;SPAN style="mso-tab-count: 3"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;group&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;id&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt;TableCommandsGroup&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;label&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;Table Extensions&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;button&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;id&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt;ColumnAnalysis&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;onAction&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;OnColumnAnalysisClicked&lt;/SPAN&gt;" &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;label&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt;Analyse Column&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;getImage&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;GetColumnAnalysisButtonImage&lt;/SPAN&gt;" &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;getEnabled&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt;GetColumnAnalysisEnabled&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt; &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp;supertip&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt;Analyse a table column and view statistical details about the values in the column.&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt; &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp;size&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt;large&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;/&amp;gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;group&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;tab&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;tabs&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp; &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #a31515; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;ribbon&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #a31515; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;customUI&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;
&lt;P&gt;We'll store this&amp;nbsp;in an XML file as part of our solution. Then we'll link the XML file into our assembly at compile time as an&amp;nbsp;embedded resource i.e., the XML is compiled into our assembly. This means that we don't have to distribute the XML file with our addin and&amp;nbsp;we use the .NET &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;Assembly &lt;/FONT&gt;&lt;/SPAN&gt;class to&amp;nbsp;access the&amp;nbsp;XML resource at runtime.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here's our implemention of the IRibbonExtensibility.GetCustomUI method:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;public&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; GetCustomUI(&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; RibbonID) {&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;&amp;nbsp; Assembly&lt;/SPAN&gt; assembly = &lt;SPAN style="COLOR: #2b91af"&gt;Assembly&lt;/SPAN&gt;.GetExecutingAssembly();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; using&lt;/SPAN&gt; (System.IO.&lt;SPAN style="COLOR: #2b91af"&gt;Stream&lt;/SPAN&gt; stream = assembly.GetManifestResourceStream&amp;nbsp;(&lt;SPAN style="COLOR: #a31515"&gt;"ExcelExtensions.ExcelExtensionsRibbon.xml"&lt;/SPAN&gt;)) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; System.IO.&lt;SPAN style="COLOR: #2b91af"&gt;StreamReader&lt;/SPAN&gt;(stream).ReadToEnd();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;It would be nice if&amp;nbsp;our&amp;nbsp;Analyse Column button was enabled only when&amp;nbsp;the user has clicked inside a table. To&amp;nbsp;do this, we need to interact with the Ribbon API a little more.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;In our XML, we specify a &lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;getEnabled&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;=&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;"&lt;SPAN style="COLOR: blue"&gt;GetColumnAnalysisEnabled&lt;/SPAN&gt;"&lt;/SPAN&gt;&amp;nbsp;attribute on the button. This tells&amp;nbsp;the Ribbon that whenever it needs to draw our button it should first call the &lt;FONT face="Courier New"&gt;GetColumnAnalysisEnabled &lt;/FONT&gt;method. This method will return a&amp;nbsp;true/false value indicating whether the button&amp;nbsp;should be&amp;nbsp;displayed as enabled or not. &lt;/P&gt;
&lt;P&gt;The Ribbon will call &lt;FONT face="Courier New"&gt;GetColumnAnalysisEnabled &lt;/FONT&gt;when it first&amp;nbsp;displays&amp;nbsp;our custom tab. But it won't call it&amp;nbsp;again. So, how do we toggle the state of our button dynamically at runtime? &lt;/P&gt;
&lt;P&gt;When our addin is first loaded, we are given a reference to the main Ribbon instance.&amp;nbsp;This is an object of type &lt;SPAN style="FONT-SIZE: 10pt; COLOR: #2b91af; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;IRibbonUI&lt;/SPAN&gt;. One of the methods&amp;nbsp;on this interface&amp;nbsp;is &lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Invalidate&lt;/SPAN&gt;.&amp;nbsp;When we call this method, the Ribbon&amp;nbsp;invokes all of our &lt;SPAN style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;getEnabled &lt;/SPAN&gt;functions. It is&amp;nbsp;our responsibility&amp;nbsp;to make sure that these functions return the correct true/false value.&lt;/P&gt;
&lt;P&gt;This seems a little weird to begin with. It is a side affect of the declarative nature of the Ribbon API; that is, we&amp;nbsp;are not given pointers or references to the Ribbon controls at runtime so we need some callback approach to enable us to&amp;nbsp;change the controls' appearances&amp;nbsp;at runtime.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The Ribbon doesn't know anything about our application logic so it doesn't know when we want to enable/disable buttons or dynamically change the Ribbon. To avoid constantly calling into all addins,&amp;nbsp;the Ribbon&amp;nbsp;declares methods by which all addins can call into it and force&amp;nbsp;it to redraw part or all of&amp;nbsp;their custom Ribbon tabs. &lt;/P&gt;
&lt;P&gt;Because we want to enable/disable our button based on the cell that the user selects, we want the Ribbon to redraw our button every time the sheet selection changes. When the user selects a cell, we want to force the Ribbon to invoke our &lt;FONT face="Courier New"&gt;GetColumnAnalysisEnabled &lt;/FONT&gt;&lt;FONT color=#000000&gt;method. In this method we will determine whether or not the user clicked inside a table&amp;nbsp;and return true/false appropriately. &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;First, let's sink the &lt;FONT face="Courier New"&gt;SheetSelectionChange &lt;/FONT&gt;event and invalidate the Ribbon whenever &lt;FONT face="Courier New"&gt;SheetSelectionChange &lt;/FONT&gt;fires.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;protected&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; SinkExcelEvents() {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp; _application.SheetSelectionChange += &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; Excel.&lt;SPAN style="COLOR: #2b91af"&gt;AppEvents_SheetSelectionChangeEventHandler&lt;/SPAN&gt;(_application_SheetSelectionChange);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; _application_SheetSelectionChange(&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt; Sh, Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Range&lt;/SPAN&gt; Target) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp; _ribbonUI.Invalidate();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Next, we implement&amp;nbsp;the &lt;FONT face="Courier New"&gt;GetColumnAnalysisEnabled &lt;/FONT&gt;&lt;FONT color=#000000&gt;method. This method returns true if&amp;nbsp;the selected cell is inside a table and false otherwise. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;public&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: blue"&gt;bool&lt;/SPAN&gt; GetColumnAnalysisEnabled(&lt;SPAN style="COLOR: #2b91af"&gt;IRibbonControl&lt;/SPAN&gt; Control) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;FONT color=#000000&gt;&amp;nbsp; &lt;/FONT&gt;return&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;ColumnAnalysisExtension&lt;/SPAN&gt;.EnableUI(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;public&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: blue"&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;bool&lt;/SPAN&gt; EnableUI(&lt;SPAN style="COLOR: #2b91af"&gt;Connect&lt;/SPAN&gt; Connection) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp; Excel.&lt;SPAN style="COLOR: #2b91af"&gt;ListObjects&lt;/SPAN&gt; listObjects = ((Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Worksheet&lt;/SPAN&gt;)Connection.ExcelApp.ActiveSheet).ListObjects;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp; Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Range&lt;/SPAN&gt; activeCell = Connection.ExcelApp.ActiveCell; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;FONT color=#000000&gt;&amp;nbsp; &lt;/FONT&gt;foreach&lt;/SPAN&gt; (Excel.&lt;SPAN style="COLOR: #2b91af"&gt;ListObject&lt;/SPAN&gt; listObj &lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt; listObjects) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/SPAN&gt; (listObj.SourceType == Excel.&lt;SPAN style="COLOR: #2b91af"&gt;XlListObjectSourceType&lt;/SPAN&gt;.xlSrcRange) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;&amp;gt; param = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;&amp;gt;();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Range&lt;/SPAN&gt; intersection = &lt;SPAN style="COLOR: #2b91af"&gt;ExcelUtility&lt;/SPAN&gt;.ApplicationInvoke&amp;lt;Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Range&lt;/SPAN&gt;&amp;gt;(Connection.ExcelApp, &lt;SPAN style="COLOR: #a31515"&gt;"Intersect"&lt;/SPAN&gt;, activeCell, listObj.Range);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt; (intersection != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;){&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;The &lt;FONT face="Courier New"&gt;GetColumnAnalysisEnabled &lt;/FONT&gt;method is defined on our &lt;SPAN style="FONT-SIZE: 10pt; COLOR: #2b91af; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Connect &lt;/SPAN&gt;class (the class that implements &lt;SPAN style="FONT-SIZE: 10pt; COLOR: #2b91af; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;IDTExtensibility2&lt;/SPAN&gt; and &lt;SPAN style="FONT-SIZE: 10pt; COLOR: #2b91af; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;IRibbonExtensibility&lt;/SPAN&gt;). But we've seperated the&amp;nbsp;implementation of the column analysis extension into a different class called &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;ColumnAnalysisExtension&lt;/FONT&gt;&lt;/SPAN&gt;. &lt;/P&gt;
&lt;P&gt;So, the Ribbon invokes &lt;SPAN style="FONT-SIZE: 10pt; COLOR: #2b91af; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Connect&lt;/SPAN&gt;.&lt;FONT face="Courier New"&gt;GetColumnAnalysisEnabled &lt;/FONT&gt;which in turn invokes &lt;SPAN style="FONT-SIZE: 10pt; COLOR: #2b91af; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;ColumnAnalysisExtension&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;.&lt;FONT face="Courier New"&gt;EnableUI&lt;/FONT&gt;.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;We determine whether&amp;nbsp;or not the active&amp;nbsp;cell is in a table by looping through all the tables in the book and&amp;nbsp;calculating the intersection of each table's range&amp;nbsp;with the active cell. If the intersection is non null then the active cell is in the table's range; otherwise, it's not.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;So, when the user clicks inside a table our button is enabled and when they click outside a table the button is disabled.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/8140249/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/8140249/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Calculating the Distribution of Values in a Column&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;There's no point writing our own code to count the occurances of values in an Excel range when we can just get Excel to do it. So, we'll make use of the existing COUNTA and COUNTIF worksheet functions to perform the actual calculations. &lt;/P&gt;
&lt;P mce_keep="true"&gt;For each value in the column we'll gather two values: the number of occurances and the percentage of occurances. We'll store this data in a&amp;nbsp;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #2b91af; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Dictionary&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt;&amp;gt;&amp;gt;&lt;/SPAN&gt;&amp;nbsp;object.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Therefore, we need to write a method that does the following: &lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Count the number of rows in&amp;nbsp;the column by evaluating =COUNTA(&amp;lt;column range&amp;gt;);&amp;nbsp;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Determine all the unique values in the column;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;For each unique value: &lt;/DIV&gt;&lt;/LI&gt;
&lt;OL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;evaluate =COUNTIF(&amp;lt;column range&amp;gt;, &amp;lt;value&amp;gt;) to calculate the number of occurances of the value in the column;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Store the number of occurances and the percentage&amp;nbsp;of occurances&amp;nbsp;in our dictionary object;&lt;/DIV&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;/OL&gt;
&lt;P mce_keep="true"&gt;Here's the code:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;protected&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; CalculateStats() {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; eval = &lt;SPAN style="COLOR: #a31515"&gt;"=COUNTA("&lt;/SPAN&gt; + &lt;SPAN style="COLOR: #2b91af"&gt;ExcelUtility&lt;/SPAN&gt;.RangeInvoke&amp;lt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&amp;gt;(_columnRange, &lt;SPAN style="COLOR: #a31515"&gt;"Address"&lt;/SPAN&gt;, &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;, Excel.&lt;SPAN style="COLOR: #2b91af"&gt;XlReferenceStyle&lt;/SPAN&gt;.xlA1) + &lt;SPAN style="COLOR: #a31515"&gt;")"&lt;/SPAN&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt; totalCount = (&lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt;)_connection.ExcelApp.Evaluate(eval);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; _stats = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;Dictionary&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt;&amp;gt;&amp;gt;();&lt;o:p&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;foreach&lt;/SPAN&gt; (Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Range&lt;/SPAN&gt; cell &lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt; _columnRange.Cells) {&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&lt;FONT color=#000000&gt; val = cell.Value2.ToString();&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;&lt;FONT color=#000000&gt; (!_stats.ContainsKey(val)) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;_stats.Add(val, &lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&lt;FONT color=#000000&gt;&amp;lt;&lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt;&lt;FONT color=#000000&gt;&amp;gt;());&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;catch&lt;/SPAN&gt;&lt;FONT color=#000000&gt; (&lt;/FONT&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Exception&lt;/SPAN&gt;&lt;FONT color=#000000&gt;) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;}&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;foreach&lt;/SPAN&gt; (&lt;SPAN style="COLOR: #2b91af"&gt;KeyValuePair&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt;&amp;gt;&amp;gt; entry &lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt; _stats) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;eval = &lt;SPAN style="COLOR: #a31515"&gt;"=COUNTIF("&lt;/SPAN&gt; + &lt;SPAN style="COLOR: #2b91af"&gt;ExcelUtility&lt;/SPAN&gt;.RangeInvoke&amp;lt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&amp;gt;(_columnRange, &lt;SPAN style="COLOR: #a31515"&gt;"Address"&lt;/SPAN&gt;, &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;, Excel.&lt;SPAN style="COLOR: #2b91af"&gt;XlReferenceStyle&lt;/SPAN&gt;.xlA1) + &lt;SPAN style="COLOR: #a31515"&gt;", \""&lt;/SPAN&gt; + entry.Key + &lt;SPAN style="COLOR: #a31515"&gt;"\")"&lt;/SPAN&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt; count = (&lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt;)_connection.ExcelApp.Evaluate(eval);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;entry.Value.Add(count);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;entry.Value.Add(count / totalCount);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Displaying the Data using a DataGridView Control and Custom Drawn Cells&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;The next stage is to display the data to the user. For this, we'll write a WinForm which contains a DataGridView control. In the DataGridView we'll list each value along with the value's statistics. However, inserting rows of data into a DataGridView control isn't that interesting so we'll not discuss that here. Instead we'll concentrate on the nicer bit: using custom drawn DataGridView cells. &lt;/P&gt;
&lt;P mce_keep="true"&gt;One of the big advantages of using .NET to write Excel addins is that we have access to all the .NET framework class library (FCL). This brings about some exciting possibilities for Excel addins, one of which is using WinForms to build good looking and modern user interfaces.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The DataGridView control has a really nice feature which makes it very easy for us to perform custom drawing for cells in&amp;nbsp;the control. It allows us to define a custom column class which the DataGridView will&amp;nbsp;use as if it was an inbuilt column class.&amp;nbsp; &lt;/P&gt;
&lt;P mce_keep="true"&gt;Then we define our custom&amp;nbsp;cell class. This is the class which defines the cells in our custom column.&amp;nbsp;The&amp;nbsp;cell class&amp;nbsp;extends one of the inbuilt DataGridViewXXXCell classes (such as &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DataGridViewTextBoxCell&lt;/SPAN&gt;)&lt;/FONT&gt;.&amp;nbsp;All we have to do is&amp;nbsp;override the Paint method of the base class and perform the custom drawing that we want to do. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Custom drawing doesn't get much easier than this!&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Let's remind ourselves what we want to draw. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/8139279/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/8139279/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;We want to draw a rectangle whose size represents the percentage value of the item. So, North America has a value of 50.8% so we want the rectangle to fill (horizontally) 50.8% of the cell. In other words, we want something similar to conditional formatting in Excel, but in a DataGridView control.&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Notice that we also want to display the value itself as a number and we still want the cell borders and alternating background colours to be drawn. &lt;/P&gt;
&lt;P mce_keep="true"&gt;The first step, is to define our custom column class. We'll call this &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DataGridViewBarChartColumn&lt;/SPAN&gt; &lt;/FONT&gt;and its definition is as follows:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;public&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: blue"&gt;class&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;DataGridViewBarChartColumn&lt;/SPAN&gt; : &lt;SPAN style="COLOR: #2b91af"&gt;DataGridViewColumn&lt;/SPAN&gt; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; DataGridViewBarChartColumn() {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.CellTemplate = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;DataGridViewBarChartCell&lt;/SPAN&gt;();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.ReadOnly = &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;
&lt;P mce_keep="true"&gt;The &lt;FONT face="Courier New"&gt;CellTemplate &lt;/FONT&gt;property specifies the class which defines the cells that occur in the column. In this case its &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DataGridViewBarChartCell&lt;/SPAN&gt;&lt;/FONT&gt;. This is our custom cell class and it is in this class that we do the custom drawing.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;The &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;DataGridViewBarChartCell &lt;/FONT&gt;&lt;/SPAN&gt;definition is as follows. &lt;/P&gt;
&lt;P mce_keep="true"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;class&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: #2b91af"&gt;DataGridViewBarChartCell&lt;/SPAN&gt; : &lt;SPAN style="COLOR: #2b91af"&gt;DataGridViewTextBoxCell&lt;/SPAN&gt; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;protected&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;Color&lt;/SPAN&gt; _barColor = &lt;SPAN style="COLOR: #2b91af"&gt;Color&lt;/SPAN&gt;.FromArgb(50, 0, 0, 0);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;protected&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;override&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; Paint(&lt;SPAN style="COLOR: #2b91af"&gt;Graphics&lt;/SPAN&gt; graphics,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Rectangle&lt;/SPAN&gt; clipBounds,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Rectangle&lt;/SPAN&gt; cellBounds,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; rowIndex,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DataGridViewElementStates&lt;/SPAN&gt; elementState,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt; value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt; formattedValue,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; errorText,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DataGridViewCellStyle&lt;/SPAN&gt; cellStyle,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DataGridViewAdvancedBorderStyle&lt;/SPAN&gt; advancedBorderStyle,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DataGridViewPaintParts&lt;/SPAN&gt; paintParts) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;base&lt;/SPAN&gt;.Paint(graphics,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;clipBounds,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;cellBounds,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;rowIndex,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;elementState,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;formattedValue,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;errorText,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;cellStyle,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;advancedBorderStyle,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;paintParts);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;float&lt;/SPAN&gt; val = 0.0F;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;try&lt;/SPAN&gt; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;val = &lt;SPAN style="COLOR: #2b91af"&gt;Convert&lt;/SPAN&gt;.ToSingle(value);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;val /= 100.0F;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;catch&lt;/SPAN&gt; (&lt;SPAN style="COLOR: #2b91af"&gt;InvalidCastException&lt;/SPAN&gt; InvalidCastEx) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;RectangleF&lt;/SPAN&gt; barRect = cellBounds;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;barRect.Width *= val;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;using&lt;/SPAN&gt; (&lt;SPAN style="COLOR: #2b91af"&gt;SolidBrush&lt;/SPAN&gt; brush = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;SolidBrush&lt;/SPAN&gt;(_barColor)) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;graphics.FillRectangle(brush, barRect);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;DataGridViewBarChartCell &lt;/FONT&gt;&lt;/SPAN&gt;is a subclass&amp;nbsp;of the inbuilt&amp;nbsp;&lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DataGridViewTextBoxCell&lt;/SPAN&gt;&amp;nbsp;&lt;/FONT&gt;class. Extending the inbuilt class means that all we have to do is override the paint behaviour of the &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DataGridViewTextBoxCell&lt;/SPAN&gt; &lt;/FONT&gt;class and let the &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DataGridViewTextBoxCell&lt;/SPAN&gt; &lt;/FONT&gt;class handle everything else.&lt;/P&gt;
&lt;P mce_keep="true"&gt;In the Paint method you can see that we are automatically provided with a Graphics object and a bounding rectangle in which to paint. All we need to do is calculate the width of the rectangle and then call &lt;FONT face="Courier New"&gt;Graphics.FillRectangle&lt;/FONT&gt;. &lt;/P&gt;
&lt;P mce_keep="true"&gt;
&lt;P mce_keep="true"&gt;Finally, notice that the first thing we do in the Paint method is call &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;base&lt;/SPAN&gt;.Paint&lt;/FONT&gt;. This means we don't have to care about drawing the cell's value or the background or the borders because the base class will do that for us. All we do is then draw on top of what the base class draws. If we didn't call &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;base&lt;/SPAN&gt;.Paint &lt;/FONT&gt;then the cells would only contain the filled rectangle and nothing else. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Hooking it all Together&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;To make the DataGridView control use our custom column class, we set the type of the appropriate column in the DataGridView control to &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DataGridViewBarChartColumn&lt;/SPAN&gt;&lt;/FONT&gt;.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;The final stage is to display our window when the user clicks the button in the Ribbon. Looking back at our Ribbon XML we defined the onAction callback for the button as &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: red"&gt;onAction&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=&lt;/SPAN&gt;"&lt;SPAN style="COLOR: blue"&gt;OnColumnAnalysisClicked&lt;/SPAN&gt;"&lt;/FONT&gt;. This means that the Ribbon will call the &lt;FONT size=2&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;OnColumnAnalysisClicked &lt;/SPAN&gt;&lt;/FONT&gt;method on our addin when the user clicks the button, so, all we need to do is define the &lt;FONT face="Courier New"&gt;OnColumnAnalysisClicked &lt;/FONT&gt;method and make it public.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;public&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; OnColumnAnalysisClicked(&lt;SPAN style="COLOR: #2b91af"&gt;IRibbonControl&lt;/SPAN&gt; Control) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT color=#000000&gt;&amp;nbsp; &lt;/FONT&gt;ColumnAnalysisExtension&lt;/SPAN&gt; ext = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;ColumnAnalysisExtension&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;
&lt;P mce_keep="true"&gt;In this method we are creating a new &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;ColumnAnalysisExtension &lt;/FONT&gt;&lt;/SPAN&gt;object. The constructor of this class simply calls our &lt;FONT face="Courier New"&gt;CalculateStats &lt;/FONT&gt;method and then displays the window containing the DataGridView control (it does one or two other things too).&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;public&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; ColumnAnalysisExtension(&lt;SPAN style="COLOR: #2b91af"&gt;Connect&lt;/SPAN&gt; Connection) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp; _connection = Connection;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;BuildColumnRange();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt; (_columnRange != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;CalculateStats();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;DisplayStatsWindow();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Summary&lt;/STRONG&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Use the IRibbonUI.Invalidate method to force the Ribbon to redraw your custom Ribbon controls when you need their state to change;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;To avoid having to ship your Ribbon XML, compile it as an embedded resource into your assembly;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Using .NET to write user interfaces offers exciting UI possibilities, such as easily-to-code custom drawn&amp;nbsp;controls;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;To custom draw cells in the DataGridView control, subclass the DataGridViewColumn class and one of the inbuilt DataGridViewXXXCell classes;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;The code for the custom drawing should override the Paint method of the custom cell's base class;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Download the Excel Extensions Addin&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;The Excel Extensions addin and full source code can be downloaded from the MSDN Code Gallery &lt;A class="" href="http://code.msdn.microsoft.com/ExcelExtensions" mce_href="http://code.msdn.microsoft.com/ExcelExtensions"&gt;here&lt;/A&gt;. &lt;/P&gt;
&lt;P mce_keep="true"&gt;There are two downloads which can be downloaded from the Releases tab. There are: ExcelExtensionsSrc.zip and ExcelExtensions.msi. &lt;/P&gt;
&lt;P mce_keep="true"&gt;ExcelExtensionsSrc.zip contains the complete source code and ExcelExtensions.msi is the set up program. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Over time, I'll be adding additional feature to the addin.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8139211" width="1" height="1"&gt;</content><author><name>Gabhan Berry</name><uri>http://blogs.msdn.com/members/Gabhan+Berry.aspx</uri></author><category term="Addins" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/Addins/default.aspx" /><category term="C#" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/C_2300_/default.aspx" /><category term=".NET" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/.NET/default.aspx" /><category term="Ribbon" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/Ribbon/default.aspx" /></entry><entry><title>Using Custom Functions in Dynamic Ranges</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/gabhan_berry/archive/2008/02/19/using-custom-functions-in-dynamic-ranges.aspx" /><link rel="enclosure" type="application/vnd.ms-excel.sheet.macroEnabled.12" length="18917" href="http://blogs.msdn.com/gabhan_berry/attachment/7798180.ashx" /><id>http://blogs.msdn.com/gabhan_berry/archive/2008/02/19/using-custom-functions-in-dynamic-ranges.aspx</id><published>2008-02-19T20:33:00Z</published><updated>2008-02-19T20:33:00Z</updated><content type="html">&lt;P&gt;Named ranges are great. They enable us to assign a name to a collection of cells and use that name in code and worksheet functions. However, named ranges tend to be static. That is, they tend to represent a fixed set of cells, such as, A1:E100. But sometimes it would be useful to have the range's set of cells be dynamic. Instead of the range representing a fixed set of cells, we would like to dynamically determine which cells are included in the range based on some custom logic. &lt;/P&gt;
&lt;P&gt;Excel already lets us do this. It allows us to embed functions inside the definition of a named range and have the functions determine on-the-fly which cells are included in the range. But it's not just native Excel functions (like IF, OFFSET, etc.) that we can embed into a named range defintion. We can also embed our own, custom functions; we can write a custom function that uses our own application logic to dynamically determine at calculation time which cells are in a named range.&lt;/P&gt;
&lt;P&gt;This gives us the capability to &lt;EM&gt;point&lt;/EM&gt; the named range at different cells&amp;nbsp;without actually changing the named range's definition. &lt;/P&gt;
&lt;P&gt;In this posting, I'll talk about dynamic ranges&amp;nbsp;and&amp;nbsp;embedding custom functions into named range defintions.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Getting Started with Dynamic Ranges&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Let's take a simple example. Let's say that we have a column of numbers in the range 'Example 1'!$C$1:$C$100 and we want to find the cells in this range that are higher than some value, X = 34,999.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Using dynamic ranges, we can create a named range (called, say, Range 1) with a definition of:&lt;/P&gt;
&lt;P mce_keep="true"&gt;=GreaterThan('Example 1'!$C$1:$C$100, 34999)&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/7801259/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/7801259/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;We also define a UDF called GreaterThan as:&lt;/P&gt;
&lt;P mce_keep="true"&gt;Public Function GreaterThan(Rng As Range, Limit As Long) As Range&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim Cell As Range&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim ResultRange As Range&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; For Each Cell In Rng&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If Cell.Value2 &amp;gt; Limit Then&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If ResultRange Is Nothing Then&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Set ResultRange = Cell&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Else&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Set ResultRange = Application.Union(ResultRange, Cell)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; End If&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; End If&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Next&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Set GreaterThan = ResultRange&lt;BR&gt;End Function&lt;/P&gt;
&lt;P mce_keep="true"&gt;The UDF iterates over the source range testing&amp;nbsp;each cell. If the cell meets our criteria (in this case its value being greater than 34999)&amp;nbsp;then it is added into a temporary range object. Once the code has iterated over all the cells, the temporary range is returned to the caller. This range represents the set of cells the named range now refers to.&lt;/P&gt;
&lt;P mce_keep="true"&gt;(Note: we're not coping with any runtime errors in this code ... which we should do in a proper version).&lt;/P&gt;
&lt;P mce_keep="true"&gt;We can use the named range just like any other named range and Excel will call our UDF as and when it needs to. So, we could calculate the average of our range by using normal worksheet functions, such as:&lt;/P&gt;
&lt;P mce_keep="true"&gt;=AVERAGE(Range1)&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/7801430/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/7801430/original.aspx"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;We can visually confirm the range that our UDF returned using the Name Manager. If we open up the Name Manager and select Range 1 and then click inside the 'Refers to:' textbox, Excel invokes our UDF and highlights the cells on the worksheet that our UDF returned. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/7805404/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/7805404/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Recalculating the Range&amp;nbsp;when Data Changes&lt;/STRONG&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Excel knows that our dynamic range depends on $C$1:$C$100.&amp;nbsp;This is&amp;nbsp;because we pass $C$1:$C$100 to the UDF call in the named range definition.&lt;/P&gt;
&lt;P mce_keep="true"&gt;This enables Excel to properly calculate our named range during worksheet calculations. &amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;In our example, the cell $E$3 (which contains the formula =AVERAGE(Range1)) depends on Range 1 and Range 1 depends on $C$1:$C$100. Therefore, if $C$1:$C$100 changes, Excel knows that it needs to recalculate Range 1 in order to recalculate $E$3. &lt;/P&gt;
&lt;P mce_keep="true"&gt;So, if we change the value of $C$1 from 40000 to 20000 Excel knows that it needs to recalculate $E$3 and, hence, invokes our UDF.&amp;nbsp;Our UDF determines which cells Range 1 refers to and deems that&amp;nbsp;$C$1 is no longer part of Range 1 (because its value is no longer&amp;nbsp;&amp;gt; 34999); thus the value of $E$3 changes, as shown below.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG style="WIDTH: 299px; HEIGHT: 331px" height=331 src="http://blogs.msdn.com/photos/gabhan_berry/images/7804705/original.aspx" width=299 mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/7804705/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;We can also confirm&amp;nbsp;that Range1 is comprised of different cells&amp;nbsp;by inspecting&amp;nbsp;Range1's address in the VBA Immediate window (this also illustrates that we can use the dynamic named range in VBA just like we can use a 'normal' named range).&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/7804821/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/7804821/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;A Note about Interacting with the Calc Tree&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;If our UDF didn't declare its source data range as a parameter then Excel would not be able to call it at the appropriate times during recalculation. &lt;/P&gt;
&lt;P mce_keep="true"&gt;For example, if our UDF simply iterated through $C$1:$C$100 without declaring this range as a parameter then, when $C$1:$C$100 is changed, $E$3 wouldn't be recalculated. &lt;/P&gt;
&lt;P mce_keep="true"&gt;This is because Excel would not know that $E$3 depends on $C$1:$C$100 because that dependency&amp;nbsp;would be&amp;nbsp;hidden inside the UDF.&lt;/P&gt;
&lt;P mce_keep="true"&gt;There may circumstances when we don't care about this. But it is worth remembering that Excel needs to know about any worksheet dependencies our UDF has in order for our dynamic range to interact with the calculation tree properly.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Making More Use of Dynamic Ranges&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Our GreaterThan UDF is about as basic as could be, but, it illustrates the technique. It doesn't, however, take much imagination to see how this technique could be used in more sophisticated ways. &lt;/P&gt;
&lt;P mce_keep="true"&gt;For example, inside our UDF we could make use of external data, such as our company's databases, and use the logic and/or data stored in them to determine the contents of the dynamic range in Excel. &lt;/P&gt;
&lt;P mce_keep="true"&gt;One example could be that we have a list of dates in our worksheet and we want to highlight the dates on which somebody downloaded a trial version of our product from our web site. This would&amp;nbsp;make use&amp;nbsp;of&amp;nbsp;the same technique described here, except, in the loop in our UDF, we would make a call to the database to determine whether that cell should or should not be included in the range. &lt;/P&gt;
&lt;P mce_keep="true"&gt;In other words, using UDFs in dynamic ranges enables us to incorporate external data and external&amp;nbsp;components into our range definitions.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Another use is: search. We could write a fairly sophisticated custom, search feature that is built on top of dynamic ranges and UDFs.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Concerns About Execution Speed&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;I'm afraid I've left the bad news until the end... &lt;/P&gt;
&lt;P mce_keep="true"&gt;Implementing dynamic ranges exactly as I have described here could hand you&amp;nbsp;serious performance issues. &lt;/P&gt;
&lt;P mce_keep="true"&gt;To illustrate this, let's change the definition of Range 1 from:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;=GreaterThan('Example 1'!&lt;STRONG&gt;$C$1:$C$100&lt;/STRONG&gt;, 34999) &lt;/P&gt;
&lt;P mce_keep="true"&gt;to:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;=GreaterThan('Example 1'!&lt;STRONG&gt;$C:$C&lt;/STRONG&gt;, 34999).&lt;/P&gt;
&lt;P mce_keep="true"&gt;Now, we are checking for cells greater than 34999 in the &lt;EM&gt;entire&lt;/EM&gt; C column. In Excel 2007, that's 1,048,576 cells. On my PC (which is a 2.66 GHz&amp;nbsp;dual core with 3GB RAM - not that dual core helps here anyway), calculating the range &lt;EM&gt;once&lt;/EM&gt; takes 3 seconds. If we referenced Range 1 in only a handful of places in our workbook or VBA, our workbook would become fairly unusable fairly quickly.&lt;/P&gt;
&lt;P mce_keep="true"&gt;It would be interesting to see if implementing our UDF in an XLL would improve the speed substantially -&amp;nbsp;(something I'll look into).&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Also, if our UDF did fancier things (like calling into an external database) then you can just imagine what would happen when we're iterating over 1,048,576 cells ....&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;So, it's worth stating that we should exercise some common sense and some judgement when using dynamic ranges. However, if we restrict our usage to &lt;EM&gt;suitably sized&lt;/EM&gt; source ranges, dynamic ranges are a useful tool indeed (where &lt;EM&gt;suitably sized&lt;/EM&gt; is something we each have to define for ourselves).&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Summary&lt;/STRONG&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Named range definitions&amp;nbsp;can contain&amp;nbsp;native and custom functions;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;A custom function used&amp;nbsp;as a named range definition should return the range that it determines the named range represents;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;To interact properly with Excel's calculation tree, all worksheet dependencies (such as the source range) should be included as parameters to the custom function;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Dynamic ranges can be used to build some fairly useful and sophisticated extensions;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Speed when iterating over large ranges is not good and we should employ careful judgment when using dynamic ranges on potentially large source ranges;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;You can download the workbook I used for this post in the list of attachments below.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7798180" width="1" height="1"&gt;</content><author><name>Gabhan Berry</name><uri>http://blogs.msdn.com/members/Gabhan+Berry.aspx</uri></author><category term="VBA" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/VBA/default.aspx" /></entry><entry><title>Ribbon Customisation Links</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/gabhan_berry/archive/2008/02/14/ribbon-customisation-links.aspx" /><id>http://blogs.msdn.com/gabhan_berry/archive/2008/02/14/ribbon-customisation-links.aspx</id><published>2008-02-14T23:00:00Z</published><updated>2008-02-14T23:00:00Z</updated><content type="html">&lt;P&gt;I thought it would be useful to provide a list of some good articles on customising the Office ribbon:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/aa338202.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa338202.aspx"&gt;3-part Article on Ribbon Customisation&lt;/A&gt;;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="" href="http://msdn2.microsoft.com/en-us/office/aa905530.aspx" mce_href="http://msdn2.microsoft.com/en-us/office/aa905530.aspx"&gt;Ribbon Developer Centre&lt;/A&gt;;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="" href="http://blogs.msdn.com/jensenh/archive/tags/Ribbon/default.aspx" mce_href="http://blogs.msdn.com/jensenh/archive/tags/Ribbon/default.aspx"&gt;Jenson Harris' blog&lt;/A&gt;;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/bb462633.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/bb462633.aspx"&gt;Repurposing Commands on the Ribbon&lt;/A&gt;;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/bb545350.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/bb545350.aspx"&gt;Hiding groups of commands on the Ribbon&lt;/A&gt;;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/bb462634.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/bb462634.aspx"&gt;Adding Custom, Dynamic Menus to the Ribbon&lt;/A&gt;;&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7699620" width="1" height="1"&gt;</content><author><name>Gabhan Berry</name><uri>http://blogs.msdn.com/members/Gabhan+Berry.aspx</uri></author><category term="Addins" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/Addins/default.aspx" /><category term="C#" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/C_2300_/default.aspx" /><category term=".NET" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/.NET/default.aspx" /><category term="Ribbon" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/Ribbon/default.aspx" /></entry><entry><title>Excel Event Handling in C#</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/gabhan_berry/archive/2008/02/13/c-excel-addin-steps-2-and-3-understanding-the-ribbon-and-event-trapping.aspx" /><id>http://blogs.msdn.com/gabhan_berry/archive/2008/02/13/c-excel-addin-steps-2-and-3-understanding-the-ribbon-and-event-trapping.aspx</id><published>2008-02-13T03:03:00Z</published><updated>2008-02-13T03:03:00Z</updated><content type="html">&lt;P&gt;After I &lt;A class="" href="http://blogs.msdn.com/gabhan_berry/archive/2008/01/30/excel-and-managed-code-how-does-that-work.aspx" mce_href="http://blogs.msdn.com/gabhan_berry/archive/2008/01/30/excel-and-managed-code-how-does-that-work.aspx"&gt;posted about getting up-and-running with managed code and Excel&lt;/A&gt;, I realised that I was really writing a brief introduction to coding a C#&amp;nbsp;Excel addin. Then I realised that there are two more areas that need to be covered before we would be ready to start building a proper Excel addin in C# (and by proper I mean one that can be used by real Excel users to do real stuff). These are:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Customising the ribbon;&lt;/LI&gt;
&lt;LI&gt;Trapping Excel events;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The ribbon is an Office-wide feature and has been covered in detail in other blogs and MSDN articles, so we won't cover it in detail here. A good article&amp;nbsp;about the ribbon can be found &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/aa338202.aspx#OfficeCustomizingRibbonUIforDevelopers_Dynamically" mce_href="http://msdn2.microsoft.com/en-us/library/aa338202.aspx#OfficeCustomizingRibbonUIforDevelopers_Dynamically"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Instead, we'll focus on event handling in C# and how it compares to VBA.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Excel Event Overview&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Excel events are COM events. They are defined in COM interfaces exported from Excel.exe. When we trap these events from VBA we're not really aware of the underlying mechanisms that enable Excel to callback into our code. The sinking and dispatching just happens automagically for us..&lt;/P&gt;
&lt;P mce_keep="true"&gt;There are two broad parts of event handling: the event source; and&amp;nbsp;the event handler. In the case of Excel, the event source is an instance of the Excel class&amp;nbsp;that defines the event, such as a Workbook instance or a Worksheet instance. The event handler (or subscriber as some people call it) is the custom code (i.e., our code) that is invoked by the event source when the event happens. &lt;/P&gt;
&lt;P mce_keep="true"&gt;The event source publishes a defined event signature which all event handlers must adhere to. As long as a handler adheres to this signature, the event source can invoke it when required.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Let's take an example: the Workbook.Open event. &lt;/P&gt;
&lt;P mce_keep="true"&gt;When we use the VBA object browser to&amp;nbsp;look at the definition of the Workbook class we&amp;nbsp;can see that the&amp;nbsp;event is called Open() and has a special lightning bolt symbol next to it indicating that it is an event.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/7682911/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/7682911/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;What the object browser did was look at the COM type library metadata for the Workbook class. As well as containing all the methods and properties of the Workbook class the type library also contains the published event signatures. The event signatures have special attributes applied to them. To see these, we use the OleView.exe tool to generate IDL from Excel.exe (note that this is a part of COM generally well hidden from Visual Basic. If you code COM components in C++ then this is should be very familiar to you). &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/7682914/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/7682914/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Notice that the Workbook class has two interfaces: _Workbook and WorkbookEvents. Notice also that the WorkbookEvents interface has an attribute named: source. This tells COM that the WorkbookEvents interface is an event source for the Workbook class.&lt;/P&gt;
&lt;P mce_keep="true"&gt;COM has its way of handling events and .NET has its and, through the magic of COM interop, we can tie these two disparate programming models together. This means that we can have a COM event source and a .NET event handler.&lt;/P&gt;
&lt;P mce_keep="true"&gt;However, the code we need to write to handle events in C# is very different from what we are used to writing in VBA. When we are coding in VBA,&amp;nbsp;most of the event mechanism and underlying framework is&amp;nbsp;hidden from us ... but not so in C#.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Delegates, Events and Excel&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;To C#, a COM event looks very much like a .NET event. This greatly simplifies things for .NET developers. However, if you are a VBA Excel developer moving to C#, the event mechanism in .NET seems complex and doing something simple, like handling the Workbook.Open event, can&amp;nbsp;look like a mystery. &amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;The first step to demystifying&amp;nbsp;this is to understand what a delegate is. &lt;/P&gt;
&lt;P mce_keep="true"&gt;A delegate is a special type of .NET class used in the .NET event mechanism.&amp;nbsp;Think of them as being wrappers of function pointers. In COM an event is defined by its function signature whereas, in .NET, it is defined by a delegate but they both&amp;nbsp;play the same role: they both define the contract between the event source and the event handler.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Let's take an example. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Let's say we are defining an event in our&amp;nbsp;C# class called OnClick.&amp;nbsp;We&amp;nbsp;have to define the signature of the event. In C# this means defining a delegate and declaring the event to be of that (delegate) type. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Here's an example delegate and event definition:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;public&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: blue"&gt;delegate&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;OnClickDelegate&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; Title);&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;event&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;OnClickDelegate&lt;/SPAN&gt; OnClick;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;
&lt;P mce_keep="true"&gt;If we took out the &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;delegate&lt;/SPAN&gt; &lt;/FONT&gt;keyword, &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;OnClickDelegate &lt;/FONT&gt;&lt;/SPAN&gt;would look just like a function definition.&amp;nbsp;Having the keyword&amp;nbsp;&lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;delegate&lt;/SPAN&gt; &lt;/FONT&gt;there wraps the function definition up into a&amp;nbsp;type safe class. We then declare&amp;nbsp;our OnClick event as being of type &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;OnClickDelegate&lt;/FONT&gt;&lt;/SPAN&gt;. This is us saying: we want&amp;nbsp;an event called OnClick that has the&amp;nbsp;signature defined by the &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;OnClickDelegate &lt;/FONT&gt;&lt;/SPAN&gt;thus, all event handlers have to have the same signature as &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;OnClickDelegate&lt;/FONT&gt;&lt;/SPAN&gt;.&lt;/P&gt;
&lt;P mce_keep="true"&gt;At first, this&amp;nbsp;seems overly complex ... but&amp;nbsp;it's not really. It just takes a little getting used to (especially if you are from a VB background). If you ever coded in C/C++ and were used to passing around function pointers, this seems a wonderful step forward. Actually, it's&amp;nbsp;one of&amp;nbsp;my favourite parts of .NET&amp;nbsp;:o)&lt;/P&gt;
&lt;P mce_keep="true"&gt;So, what's this got to do with Excel programming? &lt;/P&gt;
&lt;P mce_keep="true"&gt;Well, if you want to be able to&amp;nbsp;handle&amp;nbsp;Excel events in C# you have to understand delegates. &amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Handling Excel Events&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;So,&amp;nbsp;let's take a look at what the C# code for handling Excel events looks like. For example, how do we handle the SheetSelectionChange event of the Application class? &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;_application.SheetSelectionChange += &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; Excel.&lt;SPAN style="COLOR: #2b91af"&gt;AppEvents_SheetSelectionChangeEventHandler&lt;/SPAN&gt;(_application_SheetSelectionChange);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; _application_SheetSelectionChange(&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;object&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; Sh, Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Range&lt;/SPAN&gt; Target) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;FONT color=#008000 size=2&gt;//event handler code here&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;
&lt;P mce_keep="true"&gt;The first line creates a delegate of type &lt;FONT face="Courier New"&gt;Excel.&lt;SPAN style="COLOR: #2b91af"&gt;AppEvents_SheetSelectionChangeEventHandler &lt;/SPAN&gt;&lt;/FONT&gt;and adds to to the application object's SheetSelectionChange event. In the constructor of the delegate we pass the address of the function that the delegate encapsulates, in this case it is the &lt;FONT face="Courier New"&gt;_application_SheetSelectionChange &lt;/FONT&gt;function but it could be any function that has the same signature as the &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;AppEvents_SheetSelectionChangeEventHandler &lt;/FONT&gt;&lt;/SPAN&gt;delegate. &lt;/P&gt;
&lt;P mce_keep="true"&gt;This is a subtle but important point, especially if you are used to coding VBA. In VBA we cannot specify the name of our event handler functions because the name indicates which event is being handled on which object. But in C# the event handler name is not important; what is important is the signature of the function. So, although our event handler is called &lt;FONT face="Courier New"&gt;_application_SheetSelectionChange &lt;/FONT&gt;which looks exactly like the name we'd use in VBA, we are free to change its name to anything we like as long as it still returns &lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; &lt;/SPAN&gt;and takes an &lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;object &lt;/SPAN&gt;and &lt;FONT face="Courier New"&gt;Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Range&lt;/SPAN&gt;&amp;nbsp;&lt;/FONT&gt; as parameters.&lt;/P&gt;
&lt;P mce_keep="true"&gt;So, to summarise: every time we want to handle an Excel event, we have to create an instance of the corresponding delegate and supply&amp;nbsp;the address of a compatible function which the delegate encapsulates. This function&amp;nbsp;is invoked by Excel when the event occurs. &lt;/P&gt;
&lt;P mce_keep="true"&gt;But how do we know which delegate to create? In the example above, we created an instance of &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;AppEvents_SheetSelectionChangeEventHandler &lt;/FONT&gt;&lt;/SPAN&gt;but how did we know that and where do we go to find out the delegate types?&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Excel's&amp;nbsp;Delegate Names and COM Event Sources&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;When it comes to knowing which delegate type to use, Visual Studio comes to our rescue. Visual Studio detects that we are assigning a new delegate to an event and offers to auto-complete; generating both the delegate creation code and also an event handler function which complies to the delegate's signature. &lt;/P&gt;
&lt;P mce_keep="true"&gt;So, consuming events is typically a case of typing &amp;lt;object name&amp;gt;.&amp;lt;event name&amp;gt; += &amp;lt;press tab twice to accept auto complete's delegate creation and function generation&amp;gt;. &lt;/P&gt;
&lt;P mce_keep="true"&gt;But, its worth taking a deeper look at Excel's delegate names as it sheds some light on the underlying COM event interfaces.&lt;/P&gt;
&lt;P mce_keep="true"&gt;If we look at the Application class's RCW (the ApplicationClass) in the Visual Studio Object Browser we see that it implements a number of interfaces. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/7697556/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/7697556/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Notice that one of the interfaces is called AppEvents_Event. Remember that these interfaces are proxies/wrappers of COM interfaces, so, let's now look at the COM definition of the Application CoClass using OleView.exe. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/7697558/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/7697558/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;The Application CoClass&amp;nbsp;implements the AppEvents interface.&amp;nbsp;Also, the IDL tells us the the AppEvents&amp;nbsp;COM interface is an event source interface&amp;nbsp;for the Application CoClass. So, it turns out that the events for the Application class are actually all defined in one COM interface: the AppEvents interface. This is also something that is hidden from us when we are coding in VBA. &lt;/P&gt;
&lt;P mce_keep="true"&gt;If we take a look at the definition of the COM AppEvents interface and the .NET AppEvents_Event interface we will see that they each define the Application events in their respective ways.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/7697817/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/7697817/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;So, the AppEvents_Event interface in the PIA wraps up the AppEvents COM interface; the ApplicationClass in the PIA implements the AppEvent_Event interface and the Application CoClass in COM implements the AppEvents COM interface.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Given this we can now understand how the delegate names are generated, thus:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;lt;COM Interface Name&amp;gt;_&amp;lt;EventName&amp;gt;EventHandler&lt;/P&gt;
&lt;P mce_keep="true"&gt;i.e. &lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT face="Courier New"&gt;AppEvents_SheetSelectionChangeEventHandler&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Summary&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Hopefully, this has laid out in clear terms out how we handle Excel events in C#. I have stayed away from talking about the specifics of how COM events actually work but this is a subject covered in detail on MSDN. What's more important to us, from an Excel point of view, is&amp;nbsp;understanding the Excel event interfaces and how to&amp;nbsp;use them from C#.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The key points to take away are:&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Excel events are COM events;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Delegates are strongly typed wrappers of&amp;nbsp;function pointers;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;.NET events use delegates to invoke event handling functions;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;The name of the event handling function is not important - it is the signature of the function that is important;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Excel's COM classes have COM event interfaces and these map to the .NET RCWs in the Excel PIA;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7657803" width="1" height="1"&gt;</content><author><name>Gabhan Berry</name><uri>http://blogs.msdn.com/members/Gabhan+Berry.aspx</uri></author><category term="Addins" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/Addins/default.aspx" /><category term="C#" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/C_2300_/default.aspx" /><category term=".NET" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/.NET/default.aspx" /></entry><entry><title>The Woes of Excel's Optional Parameters and C# ... a (potential) Workaround </title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/gabhan_berry/archive/2008/02/06/excel-s-optional-parameters-and-missing-value-a-c-workaround.aspx" /><id>http://blogs.msdn.com/gabhan_berry/archive/2008/02/06/excel-s-optional-parameters-and-missing-value-a-c-workaround.aspx</id><published>2008-02-06T22:55:00Z</published><updated>2008-02-06T22:55:00Z</updated><content type="html">&lt;P&gt;When coding in C# with Excel, it doesn't take long before you encounter the dreaded 'optional parameter' issue. If you have ever copied-and-pasted numerous &lt;FONT face="Courier New"&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value&lt;/FONT&gt;&amp;nbsp;statements then you've probably wondered a few things. &lt;/P&gt;
&lt;P&gt;Firstly, what is this and why is it happening? Secondly, how do I&amp;nbsp;get round it?&lt;/P&gt;
&lt;P&gt;In this post, I'll offer answers to those questions.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;What's the Problem with Optional Parameters?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;As you know, some of Excel's APIs (such as&amp;nbsp;Application.Intersect or Range.Sort) use optional parameters . When you are coding in VBA you hardly notice this but it's a whole different story in C#.&lt;/P&gt;
&lt;P&gt;As I briefly covered in &lt;A class="" href="http://blogs.msdn.com/gabhan_berry/archive/2008/01/30/excel-and-managed-code-how-does-that-work.aspx" mce_href="http://blogs.msdn.com/gabhan_berry/archive/2008/01/30/excel-and-managed-code-how-does-that-work.aspx"&gt;my introduction to managed programming and Excel&lt;/A&gt;, when you use a managed language to code against Excel, Excel's API is exposed as a collection of Runtime Callable Wrappers (RCWs). These are managed classes that have the same methods and properties as the COM classes they wrap. When you call Application.Intersect from C# you are really calling Application.Intersect on the RCW. The RCW then internally&amp;nbsp;marshals the call to the real, COM Application.Intersect.&lt;/P&gt;
&lt;P&gt;In other words, the RCWs expose managed wrappers of the COM methods. &amp;nbsp;&lt;/P&gt;
&lt;P&gt;However, the methods and properties that have optional parameters in COM are &lt;STRONG&gt;not&lt;/STRONG&gt; optional in C#. As a C# programmer, you have to supply a value for every single parameter, regardless of whether or not it is optional in COM.&lt;/P&gt;
&lt;P&gt;At first glance, this seems&amp;nbsp;like not such a big deal. That is, however,&amp;nbsp;until you realise that some methods (like Application.Intersect) take 30 parameters; 28 of which are optional!&lt;/P&gt;
&lt;P&gt;Suddenly, having to specify a value for every single parameter becomes tedious and messy and litters your code with statements such as:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;_application.Intersect(&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;rng1,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;rng2,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value);&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10.5pt; LINE-HEIGHT: 115%; mso-bidi-font-size: 11.0pt"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Is this a .NET Problem?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;No. The CLR supports optional parameters. This is a C# problem (Incidentally, VB.NET doesn't have this issue).&lt;/P&gt;
&lt;P mce_keep="true"&gt;To underline this point, let's leave C# for a moment and&amp;nbsp;jump into what&amp;nbsp;managed code&amp;nbsp;is compiled to: MSIL.&amp;nbsp;We'll disassemble Excel's RCWs and take a look at the MSIL they contain. This gives us a language agnostic view of what the RCW is really defined as.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The following screenshot shows the MSIL of the Application.Intersect method.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.msdn.com/photos/gabhan_berry/images/7500211/original.aspx" mce_src="http://blogs.msdn.com/photos/gabhan_berry/images/7500211/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;What to notice here is&amp;nbsp;that the first two parameters are of type Microsoft.Office.Interop.Excel.Range but that the rest are of type object and they are also decorated with the [opt] attribute. &lt;/P&gt;
&lt;P mce_keep="true"&gt;When you call this method from&amp;nbsp;C# you are forced to specify a value for every parameter because C# (not .NET) doesn't support optional parameters. &lt;/P&gt;
&lt;P mce_keep="true"&gt;It's worth noting that this is also not an Excel problem. Any COM library that uses optional parameters will have the same problem when accessed from C#.&lt;/P&gt;
&lt;P mce_keep="true"&gt;So, what can we do about this? &lt;/P&gt;
&lt;P mce_keep="true"&gt;The obvious answer is: 'don't use C# use VB.NET instead' but this isn't really an option for those programmers who (for other reasons) may want to use C#.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Therefore, is there anything we can do in C# to make the story a little better?&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Working Around the Problem&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;The most common workaround I know of is to create wrapper classes of the RCWs.&amp;nbsp;For example,&amp;nbsp;we could write a wrapper of the Microsoft.Office.Interop.Excel.ApplicationClass class with more friendly C# function signatures. Internally, our wrapper would still have to make the call to the RCW with a value for all parameters but our wrapper would expose a nicer programming interface which we would use throughout our program. This&amp;nbsp;means that the messy call to the RCW happens in just one place in our code rather than in multiple. &lt;/P&gt;
&lt;P mce_keep="true"&gt;The big problem with this workaround is that the Application class has quite a lot of methods and properties and duplicating them all is time consuming. Also, we'd have to do the same thing for the Range class and the Workbook class and every other (Excel) class that we use.&lt;/P&gt;
&lt;P mce_keep="true"&gt;We could, instead, just wrap up the functions that we care about. So, instead of wrapping every function we only wrap the the Excel functions we use in our program. This is a much smaller task and the is the route most people (I think) have taken. But it's still not ideal and it's not very generic. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Therefore, is there another option? &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Using Reflection to&amp;nbsp;Dynamically&amp;nbsp;Invoke Functions at Runtime&lt;/STRONG&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;.NET assemblies have lots of metadata in them which can be accessed at runtime via a technology known as Reflection. Reflection, in .NET, is hugely powerful and is a massive subject in its own right. But one of the things it enables us to do is to invoke methods by name at runtime. &lt;/P&gt;
&lt;P mce_keep="true"&gt;When our code is compiled, the compiler ensures that&amp;nbsp;we have used the correct function signatures and types. If we haven't, the compiler emits an error.&amp;nbsp;Reflection in .NET allows us&amp;nbsp;to discover function signatures and parameter types at runtime.&amp;nbsp;We can&amp;nbsp;then go ahead and&amp;nbsp;invoke these functions 'adhoc' at runtime; bypassing the type checking and validation normally done by the compiler. If we use the wrong function signature or the wrong data type we'll get a runtime error rather than a compile-time error.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Let's take our example of calling Application.Intersect. The C# compiler requires us to specify a value for all 30 parameters. If we don't do this, the compilation fails. There's no way round this ... unless we don't&amp;nbsp;actually tell the compiler that we are invoking the Intersect method.&lt;/P&gt;
&lt;P mce_keep="true"&gt;In the remainder of this post, I'll introduce a C# class I've written that uses .NET reflection.&amp;nbsp;The class invokes methods and properties of Excel RCWs dynamically at runtime, thus, hiding from the compiler what we are really doing and removing the need for us to specify a value for all optional parameters.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;The ExcelUtility Class&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;This class is very small and is mostly defined in about 30&amp;nbsp;lines of code. However, in these few lines I make use of reflection and generics and my explanation assumes you have some basic knowledge of these two topics.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The important method in the ExcelUtility class is the Invoke method. This method contains the code which discovers function signatures at runtime and handles the invocation of them.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;static&lt;/SPAN&gt; TRet Invoke&amp;lt;TRet&amp;gt;(&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt; Obj, &lt;SPAN style="COLOR: #2b91af"&gt;Type&lt;/SPAN&gt; ObjType, &lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; MethodName, &lt;SPAN style="COLOR: blue"&gt;params&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[] CallerParams) &lt;SPAN style="COLOR: blue"&gt;where&lt;/SPAN&gt; TRet : &lt;SPAN style="COLOR: blue"&gt;class&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;o:p&gt;&lt;FONT face=Calibri size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;The &lt;FONT face="Courier New"&gt;MethodName &lt;/FONT&gt;parameter is, well, the name of the method we want to call on the RCW. For example, if we want to call Application.Intersect then we set MethodName to the string "Intersect". &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face="Courier New"&gt;ObjType &lt;/FONT&gt;is the Type object of the class which we are invoking. The framework contains a class called Type which represents the metadata of data types. Every class has a Type which can be accessed at runtime. For the Excel Application class (well, the RCW) we get its Type object using &lt;FONT color=#0000ff size=2&gt;typeof&lt;/FONT&gt;&lt;FONT size=2&gt;(Microsoft.Office.Interop.Excel.&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;ApplicationClass&lt;/FONT&gt;&lt;FONT size=2&gt;).&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face="Courier New"&gt;Obj &lt;/FONT&gt;is the actual object which we want to invoke i.e. the Application instance.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;Finally, the &lt;FONT face="Courier New"&gt;CallerParams &lt;/FONT&gt;array contains the parameters that the caller wants to pass into the function call. So, in the case of calling Application.Intersect, we would supply the range objects&amp;nbsp;we want to intersect.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;Notice that Invoke is a generic method. The generic parameter, &lt;FONT face="Courier New"&gt;TRet&lt;/FONT&gt;, specifies the type of the object to return. Invoke will attempt to cast the result of the dynamic function call to this type. So, if the method we are invoking returns a string then we specify &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;&lt;/FONT&gt;as the generic parameter i.e. &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; val = Invoke&amp;lt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&amp;gt;( ... )&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;Let's now look at the method's code.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;public&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: blue"&gt;static&lt;/SPAN&gt; TRet Invoke&amp;lt;TRet&amp;gt;(&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt; Obj, &lt;SPAN style="COLOR: #2b91af"&gt;Type&lt;/SPAN&gt; ObjType, &lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; MethodName, &lt;SPAN style="COLOR: blue"&gt;params&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[] CallerParams) &lt;SPAN style="COLOR: blue"&gt;where&lt;/SPAN&gt; TRet : &lt;SPAN style="COLOR: blue"&gt;class&lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;&amp;nbsp; MemberInfo&lt;/SPAN&gt;[] memberInfo = ObjType.GetMember(MethodName, &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Public |&lt;SPAN style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp; BindingFlags&lt;/SPAN&gt;.IgnoreCase | &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Instance);&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;&amp;nbsp; BindingFlags&lt;/SPAN&gt; memberTypeFlag;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; int&lt;/SPAN&gt; paramCount = 0;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; switch&lt;/SPAN&gt; (memberInfo[0].MemberType) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;default&lt;/SPAN&gt;:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; case&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;MemberTypes&lt;/SPAN&gt;.Method:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;MethodInfo&lt;/SPAN&gt; methodInfo = ObjType.GetMethod(MethodName, &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Public |&lt;SPAN style="COLOR: #2b91af"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; BindingFlags&lt;/SPAN&gt;.IgnoreCase | &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Instance);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;paramCount = methodInfo.GetParameters().Length;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;memberTypeFlag = &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.InvokeMethod;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;break&lt;/SPAN&gt;;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; case&lt;/SPAN&gt; &lt;SPAN style="COLOR: #2b91af"&gt;MemberTypes&lt;/SPAN&gt;.Property:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;PropertyInfo&lt;/SPAN&gt; propInfo = ObjType.GetProperty(MethodName, &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Public | &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.IgnoreCase | &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Instance);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;paramCount = propInfo.GetIndexParameters().Length;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;memberTypeFlag = &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.GetProperty;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;break&lt;/SPAN&gt;;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp; }&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; object&lt;/SPAN&gt;[] paramArray = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[paramCount];&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; i = 0; i &amp;lt; paramCount; ++i) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; paramArray[i] = &lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp; }&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; if&lt;/SPAN&gt; (CallerParams != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CallerParams.CopyTo(paramArray, 0);&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&amp;nbsp; TRet ret = Obj.GetType().InvokeMember(MethodName, memberTypeFlag | &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Instance&amp;nbsp;&amp;nbsp; |&lt;SPAN style="COLOR: #2b91af"&gt;&amp;nbsp;BindingFlags&lt;/SPAN&gt;.Public, &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;, Obj, paramArray) &lt;SPAN style="COLOR: blue"&gt;as&lt;/SPAN&gt; TRet;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; return&lt;/SPAN&gt; ret;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;The basic idea is this. First, get the metadata for the member specified in &lt;FONT face="Courier New"&gt;MethodName &lt;/FONT&gt;and then store how many parameters the member takes. We also use a bitmap (&lt;FONT face="Courier New"&gt;memberTypeFlag&lt;/FONT&gt;) to store whether the member is a method or a property (this is used later). &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;Next, we create an array of objects. the size of the array is equal to the number of parameters the method/property needs. We also initialise every object in that array to &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value. &lt;/FONT&gt;So if the method takes 30 parameters &lt;FONT face="Courier New"&gt;paramArray &lt;/FONT&gt;will have 30 objects in it, each set to &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value&lt;/FONT&gt;.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;We then copy the parameters in&amp;nbsp;&lt;FONT face="Courier New"&gt;CallerParams&amp;nbsp;&lt;/FONT&gt;into&amp;nbsp;&lt;FONT face="Courier New"&gt;paramArray&lt;/FONT&gt; . So, if &lt;FONT face="Courier New"&gt;CallerParams &lt;/FONT&gt;had two objects in it, &lt;FONT face="Courier New"&gt;paramArray&lt;/FONT&gt; would have 30 objects with the first two being the same as those specified in &lt;FONT face="Courier New"&gt;CallerParams &lt;/FONT&gt;(i.e. the parameters we care about) and the remaining 28 being set to &lt;FONT face="Courier New"&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value&lt;/FONT&gt;.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;Finally, we invoke the method/property passing in &lt;FONT face="Courier New"&gt;paramArray&lt;/FONT&gt;&amp;nbsp;as its parameters and casting the result to an object of type &lt;FONT face="Courier New"&gt;TRet &lt;/FONT&gt;and returning it to the caller.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;So to summarise, Invoke takes an object reference and a name of a method. It then figures out how many parameters the method expects and ensures that it supplies any missing parameters not specified by the caller. That is, the caller only needs to supply the parameters it cares about; Invoke will fill-in-the-blanks.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;&lt;STRONG&gt;Using ExcelUtility&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;The Invoke&amp;nbsp;method will call methods on any class. But using it directly means that we have to constantly specify which class we want to use. So, to make&amp;nbsp;our lives&amp;nbsp;a little simpler, I have added wrapper functions that can be used with the Application and Range classes.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;These functions are all one-liners and simply reduce the number of parameters we need to pass when using the ExcelUtility in our code. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;Here's the wrapper function for invoking the Application class (the Range function wrapper can be obviously deduced).&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;public&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; &lt;SPAN style="COLOR: blue"&gt;static&lt;/SPAN&gt; TRet ApplicationInvoke&amp;lt;TRet&amp;gt;(&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt; Obj, &lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; MethodName, &lt;SPAN style="COLOR: blue"&gt;params&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[] Params) &lt;SPAN style="COLOR: blue"&gt;where&lt;/SPAN&gt; TRet : &lt;SPAN style="COLOR: blue"&gt;class&lt;/SPAN&gt; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;FONT color=#000000&gt;&amp;nbsp; &lt;/FONT&gt;return&lt;/SPAN&gt; Invoke&amp;lt;TRet&amp;gt;(Obj, &lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(Excel.&lt;SPAN style="COLOR: #2b91af"&gt;ApplicationClass&lt;/SPAN&gt;), MethodName, Params);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;So, let's take a look at how the ExcelUtility class changes the landscape. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;Using the RCWs directly, to invoke Application.Intersect for two ranges (rng1 and rng2) we have to write:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;Excel.&lt;SPAN style="COLOR: #2b91af"&gt;&lt;FONT size=2&gt;Range &lt;/FONT&gt;&lt;/SPAN&gt;rng = _application.Intersect(&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;rng1,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;rng2,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 9pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-bidi-font-size: 10.0pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value);&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;With the ExcelUtility class, this changes to:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #2b91af; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;Excel.&lt;/FONT&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Range &lt;SPAN style="FONT-SIZE: 10pt; COLOR: #2b91af; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;rng &lt;/FONT&gt;&lt;/SPAN&gt;= &lt;/SPAN&gt;ExcelUtility&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;.ApplicationInvoke&amp;lt;Excel.&lt;SPAN style="COLOR: #2b91af"&gt;Range&lt;/SPAN&gt;&amp;gt;(_application, &lt;SPAN style="COLOR: #a31515"&gt;"Intersect"&lt;/SPAN&gt;, rng1, rng2);&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;(where&amp;nbsp;&lt;FONT face="Courier New"&gt;_application&lt;/FONT&gt; is our instance of&amp;nbsp;Excel's application object).&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;Quite a difference...&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;&lt;STRONG&gt;Great ... but not so great ...&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;On the surface, it looks like a nice solution. But there are downsides to this workaround that become apparent once you start using it for real. &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;First of all ... things start looking not so nice again when you invoke methods/properties with a non-optional parameter in the middle of a list of optional ones. For example, the Range.Address property has 5 parameters. The first two are optional, as are the last two, but the third parameter is non-optional.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;Directly invoking the RCW to get Range.Address means writing: &lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;string&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt; addr = _columnRange.get_Address(&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Microsoft.Office.Interop.Excel.&lt;SPAN style="COLOR: #2b91af"&gt;XlReferenceStyle&lt;/SPAN&gt;.xlA1,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;System.Reflection.&lt;SPAN style="COLOR: #2b91af"&gt;Missing&lt;/SPAN&gt;.Value&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;);&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;and using ExcelUtility we do:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;addr = &lt;SPAN style="COLOR: #2b91af"&gt;ExcelUtility&lt;/SPAN&gt;.RangeInvoke&amp;lt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&amp;gt;(_columnRange, &lt;SPAN style="COLOR: #a31515"&gt;"Address"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;, Microsoft.Office.Interop.Excel.&lt;SPAN style="COLOR: #2b91af"&gt;XlReferenceStyle&lt;/SPAN&gt;.xlA1);&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;I'd say that wasn't much of an improvement.&amp;nbsp;It might even be worse.&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;(Note that we specify the property name&amp;nbsp;&lt;SPAN style="COLOR: #a31515"&gt;&lt;FONT face="Courier New"&gt;"Address"&lt;/FONT&gt;&lt;/SPAN&gt; in the call to RangeInvoke where as&amp;nbsp;the RCW uses a &lt;FONT face="Courier New"&gt;get_Address&lt;/FONT&gt; method. This is because C# does not support properties with parameters -&amp;nbsp;but that's another topic).&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;Second problem ... we only find out about coding errors at runtime. Because we are hiding the call to the RCW from the compiler we won't get any compilation errors if we use the wrong data types or incorrectly spell a function name. If, for example, we try to invoke the &lt;SPAN style="COLOR: #a31515"&gt;&lt;FONT face="Courier New"&gt;"Addres s" &lt;/FONT&gt;&lt;/SPAN&gt;property - our code will compile. It will only be at runtime that we get an error (and even then the error message might not be that useful in figuring out our mistake). This means that we need to already know (or have looked up) the signatures of all the Excel APIs we are calling.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;Third problem ... when the method we are calling on the RCW does not have optional parameters, calling the RCW directly is nicer. So, ExcelUtility isn't always a good replacement for calling the RCW directly. It's more like something that should be used when there are optional parameters.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;&lt;STRONG&gt;Summary&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;What I've presented here is an idea for how we can workaround the problem of optional parameters in Excel's API when coding in C#. I should point out that it's just my idea and isn't a Microsoft recommended solution. Also, I have not exhaustively tested this code. By that I mean I haven't tested whether&amp;nbsp;this works with every single method and property in the Excel API so there may be (and likely are) cases where&amp;nbsp;this fails.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;These are the key points:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;ExcelUtility uses reflection to discover function signatures at runtime;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;The Invoke method fills-in-the-blanks; we only have to specify the parameters we care about (most of the time);&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;Because&amp;nbsp;we don't tell the compiler which methods we are invoking,&amp;nbsp;we only&amp;nbsp;get told of errors at runtime;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;To call a method or a property on the Application class, use the ApplicationInvoke method;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;To call a method or a property on the Range class, use the RangeInvoke method;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;The main method is Invoke which can be used (in theory) to call methods on any class;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;&lt;STRONG&gt;Download the Source Code&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;I have published ExcelUtility.cs to the MSDN Code Gallery and it can be downloaded by clicking on the link below (go to the &lt;STRONG&gt;Releases&lt;/STRONG&gt; tab to download).&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;&lt;A class="" href="http://code.msdn.microsoft.com/ExcelUtility" mce_href="http://code.msdn.microsoft.com/ExcelUtility"&gt;Click here to download&lt;/A&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7497238" width="1" height="1"&gt;</content><author><name>Gabhan Berry</name><uri>http://blogs.msdn.com/members/Gabhan+Berry.aspx</uri></author><category term="Addins" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/Addins/default.aspx" /><category term="C#" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/C_2300_/default.aspx" /><category term="Automation" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/Automation/default.aspx" /></entry><entry><title>Creating Custom Calculated Members and Sets in OLAP PivotTables </title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/gabhan_berry/archive/2008/02/06/creating-custom-calculated-members-and-sets-in-olap-pivottables.aspx" /><id>http://blogs.msdn.com/gabhan_berry/archive/2008/02/06/creating-custom-calculated-members-and-sets-in-olap-pivottables.aspx</id><published>2008-02-06T22:45:00Z</published><updated>2008-02-06T22:45:00Z</updated><content type="html">&lt;P&gt;If you are using PivotTables against an OLAP data source you may find it useful to be able to create your own custom, calculated measures and sets. These calculations are client-side meaning they exist inside Excel and you don't have to change the server-side OLAP cube.&lt;/P&gt;
&lt;P&gt;Excel does not enable you to do this using the user interface, however, you can do this via the API.&lt;/P&gt;
&lt;P&gt;Allan Folting (our PivotTable expert) has published a post&amp;nbsp;showing how to do this using VBA&amp;nbsp;over in the team's blog.&lt;/P&gt;
&lt;P&gt;&lt;A class="" href="http://blogs.msdn.com/excel/archive/2008/02/05/common-questions-around-excel-2007-OLAP-PivotTables.aspx" mce_href="http://blogs.msdn.com/excel/archive/2008/02/05/common-questions-around-excel-2007-OLAP-PivotTables.aspx"&gt;Click here to read his post.&lt;/A&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7497054" width="1" height="1"&gt;</content><author><name>Gabhan Berry</name><uri>http://blogs.msdn.com/members/Gabhan+Berry.aspx</uri></author><category term="VBA" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/VBA/default.aspx" /><category term="PivotTables" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/PivotTables/default.aspx" /></entry><entry><title>MSDN Code Gallery</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/gabhan_berry/archive/2008/02/05/msdn-code-gallery.aspx" /><id>http://blogs.msdn.com/gabhan_berry/archive/2008/02/05/msdn-code-gallery.aspx</id><published>2008-02-05T23:02:00Z</published><updated>2008-02-05T23:02:00Z</updated><content type="html">&lt;P&gt;We have recently launched a code sharing community web site called &lt;A class="" href="http://code.msdn.microsoft.com/" mce_href="http://code.msdn.microsoft.com/"&gt;MSDN Code Gallery&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;MSDN Code Gallery hosts code snippets and entire projects that have been shared with the community. You can publish your own code or search for and download other peoples' code.&lt;/P&gt;
&lt;P&gt;There are lots of nice features on the web site.&amp;nbsp;For example, when you publish code, the site&amp;nbsp;enables issue tracking, discussions, comments&amp;nbsp;and RSS feeds pertaining to your release. &lt;/P&gt;
&lt;P&gt;The basic format is that you create resource pages. These pages each have descriptions, versioning etc. and contain releases. Each release is a file. It&amp;nbsp;can be a code snippet or documentation or any other useful file. You search the gallery using tags or using the embedded Live search. Also, the web site automatically enforces the Microsoft Public License on all the source code downloads.&lt;/P&gt;
&lt;P&gt;All in all, it seems like a great idea, so, I'll be publishing all my source code to the MSDN Code Gallery.&lt;/P&gt;
&lt;P&gt;If you're interested in publishing your own code,&amp;nbsp;you can find out&amp;nbsp;how to do it &lt;A class="" href="http://code.msdn.microsoft.com/CodeGallery" mce_href="http://code.msdn.microsoft.com/CodeGallery"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;As an example, the&amp;nbsp;resource page&amp;nbsp;for my post on filtering a&amp;nbsp;PivotTable&amp;nbsp;using&amp;nbsp;cell contents&amp;nbsp;has been published &lt;A class="" href="http://code.msdn.microsoft.com/CellFilterPivot" mce_href="http://code.msdn.microsoft.com/CellFilterPivot"&gt;here&lt;/A&gt;. The workbook can be downloaded&amp;nbsp;from the &lt;STRONG&gt;Releases&lt;/STRONG&gt; tab.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7473501" width="1" height="1"&gt;</content><author><name>Gabhan Berry</name><uri>http://blogs.msdn.com/members/Gabhan+Berry.aspx</uri></author><category term="C#" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/C_2300_/default.aspx" /><category term="VBA" scheme="http://blogs.msdn.com/gabhan_berry/archive/tags/VBA/default.aspx" /></entry></feed>