<?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">.NET4Office</title><subtitle type="html">A blog by Eric Carter</subtitle><id>http://blogs.msdn.com/b/eric_carter/atom.aspx</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/eric_carter/" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/b/eric_carter/atom.aspx" /><generator uri="http://telligent.com" version="5.6.50428.7875">Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><updated>2009-05-08T00:04:27Z</updated><entry><title>VB Code Samples for the VSTO for Office 2007 Book Now Available</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/eric_carter/archive/2009/11/18/vb-code-samples-for-the-vsto-for-office-2007-book-now-available.aspx" /><id>http://blogs.msdn.com/b/eric_carter/archive/2009/11/18/vb-code-samples-for-the-vsto-for-office-2007-book-now-available.aspx</id><published>2009-11-18T13:24:00Z</published><updated>2009-11-18T13:24:00Z</updated><content type="html">&lt;P&gt;I wanted to make sure everyone knows that VB code samples for the VSTO for Office 2007 book are now available.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;You can download them here:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;A href="http://www.informit.com/content/images/9780321533210/downloads/VB%20Code%20Listings.zip"&gt;http://www.informit.com/content/images/9780321533210/downloads/VB%20Code%20Listings.zip&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;Long live VB!&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9924265" width="1" height="1"&gt;</content><author><name>Eric Carter</name><uri>http://blogs.msdn.com/Eric-Carter/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>8. VSTO Bug Tracker : Using a Ribbon</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/eric_carter/archive/2009/05/14/8-vsto-bug-tracker-using-a-ribbon.aspx" /><id>http://blogs.msdn.com/b/eric_carter/archive/2009/05/14/8-vsto-bug-tracker-using-a-ribbon.aspx</id><published>2009-05-14T21:19:20Z</published><updated>2009-05-14T21:19:20Z</updated><content type="html">&lt;p&gt;To get started, from the Project menu choose Add New Item. In the Add New Item dialog box, click Ribbon (Visual Designer). Then click the Add button. A new Ribbon is created and the Ribbon Designer is displayed. &lt;/p&gt;  &lt;p&gt;Next, click on the Group control that is created for you and change the Label in the Properties window to “Bugs” as well. Drag and drop a Button control from the Toolbox onto the Group control.&amp;#160; Use the Properties window to set the Label for the button to “Add Bug Data”.&amp;#160; Also, set the ControlSize to RibbonControlSizeLarge and set an Image for the button if you like.&amp;#160; Double click on the Button control to add an event handler.&amp;#160; The event handler will invoke the PopulateSpreadsheet method.&amp;#160; You can now remove the SheetBeforeRightClick handler that we added earlier if you like.&lt;/p&gt;  &lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; AddBugData_Click(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; sender &lt;span class="kwrd"&gt;As&lt;/span&gt; System.&lt;span class="kwrd"&gt;Object&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; e &lt;span class="kwrd"&gt;As&lt;/span&gt; Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs) &lt;span class="kwrd"&gt;Handles&lt;/span&gt; AddBugData.Click
        Globals.ThisAddIn.PopulateSpreadsheet(&lt;span class="kwrd"&gt;True&lt;/span&gt;)
    &lt;span class="kwrd"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;
&lt;style type="text/css"&gt;





.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;Then, drag and drop a Gallery control from the Toolbox onto the Group control. Use the Properties window to set the Label for the Gallery control to “Bug Charts”. Also, set the ControlSize to RibbonControlSizeLarge and set an Image for the Gallery control if you like.&lt;/p&gt;

&lt;p&gt;With the Gallery control configured the way we want, let’s write some code behind it. Click on the Gallery control again to select it. Then click on the lightning bolt icon button in the Properties window to show the events for the Gallery control. Three events are displayed. Click is raised when an item in our Items collection is clicked. And ItemsLoading is raised when the user drops down the Gallery control before its contents are displayed—this is the event that can be handled at runtime to modify the Items and Buttons lists before the Gallery control is displayed to the user.&lt;/p&gt;

&lt;p&gt;We want to add handlers for ItemsLoading and Click. First, let’s write the handler for the ItemsLoading event. Double click on the ItemsLoading event in the Properties window and Visual Studio generates an event handler in the code behind the Ribbon and displays the event handler. Add the code below.&amp;#160; What does this code do?&amp;#160; It will dynamically populate the Gallery control with a RibbonDropDownItem for each chart in the workbook.&amp;#160; It sets the RibbonDropDownItem to the image of the chart.&amp;#160; It also tags each RibbonDropDownItem with an identifier that the Click event will use.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; Gallery1_ItemsLoading(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; sender &lt;span class="kwrd"&gt;As&lt;/span&gt; System.&lt;span class="kwrd"&gt;Object&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; e &lt;span class="kwrd"&gt;As&lt;/span&gt; Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs) &lt;span class="kwrd"&gt;Handles&lt;/span&gt; Gallery1.ItemsLoading
        Gallery1.Items.Clear()

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; c &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; s &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.Worksheet
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; tag &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; tempFileName &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; = System.IO.Path.GetTempFileName()

        &lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; s &lt;span class="kwrd"&gt;In&lt;/span&gt; Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets
            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; i &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;
            &lt;span class="kwrd"&gt;For&lt;/span&gt; i = 1 &lt;span class="kwrd"&gt;To&lt;/span&gt; s.ChartObjects.Count
                &lt;span class="kwrd"&gt;Dim&lt;/span&gt; d &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; RibbonDropDownItem
                c = s.ChartObjects(i)

                c.Chart.Export(tempFileName, &lt;span class="str"&gt;&amp;quot;BMP&amp;quot;&lt;/span&gt;)
                &lt;span class="kwrd"&gt;Dim&lt;/span&gt; bmpTemp &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; System.Drawing.Bitmap(tempFileName)
                &lt;span class="kwrd"&gt;Dim&lt;/span&gt; bmpUnlinked &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; System.Drawing.Bitmap(bmpTemp)
                bmpTemp.Dispose()
                d.Image = bmpUnlinked

                d.Tag = tag
                Gallery1.Items.Add(d)
                tag = tag + 1
            &lt;span class="kwrd"&gt;Next&lt;/span&gt;
        &lt;span class="kwrd"&gt;Next&lt;/span&gt;

        System.IO.File.Delete(tempFileName)
    &lt;span class="kwrd"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;

&lt;p&gt;Now click on the Gallery control again to select it, then double click on the Click event in the Properties window and Visual Studio generates an event handler in the code behind the Ribbon and displays the event handler.&amp;#160;&amp;#160; In the Click event we will activate the chart corresponding to the RibbonDropDownItem.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; Gallery1_Click(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; sender &lt;span class="kwrd"&gt;As&lt;/span&gt; System.&lt;span class="kwrd"&gt;Object&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; e &lt;span class="kwrd"&gt;As&lt;/span&gt; Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs) &lt;span class="kwrd"&gt;Handles&lt;/span&gt; Gallery1.Click
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; tagFound &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = Gallery1.SelectedItem.Tag
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; s &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.Worksheet
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; tag &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;

        &lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; s &lt;span class="kwrd"&gt;In&lt;/span&gt; Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets
            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; i &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;
            &lt;span class="kwrd"&gt;For&lt;/span&gt; i = 1 &lt;span class="kwrd"&gt;To&lt;/span&gt; s.ChartObjects.Count
                &lt;span class="kwrd"&gt;If&lt;/span&gt; tagFound = tag &lt;span class="kwrd"&gt;Then&lt;/span&gt;
                    s.ChartObjects(i).Activate()
                    &lt;span class="kwrd"&gt;Exit&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;
                &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
                tag = tag + 1
            &lt;span class="kwrd"&gt;Next&lt;/span&gt;
        &lt;span class="kwrd"&gt;Next&lt;/span&gt;
    &lt;span class="kwrd"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;

&lt;p&gt;When we run the add-in, we get this result when you drop down the gallery control for a document with two charts in it.&amp;#160; The gallery control updates to display images of the current charts in the workbook.&amp;#160; If you click one of the drop down items, it activates the corresponding chart in the workbook.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/7.VSTOBugTrackerUsingaRibbon_11A8B/image_2.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/7.VSTOBugTrackerUsingaRibbon_11A8B/image_thumb.png" width="644" height="440" /&gt;&lt;/a&gt; &lt;style type="text/css"&gt;




.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type="text/css"&gt;




.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/p&gt;

&lt;p&gt;That’s all folks!&amp;#160; Hoped you enjoyed this example of using VSTO.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9616768" width="1" height="1"&gt;</content><author><name>Eric Carter</name><uri>http://blogs.msdn.com/Eric-Carter/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>7. VSTO Bug Tracker : Using Document-Level Features in Add-Ins</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/eric_carter/archive/2009/05/14/7-vsto-bug-tracker-using-document-level-features-in-add-ins.aspx" /><id>http://blogs.msdn.com/b/eric_carter/archive/2009/05/14/7-vsto-bug-tracker-using-document-level-features-in-add-ins.aspx</id><published>2009-05-14T21:18:11Z</published><updated>2009-05-14T21:18:11Z</updated><content type="html">&lt;p&gt;Prior to Visual Studio 2008 SP1, you couldn’t use common VSTO features like controls in the document and databinding to list objects at the add-in level.&amp;#160; But with SP1 we introduced a way for you to use these features at the add-in level.&amp;#160; In this section some of the wierd ways Idid things in section 4 will start to make more sense—I designed the code in Section 4 to be easily portable to an add-in.&lt;/p&gt;  &lt;p&gt;One thing that won’t port to the add-in level is cached data—that feature only works when code is at the document level.&lt;/p&gt;  &lt;p&gt;Choose File &amp;gt; Add &amp;gt; New Project.. and create a new Excel add-in project.&amp;#160; I’ll be using VB in this example.&lt;/p&gt;  &lt;p&gt;Add a web reference to the BugService as described in Article 4.&amp;#160; Be sure to name the reference BugService.&lt;/p&gt;  &lt;p&gt;Now, double click on your ThisAddIn file.&amp;#160; In the ThisAddIn class, add this as a member variable.&amp;#160; We won’t be adding any our dataset as a member variable because we can’t cache it at the add-in level, so there is no reason to make it a class member variable.&lt;/p&gt;  &lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;Public&lt;/span&gt; buttonDictionary &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; Dictionary(Of Excel.Worksheet, Microsoft.Office.Tools.Excel.Controls.Button)&lt;/pre&gt;

&lt;p&gt;Next, we will put some calls to our AddListObjectAndButton function.&amp;#160; Add an event handler for the NewWorkbook, WorkbookBeforeClose, and WorkbookOpen events.&amp;#160; You will also put some code in ThisAddIn_Startup.&amp;#160; Also, handle the SheetBeforeRightClick event temporarily until we add a ribbon in the next article—this will make it so that if you right click on a worksheet, the bug data will be added to the workbook.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; ThisAddIn_Startup(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; sender &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; e &lt;span class="kwrd"&gt;As&lt;/span&gt; System.EventArgs) &lt;span class="kwrd"&gt;Handles&lt;/span&gt; &lt;span class="kwrd"&gt;Me&lt;/span&gt;.Startup
        &lt;span class="kwrd"&gt;If&lt;/span&gt; Application.ActiveWorkbook IsNot &lt;span class="kwrd"&gt;Nothing&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
            PopulateSpreadsheet(&lt;span class="kwrd"&gt;False&lt;/span&gt;)
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; ThisAddIn_Shutdown(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; sender &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; e &lt;span class="kwrd"&gt;As&lt;/span&gt; System.EventArgs) &lt;span class="kwrd"&gt;Handles&lt;/span&gt; &lt;span class="kwrd"&gt;Me&lt;/span&gt;.Shutdown

    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; Application_NewWorkbook(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; Wb &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.Workbook) &lt;span class="kwrd"&gt;Handles&lt;/span&gt; Application.NewWorkbook
        PopulateSpreadsheet(&lt;span class="kwrd"&gt;False&lt;/span&gt;)
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; Application_SheetBeforeRightClick(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; Sh &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; Target &lt;span class="kwrd"&gt;As&lt;/span&gt; Microsoft.Office.Interop.Excel.Range, &lt;span class="kwrd"&gt;ByRef&lt;/span&gt; Cancel &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Boolean&lt;/span&gt;) &lt;span class="kwrd"&gt;Handles&lt;/span&gt; Application.SheetBeforeRightClick
        PopulateSpreadsheet(&lt;span class="kwrd"&gt;True&lt;/span&gt;)
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; Application_WorkbookBeforeClose(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; Wb &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.Workbook, &lt;span class="kwrd"&gt;ByRef&lt;/span&gt; Cancel &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Boolean&lt;/span&gt;) &lt;span class="kwrd"&gt;Handles&lt;/span&gt; Application.WorkbookBeforeClose
        CleanUpDynamicButton()
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; Application_WorkbookOpen(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; Wb &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.Workbook) &lt;span class="kwrd"&gt;Handles&lt;/span&gt; Application.WorkbookOpen
        PopulateSpreadsheet(&lt;span class="kwrd"&gt;False&lt;/span&gt;)
    &lt;span class="kwrd"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;
&lt;style type="text/css"&gt;


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;The rest of the code is almost identical to the code we wrote in Article 4.&amp;#160; PopulateSpreadsheet has these changes from the document to the add-in level.&lt;/p&gt;

&lt;p&gt;1) Instead of the line “vstoSheet = GetVstoObject(s)” it changes to “vstoSheet = s.GetVstoObject()”.&amp;#160; At the add-in level, GetVstoObject is an extension method to the Microsoft.Office.Interop.Excel.Worksheet type.&lt;/p&gt;

&lt;p&gt;2) We don’t have the “If NeedsFill(“bugDataSet”)” if clause—cached data isn’t supported at the add-in level.&lt;/p&gt;

&lt;p&gt;3) Since bugDataset isn’t needed to be declared at the class member level due to no cached data, we declare it local in PopulateSpreadsheet.&amp;#160; Also you might need to add an “Imports System.Data&amp;quot; to the top of the file.&lt;/p&gt;

&lt;p&gt;4) We’ll also add a line at the top of PopulateSpreadsheet to detect if the name of the active workbook is “BugWorkbook”—the wokrbook we created in Section 4.&amp;#160; If it is, we’ll immediately return so as not to have our add-in conflict with our document level solution.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;style type="text/css"&gt;




.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
&lt;style type="text/css"&gt;




.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;Other than these four changes, the remaining code should look very familiar:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;  &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; PopulateSpreadsheet(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; alwaysAdd &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Boolean&lt;/span&gt;)
        &lt;span class="kwrd"&gt;If&lt;/span&gt; Application.ActiveWorkbook.Name = &lt;span class="str"&gt;&amp;quot;BugWorkbook&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt; &lt;span class="kwrd"&gt;Exit&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; foundList &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.ListObject = &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; s &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.Worksheet = &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; bugDataset &lt;span class="kwrd"&gt;As&lt;/span&gt; DataSet


        foundList = FindList()

        &lt;span class="rem"&gt;' If not there create it if always add is true&lt;/span&gt;
        &lt;span class="kwrd"&gt;If&lt;/span&gt; foundList &lt;span class="kwrd"&gt;Is&lt;/span&gt; &lt;span class="kwrd"&gt;Nothing&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
            &lt;span class="kwrd"&gt;If&lt;/span&gt; alwaysAdd = &lt;span class="kwrd"&gt;True&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
                s = Application.ActiveSheet
                foundList = s.ListObjects.AddEx(Excel.XlListObjectSourceType.xlSrcRange, s.Range(&lt;span class="str"&gt;&amp;quot;A1&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;D2&amp;quot;&lt;/span&gt;))
                foundList.Name = &lt;span class="str"&gt;&amp;quot;BugListObject&amp;quot;&lt;/span&gt;
            &lt;span class="kwrd"&gt;Else&lt;/span&gt;
                &lt;span class="kwrd"&gt;Exit&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;
            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
        &lt;span class="kwrd"&gt;Else&lt;/span&gt;
            s = &lt;span class="kwrd"&gt;TryCast&lt;/span&gt;(foundList.Parent, Excel.Worksheet)
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

        &lt;span class="rem"&gt;' Dynamically create the list object&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; vstoSheet &lt;span class="kwrd"&gt;As&lt;/span&gt; Microsoft.Office.Tools.Excel.Worksheet
        vstoSheet = s.GetVstoObject()

        &lt;span class="rem"&gt;' Do we already have a listobject, if so exit.&lt;/span&gt;
        &lt;span class="kwrd"&gt;If&lt;/span&gt; vstoSheet.Controls.Contains(&lt;span class="str"&gt;&amp;quot;BugListObject&amp;quot;&lt;/span&gt;) &lt;span class="kwrd"&gt;Then&lt;/span&gt;
            &lt;span class="kwrd"&gt;Exit&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; list &lt;span class="kwrd"&gt;As&lt;/span&gt; Microsoft.Office.Tools.Excel.ListObject = vstoSheet.Controls.AddListObject(foundList)

        &lt;span class="rem"&gt;'If NeedsFill(&amp;quot;bugDataset&amp;quot;) Then&lt;/span&gt;
        Application.StatusBar = &lt;span class="str"&gt;&amp;quot;Updating data from bug web service...&amp;quot;&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; bugService &lt;span class="kwrd"&gt;As&lt;/span&gt; BugService.BugService = &lt;span class="kwrd"&gt;New&lt;/span&gt; BugService.BugService()
        bugDataset = bugService.BulkDataExport(&lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;)
        &lt;span class="rem"&gt;'End If&lt;/span&gt;

        list.AutoSetDataBoundColumnHeaders = &lt;span class="kwrd"&gt;True&lt;/span&gt;
        list.DataSource = bugDataset.Tables(0)
        list.Range.Columns.AutoFit()
        list.Disconnect()

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; buttonRange &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.Range = s.Range(&lt;span class="str"&gt;&amp;quot;E1&amp;quot;&lt;/span&gt;)
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; pivotButton &lt;span class="kwrd"&gt;As&lt;/span&gt; Microsoft.Office.Tools.Excel.Controls.Button
        pivotButton = vstoSheet.Controls.AddButton(buttonRange, &lt;span class="str"&gt;&amp;quot;CreatePivotTable&amp;quot;&lt;/span&gt;)
        buttonDictionary.Add(s, pivotButton)
        &lt;span class="kwrd"&gt;AddHandler&lt;/span&gt; pivotButton.Click, &lt;span class="kwrd"&gt;AddressOf&lt;/span&gt; pivotButton_Click
        pivotButton.Text = &lt;span class="str"&gt;&amp;quot;Pivot&amp;quot;&lt;/span&gt;

        Application.StatusBar = &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;
        s.Name = &lt;span class="str"&gt;&amp;quot;Bug Data&amp;quot;&lt;/span&gt;
        s.Activate()
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; FindList() &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.ListObject
        &lt;span class="rem"&gt;' Do we already have a created list object?&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; l &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.ListObject = &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; s &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.Worksheet = &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;
        &lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; s &lt;span class="kwrd"&gt;In&lt;/span&gt; Application.ActiveWorkbook.Worksheets
            &lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; l &lt;span class="kwrd"&gt;In&lt;/span&gt; s.ListObjects
                &lt;span class="kwrd"&gt;If&lt;/span&gt; l.Name = &lt;span class="str"&gt;&amp;quot;BugListObject&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
                    &lt;span class="kwrd"&gt;Return&lt;/span&gt; l
                &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
            &lt;span class="kwrd"&gt;Next&lt;/span&gt;
        &lt;span class="kwrd"&gt;Next&lt;/span&gt;
        &lt;span class="kwrd"&gt;Return&lt;/span&gt; &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt;

    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; pivotButton_Click(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; sender &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; e &lt;span class="kwrd"&gt;As&lt;/span&gt; System.EventArgs)
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; s &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.Worksheet = &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; pivotCache &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.PivotCache
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; pivotTables &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.PivotTables
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; pivotTable &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.PivotTable
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; pivotField &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.PivotField

        s = Application.ActiveWorkbook.Worksheets.Add()
        pivotCache = s.Parent.PivotCaches.Create(Excel.XlPivotTableSourceType.xlDatabase, FindList().Range, Excel.XlPivotTableVersionList.xlPivotTableVersion12)
        pivotTables = s.PivotTables()
        pivotTable = pivotTables.Add(pivotCache, s.Range(&lt;span class="str"&gt;&amp;quot;A1&amp;quot;&lt;/span&gt;))

        pivotTable.AddDataField(pivotTable.PivotFields(4))
        pivotTable.AddFields(&lt;span class="str"&gt;&amp;quot;Date&amp;quot;&lt;/span&gt;)

        pivotField = pivotTable.PivotFields(&lt;span class="str"&gt;&amp;quot;Column&amp;quot;&lt;/span&gt;)
        pivotField.Orientation = Excel.XlPivotFieldOrientation.xlPageField
        pivotField.CurrentPage = &lt;span class="str"&gt;&amp;quot;Active&amp;quot;&lt;/span&gt;

        pivotField = pivotTable.PivotFields(&lt;span class="str"&gt;&amp;quot;Team&amp;quot;&lt;/span&gt;)
        pivotField.Orientation = Excel.XlPivotFieldOrientation.xlPageField
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; project &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; = InputBox(&lt;span class="str"&gt;&amp;quot;Enter the team&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;Team name&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;Project - Office Client&amp;quot;&lt;/span&gt;)
        pivotField.CurrentPage = project

        s.Name = project
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; CleanUpDynamicButton()
        &lt;span class="kwrd"&gt;Try&lt;/span&gt;
            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; l &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.ListObject = FindList()
            &lt;span class="kwrd"&gt;If&lt;/span&gt; (l &lt;span class="kwrd"&gt;Is&lt;/span&gt; &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;) &lt;span class="kwrd"&gt;Then&lt;/span&gt;
                &lt;span class="kwrd"&gt;Exit&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;
            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; vstoButton &lt;span class="kwrd"&gt;As&lt;/span&gt; Microsoft.Office.Tools.Excel.Controls.Button
            vstoButton = buttonDictionary(l.Parent)
            &lt;span class="kwrd"&gt;RemoveHandler&lt;/span&gt; vstoButton.Click, &lt;span class="kwrd"&gt;AddressOf&lt;/span&gt; pivotButton_Click
            buttonDictionary.Remove(l.Parent)
        &lt;span class="kwrd"&gt;Catch&lt;/span&gt; ex &lt;span class="kwrd"&gt;As&lt;/span&gt; Exception

        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Try&lt;/span&gt;
    &lt;span class="kwrd"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;

&lt;p&gt;Now, when you run this add-in and right click on the worksheet, the bugs dataset will be added to the workbook along with the “Pivot” button.&lt;/p&gt;
&lt;style type="text/css"&gt;


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;Next up, we’ll enhance our solution with a custom ribbon.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9616764" width="1" height="1"&gt;</content><author><name>Eric Carter</name><uri>http://blogs.msdn.com/Eric-Carter/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>6. VSTO Bug Tracker: Word Report Generation</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/eric_carter/archive/2009/05/14/6-vsto-bug-tracker-word-report-generation.aspx" /><id>http://blogs.msdn.com/b/eric_carter/archive/2009/05/14/6-vsto-bug-tracker-word-report-generation.aspx</id><published>2009-05-14T21:17:17Z</published><updated>2009-05-14T21:17:17Z</updated><content type="html">&lt;p&gt;Another thing I want my bug tracking system to do is help me generate a weekly report with a summary table of key stats for all my teams. I want to do this in Word so I can add my own comments and a status summary of what went on during the week.&lt;/p&gt;  &lt;p&gt;We already prepared to build this Word report by writing the Web Service method “GetDailyValues”.&amp;#160; Create a new Word document project in C# and call it &lt;strong&gt;BugDocument. &lt;/strong&gt;If you start from a new document, follow the instructions below.&amp;#160; If you want to start from an existing document I’ve provided one here:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://ericca.members.winisp.net/bugdocument.docx"&gt;http://ericca.members.winisp.net/bugdocument.docx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Add a heading in the document called “Bug Report for “ then drag and drop a DatePickerContentControl in.&amp;#160; Next, add a table with 6 rows and 5 columns.&amp;#160; The headings for the columns are Active, Incoming, Fix Rate, and Resolve Rate.&amp;#160; The headings for the rows are Office Client, Office Server, Pro Tools, VBA, and VSTA.&amp;#160; Now drag and drop in new PlainTextContentControls left to right in this order into the table:&lt;/p&gt;  &lt;p&gt;1 2 3 4 &lt;/p&gt;  &lt;p&gt;5 6 7 8&lt;/p&gt;  &lt;p&gt;9 10 11 12&lt;/p&gt;  &lt;p&gt;13 14 15 16&lt;/p&gt;  &lt;p&gt;17 18 19 20&lt;/p&gt;  &lt;p&gt;This results in the document shown below:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/6.VSTOBugTrackerWordReportGeneration_12275/image_2.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/6.VSTOBugTrackerWordReportGeneration_12275/image_thumb.png" width="644" height="447" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Next, add a WebService reference to our BugService as described in Article 4.&amp;#160; Make sure the WebService is named BugService.&lt;/p&gt;  &lt;p&gt;We’re going to add an event handler for the DatePickerContentControl we added to the heading.&amp;#160; Click on the DatePickerControl, then use the Properties window to add an event handler for the Exiting event.&lt;/p&gt;  &lt;p&gt;In the code behind for ThisDocument, add a member variable to hold the dataset we will get back from the web service.&lt;/p&gt;  &lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; DataSet ds;&lt;/pre&gt;

&lt;p&gt;The exiting event should look like this.&amp;#160; It gets the date that is picked, calls the web service, and calls the BindControls (if this is the first call) which establishes databindings between all the content controls you added and the dataset.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; datePickerContentControl1_Exiting(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, Microsoft.Office.Tools.Word.ContentControlExitingEventArgs e)
    {
        DateTime date = System.Convert.ToDateTime(datePickerContentControl1.Text);
        BugService.BugService bugService = &lt;span class="kwrd"&gt;new&lt;/span&gt; BugService.BugService();

        &lt;span class="kwrd"&gt;if&lt;/span&gt; (ds != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
        {
            ds.Clear();
            DataSet d = bugService.GetDailyValues(date.Date.ToShortDateString());
            ds.Merge(d);
        }
        &lt;span class="kwrd"&gt;else&lt;/span&gt;
        {
            ds = bugService.GetDailyValues(date.Date.ToShortDateString());
            BindControls();
        }
    }

    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; BindControls()
    {
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl1.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.1&amp;quot;&lt;/span&gt;);
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl2.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.2&amp;quot;&lt;/span&gt;);
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl3.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.3&amp;quot;&lt;/span&gt;);
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl4.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.4&amp;quot;&lt;/span&gt;);

        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl5.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.5&amp;quot;&lt;/span&gt;);
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl6.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.6&amp;quot;&lt;/span&gt;);
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl7.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.7&amp;quot;&lt;/span&gt;);
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl8.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.8&amp;quot;&lt;/span&gt;);

        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl9.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.9&amp;quot;&lt;/span&gt;);
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl10.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.10&amp;quot;&lt;/span&gt;);
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl11.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.11&amp;quot;&lt;/span&gt;);
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl12.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.12&amp;quot;&lt;/span&gt;);

        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl13.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.13&amp;quot;&lt;/span&gt;);
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl14.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.14&amp;quot;&lt;/span&gt;);
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl15.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.15&amp;quot;&lt;/span&gt;);
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl16.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.16&amp;quot;&lt;/span&gt;);

        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl17.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.17&amp;quot;&lt;/span&gt;);
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl18.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.18&amp;quot;&lt;/span&gt;);
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl19.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.19&amp;quot;&lt;/span&gt;);
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.plainTextContentControl20.DataBindings.Add(&lt;span class="str"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;, ds, &lt;span class="str"&gt;&amp;quot;Table.20&amp;quot;&lt;/span&gt;);
    }&lt;/pre&gt;

&lt;p&gt;When we run this solution, and pick a date from the date picker, the table is filled in from the data set returned by the web service showing current bug statistics for that date.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;a href="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/6.VSTOBugTrackerWordReportGeneration_12275/image_4.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/6.VSTOBugTrackerWordReportGeneration_12275/image_thumb_1.png" width="644" height="466" /&gt;&lt;/a&gt; &lt;/pre&gt;
&lt;style type="text/css"&gt;




.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;Although this is as far as we are going to take this part of the solution, you can imagine some additional things we could do.&amp;#160; First, because we use databinding, we could update our web service to return more than a single row, and use a currency manager to move through the rows in the dataset which would cause all the bound controls to update automatically.&amp;#160; This is a potential reason to use this technique (databinding) as opposed to the other technique you can use with content controls which is doing xpath bindings to an XML xpart embedded in the document.&lt;/p&gt;

&lt;p&gt;Also, we could use cached data in this solution in a similar way as was explained in Article 5 to populate the dataset in the document without starting Word.&lt;/p&gt;

&lt;p&gt;In the next section, I’m going to show you how we can take some of the functionality in my bug workbook to the add-in level so it will work against any spreadsheet without requiring any code in a spreadsheet.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9616762" width="1" height="1"&gt;</content><author><name>Eric Carter</name><uri>http://blogs.msdn.com/Eric-Carter/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>5. VSTO Bug Tracker : Using Cached Data</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/eric_carter/archive/2009/05/14/5-vsto-bug-tracker-using-cached-data.aspx" /><id>http://blogs.msdn.com/b/eric_carter/archive/2009/05/14/5-vsto-bug-tracker-using-cached-data.aspx</id><published>2009-05-14T21:15:10Z</published><updated>2009-05-14T21:15:10Z</updated><content type="html">&lt;p&gt;We are now going to convert our previous sample to use cached data.&amp;#160; In our current solution we have code that when the document loads, it calls a web service to get the bug data.&amp;#160; We are going to use the cached data feature to allow us to call the web service at a different time to fill in the dataset in the document without having to start Excel.&amp;#160; &lt;/p&gt;  &lt;p&gt;Why would we want to do this?&amp;#160; Well, several reasons.&amp;#160; First, we can improve the load time of our document by updating the data in the document in advance.&amp;#160; This also is handy to update the data in the document if the document is going to be opened outside the firewall where the web service can’t be accessed.&amp;#160; So a process running on a machine within the firewall can update the data in the document and then give the document to a machine running outside the firewall. As mentioned in the last article, it can also allow me to update the bug data in my workbooks in the middle of the night via a scheduled process so I can hit the web service when traffic is low.&lt;/p&gt;  &lt;p&gt;To convert our previous solution to used cached data, we simply add the CachedData attribute to the DataSet we declared in Sheet1.&lt;/p&gt;  &lt;pre class="csharpcode"&gt;    &amp;lt;Cached()&amp;gt; &lt;span class="kwrd"&gt;Public&lt;/span&gt; bugDataset &lt;span class="kwrd"&gt;As&lt;/span&gt; DataSet&lt;/pre&gt;
&lt;style type="text/css"&gt;





.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;Next, we’ll modify our implementation of PopulateSpreadsheet.&amp;#160; The change here is to uncomment out the if statement &lt;font face="Consolas"&gt;&lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;NeedsFill&lt;/span&gt;(&lt;span class="str"&gt;&amp;quot;bugDataset&amp;quot;&lt;/span&gt;) &lt;/font&gt;&lt;span class="kwrd"&gt;&lt;font face="Consolas"&gt;Then&lt;/font&gt; which now brackets the code that calls the web service to update bugDataset.&amp;#160; What will happen now is that there are two ways of initializing the dataset in the document.&amp;#160; If the document gets run immediately after it is built, bugDataSet will not yet be cached in the document, so the bugDataSet will be updated by the web service call.&amp;#160; On subsequent runs after the document is saved, the web service won’t be called because the dataset will be cached in the document already.&amp;#160; The second way that the dataset can be initialized is through a console app that we will write presently.&lt;/span&gt;&lt;/p&gt;

&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;If&lt;/span&gt; NeedsFill(&lt;span class="str"&gt;&amp;quot;bugDataset&amp;quot;&lt;/span&gt;) &lt;span class="kwrd"&gt;Then&lt;/span&gt;
            Application.StatusBar = &lt;span class="str"&gt;&amp;quot;Updating data from bug web service...&amp;quot;&lt;/span&gt;
            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; bugService &lt;span class="kwrd"&gt;As&lt;/span&gt; BugWorkbook.BugService.BugService = &lt;span class="kwrd"&gt;New&lt;/span&gt; BugWorkbook.BugService.BugService()
            bugDataset = bugService.BulkDataExport(&lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;)
        &lt;span class="kwrd"&gt;End&lt;/span&gt; If&lt;/pre&gt;
&lt;style type="text/css"&gt;



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;Now, lets create a console application that can populate the data set into the document without starting Excel.&amp;#160; Use File &amp;gt; Add &amp;gt; New Project… to add a new console application to the solution (under Language, Windows, Console Application) and call it &lt;strong&gt;UpdateExcelWorkbook&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this console application, we will be using a class called ServerDocument which lets us access the cached data without starting up Excel.&amp;#160; Right click on the project node for the console application and choose “Add Reference…”.&amp;#160; From the Add Reference dialog, locate the .NET assembly called Microsoft.VisualStudio.Tools.Applications.ServerDocument.v9.0 and add it as a reference.&lt;/p&gt;

&lt;p&gt;Also add using Microsoft.VisualStudio.Tools.Applications; (Imports Microsoft.VisualStudio.Tools.Applications for VB) and using System.Data; (Imports System.Data) to the Program.cs (or Program.vb) file.&lt;/p&gt;

&lt;p&gt;We must also add a web reference to BugService—follow the steps given in article 4, and be sure to name it BugService.&lt;/p&gt;

&lt;p&gt;Now we’ll write the code for the console application.&amp;#160; The code creates a new instance of the ServerDocument class, iterates over the cached data until it finds a cached dataset called “bugDataSet”—the name of the public variable we added to Sheet1.&amp;#160; It then updates that dataset by calling the web service, then using a method called SerializeDataInstance which writes the dataset into the document.&amp;#160; Finally it calls doc.Save then exits.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Linq;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Text;
&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.VisualStudio.Tools.Applications;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Data;

&lt;span class="kwrd"&gt;namespace&lt;/span&gt; UpdateExcelWorkbook
{
    &lt;span class="kwrd"&gt;class&lt;/span&gt; Program
    {
        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)
        {
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (args.Length != 1)
            {
                Console.WriteLine(&lt;span class="str"&gt;&amp;quot;Usage:&amp;quot;&lt;/span&gt;);
                Console.WriteLine(&lt;span class="str"&gt;&amp;quot;   UpdateExcelWorkbook.exe myfile.xlsx&amp;quot;&lt;/span&gt;);
                &lt;span class="kwrd"&gt;return&lt;/span&gt;;
            }

            &lt;span class="kwrd"&gt;string&lt;/span&gt; filename = args[0];
            ServerDocument doc = &lt;span class="kwrd"&gt;null&lt;/span&gt;;

            &lt;span class="kwrd"&gt;try&lt;/span&gt;
            {
                doc = &lt;span class="kwrd"&gt;new&lt;/span&gt; ServerDocument(filename);

                &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (CachedDataHostItem view &lt;span class="kwrd"&gt;in&lt;/span&gt;
                  doc.CachedData.HostItems)
                {
                    &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (CachedDataItem item &lt;span class="kwrd"&gt;in&lt;/span&gt; view.CachedData)
                    {
                        &lt;span class="kwrd"&gt;if&lt;/span&gt; (item.Id == &lt;span class="str"&gt;&amp;quot;bugDataset&amp;quot;&lt;/span&gt;)
                        {
                            BugService.BugService bugService = &lt;span class="kwrd"&gt;new&lt;/span&gt; BugService.BugService();
                            DataSet ds = bugService.BulkDataExport(&lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;);
                            item.SerializeDataInstance(ds);
                            doc.Save();
                            &lt;span class="kwrd"&gt;continue&lt;/span&gt;;
                        }
                    }
                }
            }
            &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception ex)
            {
                Console.WriteLine(&lt;span class="str"&gt;&amp;quot;Unexpected Exception:&amp;quot;&lt;/span&gt; + filename);
                Console.WriteLine(ex.ToString());
            }
            &lt;span class="kwrd"&gt;finally&lt;/span&gt;
            {
                &lt;span class="kwrd"&gt;if&lt;/span&gt; (doc != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
                {
                    doc.Close();
                }
            }
        }
    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;





.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;Now, to make this run, go back to the BugWorkbook project node, right click on it, and choose “Open Folder in Windows Explorer”.&amp;#160; We are trying to get the full path to the excel workbook that is being built by Visual Studio.&amp;#160; Double click on the bin directory, then the debug directory, then copy the whole path to the clipboard.&amp;#160; On my computer it is C:\Users\ecarter\Documents\Visual Studio 2008\Projects\BugService\BugWorkbook\bin\Debug\BugWorkbook.xlsx&lt;/p&gt;

&lt;p&gt;Right click on the UpdateExcelWorkbook project node, and choose properties.&amp;#160; Click the Debug tab.&amp;#160; In that tab, paste into the Command line arguments text box the full path to the workbook as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/5.VSTOBugTrackerUsingCachedData_12E60/image_4.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/5.VSTOBugTrackerUsingCachedData_12E60/image_thumb_1.png" width="644" height="405" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now, set the UpdateExcelWorkbook project to be the startup project by right clicking on the UpdateExcelWorkbook project node and choosing “Set as Startup Project”.&amp;#160; Clean and rebuild the solution.&amp;#160; This will rebuild the Excel workbook “ExcelWorkbook.xlsx” which will now have an empty data set in it called bugDataSet after the rebuild.&amp;#160; After the console application runs, bugDataSet will have been populated into the document.&lt;/p&gt;

&lt;p&gt;To verify that is so, navigate back to the directory where the excel workbook (now modified by the console application) lives (e.g. C:\Users\ecarter\Documents\Visual Studio 2008\Projects\BugService\BugWorkbook\bin\Debug\BugWorkbook.xlsx) and launch the workbook.&amp;#160; As it loads, note that the Status Bar of Excel does not display the text “Updating data from web service” because the dataset is already in the document.&amp;#160; When it starts up, it immediately binds the already populated dataset to the list object in the document.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9616756" width="1" height="1"&gt;</content><author><name>Eric Carter</name><uri>http://blogs.msdn.com/Eric-Carter/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>4. VSTO Bug Tracker : Getting the data into Excel</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/eric_carter/archive/2009/05/14/4-vsto-bug-tracker-getting-the-data-into-excel.aspx" /><id>http://blogs.msdn.com/b/eric_carter/archive/2009/05/14/4-vsto-bug-tracker-getting-the-data-into-excel.aspx</id><published>2009-05-14T21:14:40Z</published><updated>2009-05-14T21:14:40Z</updated><content type="html">&lt;p&gt;The next step is to get more of the bug data into Excel so we can start to analyze it.&amp;#160; To do this, we will use VSTO’s data bind to ListObject support.&lt;/p&gt;  &lt;p&gt;I’m going to approach this in a different “more advanced” way that will make sense later in the demo. Long time VSTO developer will know that the simple way to bind data to a list object in VSTO is to create an Excel Workbook project, add a data source, then drag and drop the data source onto the Excel Workbook.&lt;/p&gt;  &lt;p&gt;The problem with that approach for this demo is that the code that is generated is deeply tied to the specific workbook being designed.&amp;#160; Since I’m going to show some advanced tips and tricks here including using document features in an add-in, I’m going to do this in a way that doesn’t tie it to a specific workbook project.&lt;/p&gt;  &lt;p&gt;We want to add the new Excel Workbook project to our existing solution that has our BugService project in it.&amp;#160; To do this, select File &amp;gt; Add &amp;gt; New Project.&amp;#160; Pick Visual Basic or Visual C# then Office then 2007 in the Project types outline.&amp;#160; Then pick Excel 2007 Workbook project and name it BugWorkbook:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/3.VSTOBugTrackerGettingthedataintoExcel_C008/image_2.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/3.VSTOBugTrackerGettingthedataintoExcel_C008/image_thumb.png" width="644" height="413" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Select Create a new document in the next dialog box that appears then click OK.&lt;/p&gt;  &lt;p&gt;Now we want to add a web reference to our BugService web service.&amp;#160; Right click on the BugWorkbook project node in Solution Explorer and choose Add Service Reference...&amp;#160; Then click on the Advanced button then the Add Web Reference.. button. Click the “Web Services in this Solution” link.&amp;#160; Then click “BugService”.&amp;#160; Change the web reference name from localhost to BugService and click the Add Reference button:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/3.VSTOBugTrackerGettingthedataintoExcel_C008/image_6.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/3.VSTOBugTrackerGettingthedataintoExcel_C008/image_thumb_2.png" width="644" height="449" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Now, right click on Sheet1.vb (or Sheet1.cs) and choose View Code.&lt;/p&gt;  &lt;p&gt;Add these two member variable to the ThisWorkbook class.&amp;#160; We need a variable to hold onto our dataset and one to hold onto a button we will be dynamically creating.&amp;#160; The reason we are using a dictionary object to store our button will be apparent later in the demo, for this section it will feel like overkill.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;Public&lt;/span&gt; bugDataset &lt;span class="kwrd"&gt;As&lt;/span&gt; DataSet
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; buttonDictionary &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; Dictionary(Of Excel.Worksheet, Microsoft.Office.Tools.Excel.Controls.Button)&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Startup and Shutdown for the sheet look like this:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; Sheet1_Startup(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; sender &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; e &lt;span class="kwrd"&gt;As&lt;/span&gt; System.EventArgs) &lt;span class="kwrd"&gt;Handles&lt;/span&gt; &lt;span class="kwrd"&gt;Me&lt;/span&gt;.Startup
        PopulateSpreadsheet(&lt;span class="kwrd"&gt;True&lt;/span&gt;)
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; Sheet1_Shutdown(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; sender &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; e &lt;span class="kwrd"&gt;As&lt;/span&gt; System.EventArgs) &lt;span class="kwrd"&gt;Handles&lt;/span&gt; &lt;span class="kwrd"&gt;Me&lt;/span&gt;.Shutdown
        CleanUpDynamicButton()
    &lt;span class="kwrd"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;
&lt;style type="text/css"&gt;


.csharpcode {
	background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small
}
.csharpcode pre {
	background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small
}
.csharpcode pre {
	margin: 0em
}
.csharpcode .rem {
	color: #008000
}
.csharpcode .kwrd {
	color: #0000ff
}
.csharpcode .str {
	color: #006080
}
.csharpcode .op {
	color: #0000c0
}
.csharpcode .preproc {
	color: #cc6633
}
.csharpcode .asp {
	background-color: #ffff00
}
.csharpcode .html {
	color: #800000
}
.csharpcode .attr {
	color: #ff0000
}
.csharpcode .alt {
	background-color: #f4f4f4; margin: 0em; width: 100%
}
.csharpcode .lnum {
	color: #606060
}&lt;/style&gt;

&lt;p&gt;The PopulateSpreadsheet method takes a boolean parameter that sets whether or not to force that the data be added.&amp;#160; The reason for this parameter will be apparent later as well.&amp;#160; This code finds the existing listobject with the bug data (if it has already been inserted into the spreadsheet in a previous run of the spreadsheet).&amp;#160; If it hasn’t yet been created, it creates the list.&amp;#160; It then contacts the web service (it does this every time the document opens), gets all the bug data, binds the resulting dataset to the&amp;#160; list object, then it disconnects from the list object once it has been populated.&amp;#160; Finally, it dynamically creates a button that if clicked will create a new sheet with a pivot table for the data in the list.&amp;#160; It puts the button in a dictionary along with the worksheet it was created on so it can be cleaned up later (in CleanUpDynamicButton).&amp;#160; The FindList method is a helper method that looks through the workbook to see if we’ve already added a listobject—it does this by looking for a listobject named “BugListObject”.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; PopulateSpreadsheet(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; alwaysAdd &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Boolean&lt;/span&gt;)
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; foundList &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.ListObject = &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; s &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.Worksheet = &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;

        foundList = FindList()

        &lt;span class="rem"&gt;' If not there create it if always add is true&lt;/span&gt;
        &lt;span class="kwrd"&gt;If&lt;/span&gt; foundList &lt;span class="kwrd"&gt;Is&lt;/span&gt; &lt;span class="kwrd"&gt;Nothing&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
            &lt;span class="kwrd"&gt;If&lt;/span&gt; alwaysAdd = &lt;span class="kwrd"&gt;True&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
                s = Application.ActiveSheet
                foundList = s.ListObjects.AddEx(Excel.XlListObjectSourceType.xlSrcRange, s.Range(&lt;span class="str"&gt;&amp;quot;A1&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;D2&amp;quot;&lt;/span&gt;))
                foundList.Name = &lt;span class="str"&gt;&amp;quot;BugListObject&amp;quot;&lt;/span&gt;
            &lt;span class="kwrd"&gt;Else&lt;/span&gt;
                &lt;span class="kwrd"&gt;Exit&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;
            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
        &lt;span class="kwrd"&gt;Else&lt;/span&gt;
            s = &lt;span class="kwrd"&gt;TryCast&lt;/span&gt;(foundList.Parent, Excel.Worksheet)
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

        &lt;span class="rem"&gt;' Dynamically create the list object&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; vstoSheet &lt;span class="kwrd"&gt;As&lt;/span&gt; Microsoft.Office.Tools.Excel.Worksheet
        vstoSheet = GetVstoObject(s)

        &lt;span class="rem"&gt;' Do we already have a listobject, if so exit.&lt;/span&gt;
        &lt;span class="kwrd"&gt;If&lt;/span&gt; vstoSheet.Controls.Contains(&lt;span class="str"&gt;&amp;quot;BugListObject&amp;quot;&lt;/span&gt;) &lt;span class="kwrd"&gt;Then&lt;/span&gt;
            &lt;span class="kwrd"&gt;Exit&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; list &lt;span class="kwrd"&gt;As&lt;/span&gt; Microsoft.Office.Tools.Excel.ListObject = vstoSheet.Controls.AddListObject(foundList)

        &lt;span class="rem"&gt;'If NeedsFill(&amp;quot;bugDataset&amp;quot;) Then&lt;/span&gt;
        Application.StatusBar = &lt;span class="str"&gt;&amp;quot;Updating data from bug web service...&amp;quot;&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; bugService &lt;span class="kwrd"&gt;As&lt;/span&gt; BugService.BugService = &lt;span class="kwrd"&gt;New&lt;/span&gt; BugService.BugService()
        bugDataset = bugService.BulkDataExport(&lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;)
        &lt;span class="rem"&gt;'End If&lt;/span&gt;

        list.AutoSetDataBoundColumnHeaders = &lt;span class="kwrd"&gt;True&lt;/span&gt;
        list.DataSource = bugDataset.Tables(0)
        list.Range.Columns.AutoFit()
        list.Disconnect()

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; buttonRange &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.Range = s.Range(&lt;span class="str"&gt;&amp;quot;E1&amp;quot;&lt;/span&gt;)
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; pivotButton &lt;span class="kwrd"&gt;As&lt;/span&gt; Microsoft.Office.Tools.Excel.Controls.Button
        pivotButton = vstoSheet.Controls.AddButton(buttonRange, &lt;span class="str"&gt;&amp;quot;CreatePivotTable&amp;quot;&lt;/span&gt;)
        buttonDictionary.Add(s, pivotButton)
        &lt;span class="kwrd"&gt;AddHandler&lt;/span&gt; pivotButton.Click, &lt;span class="kwrd"&gt;AddressOf&lt;/span&gt; pivotButton_Click
        pivotButton.Text = &lt;span class="str"&gt;&amp;quot;Pivot&amp;quot;&lt;/span&gt;

        Application.StatusBar = &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;
        s.Name = &lt;span class="str"&gt;&amp;quot;Bug Data&amp;quot;&lt;/span&gt;
        s.Activate()
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; FindList() &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.ListObject
        &lt;span class="rem"&gt;' Do we already have a created list object?&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; l &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.ListObject = &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; s &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.Worksheet = &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;
        &lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; s &lt;span class="kwrd"&gt;In&lt;/span&gt; Application.ActiveWorkbook.Worksheets
            &lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; l &lt;span class="kwrd"&gt;In&lt;/span&gt; s.ListObjects
                &lt;span class="kwrd"&gt;If&lt;/span&gt; l.Name = &lt;span class="str"&gt;&amp;quot;BugListObject&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
                    &lt;span class="kwrd"&gt;Return&lt;/span&gt; l
                &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
            &lt;span class="kwrd"&gt;Next&lt;/span&gt;
        &lt;span class="kwrd"&gt;Next&lt;/span&gt;
        &lt;span class="kwrd"&gt;Return&lt;/span&gt; &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;
    &lt;span class="kwrd"&gt;End&lt;/span&gt; Function&lt;/pre&gt;
&lt;style type="text/css"&gt;


.csharpcode {
	background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small
}
.csharpcode pre {
	background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small
}
.csharpcode pre {
	margin: 0em
}
.csharpcode .rem {
	color: #008000
}
.csharpcode .kwrd {
	color: #0000ff
}
.csharpcode .str {
	color: #006080
}
.csharpcode .op {
	color: #0000c0
}
.csharpcode .preproc {
	color: #cc6633
}
.csharpcode .asp {
	background-color: #ffff00
}
.csharpcode .html {
	color: #800000
}
.csharpcode .attr {
	color: #ff0000
}
.csharpcode .alt {
	background-color: #f4f4f4; margin: 0em; width: 100%
}
.csharpcode .lnum {
	color: #606060
}&lt;/style&gt;&lt;style type="text/css"&gt;


.csharpcode {
	background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small
}
.csharpcode pre {
	background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small
}
.csharpcode pre {
	margin: 0em
}
.csharpcode .rem {
	color: #008000
}
.csharpcode .kwrd {
	color: #0000ff
}
.csharpcode .str {
	color: #006080
}
.csharpcode .op {
	color: #0000c0
}
.csharpcode .preproc {
	color: #cc6633
}
.csharpcode .asp {
	background-color: #ffff00
}
.csharpcode .html {
	color: #800000
}
.csharpcode .attr {
	color: #ff0000
}
.csharpcode .alt {
	background-color: #f4f4f4; margin: 0em; width: 100%
}
.csharpcode .lnum {
	color: #606060
}&lt;/style&gt;

&lt;p&gt;The callback function for the dynamically created button looks like this.&amp;#160; It creates a new pivot table on a new worksheet that is bound to the list object we created.&amp;#160; It creates two page fields to filter the data by team and column.&amp;#160; Finally, it prompts for the team name and sets the team filter to that team name (and sets the name of the newly created worksheet to the team name).&amp;#160; This is basic Excel code, but it took me a while to figure out the Pivot Table object model.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; pivotButton_Click(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; sender &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; e &lt;span class="kwrd"&gt;As&lt;/span&gt; System.EventArgs)
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; s &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.Worksheet = &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; pivotCache &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.PivotCache
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; pivotTables &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.PivotTables
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; pivotTable &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.PivotTable
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; pivotField &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.PivotField

        s = Application.ActiveWorkbook.Worksheets.Add()
        pivotCache = s.Parent.PivotCaches.Create(Excel.XlPivotTableSourceType.xlDatabase, FindList().Range, Excel.XlPivotTableVersionList.xlPivotTableVersion12)
        pivotTables = s.PivotTables()
        pivotTable = pivotTables.Add(pivotCache, s.Range(&lt;span class="str"&gt;&amp;quot;A1&amp;quot;&lt;/span&gt;))

        pivotTable.AddDataField(pivotTable.PivotFields(4))
        pivotTable.AddFields(&lt;span class="str"&gt;&amp;quot;Date&amp;quot;&lt;/span&gt;)

        pivotField = pivotTable.PivotFields(&lt;span class="str"&gt;&amp;quot;Column&amp;quot;&lt;/span&gt;)
        pivotField.Orientation = Excel.XlPivotFieldOrientation.xlPageField
        pivotField.CurrentPage = &lt;span class="str"&gt;&amp;quot;Active&amp;quot;&lt;/span&gt;

        pivotField = pivotTable.PivotFields(&lt;span class="str"&gt;&amp;quot;Team&amp;quot;&lt;/span&gt;)
        pivotField.Orientation = Excel.XlPivotFieldOrientation.xlPageField
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; project &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt; = InputBox(&lt;span class="str"&gt;&amp;quot;Enter the team&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;Team name&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;Project - Office Client&amp;quot;&lt;/span&gt;)
        pivotField.CurrentPage = project

        s.Name = project
    &lt;span class="kwrd"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;
&lt;style type="text/css"&gt;


.csharpcode {
	background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small
}
.csharpcode pre {
	background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small
}
.csharpcode pre {
	margin: 0em
}
.csharpcode .rem {
	color: #008000
}
.csharpcode .kwrd {
	color: #0000ff
}
.csharpcode .str {
	color: #006080
}
.csharpcode .op {
	color: #0000c0
}
.csharpcode .preproc {
	color: #cc6633
}
.csharpcode .asp {
	background-color: #ffff00
}
.csharpcode .html {
	color: #800000
}
.csharpcode .attr {
	color: #ff0000
}
.csharpcode .alt {
	background-color: #f4f4f4; margin: 0em; width: 100%
}
.csharpcode .lnum {
	color: #606060
}&lt;/style&gt;

&lt;p&gt;Finally, the CleanUpDynamicButton method finds the dynamically created button in the dictionary and removes it and cleans up the event handler, etc.&amp;#160; This is in a try catch block just in case a button wasn’t created and therefore isn’t found in the dictionary which will be the case later in this demo.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; CleanUpDynamicButton()
        &lt;span class="kwrd"&gt;Try&lt;/span&gt;
            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; l &lt;span class="kwrd"&gt;As&lt;/span&gt; Excel.ListObject = FindList()
            &lt;span class="kwrd"&gt;If&lt;/span&gt; (l &lt;span class="kwrd"&gt;Is&lt;/span&gt; &lt;span class="kwrd"&gt;Nothing&lt;/span&gt;) &lt;span class="kwrd"&gt;Then&lt;/span&gt;
                &lt;span class="kwrd"&gt;Exit&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;
            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; vstoButton &lt;span class="kwrd"&gt;As&lt;/span&gt; Microsoft.Office.Tools.Excel.Controls.Button
            vstoButton = buttonDictionary(&lt;span class="kwrd"&gt;l&lt;/span&gt;.Parent)
            &lt;span class="kwrd"&gt;RemoveHandler&lt;/span&gt; vstoButton.Click, &lt;span class="kwrd"&gt;AddressOf&lt;/span&gt; pivotButton_Click
            buttonDictionary.Remove(l.Parent)
        &lt;span class="kwrd"&gt;Catch&lt;/span&gt; ex &lt;span class="kwrd"&gt;As&lt;/span&gt; Exception

        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Try&lt;/span&gt;
    &lt;span class="kwrd"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;
&lt;style type="text/css"&gt;


.csharpcode {
	background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small
}
.csharpcode pre {
	background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small
}
.csharpcode pre {
	margin: 0em
}
.csharpcode .rem {
	color: #008000
}
.csharpcode .kwrd {
	color: #0000ff
}
.csharpcode .str {
	color: #006080
}
.csharpcode .op {
	color: #0000c0
}
.csharpcode .preproc {
	color: #cc6633
}
.csharpcode .asp {
	background-color: #ffff00
}
.csharpcode .html {
	color: #800000
}
.csharpcode .attr {
	color: #ff0000
}
.csharpcode .alt {
	background-color: #f4f4f4; margin: 0em; width: 100%
}
.csharpcode .lnum {
	color: #606060
}&lt;/style&gt;&lt;style type="text/css"&gt;


.csharpcode {
	background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small
}
.csharpcode pre {
	background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small
}
.csharpcode pre {
	margin: 0em
}
.csharpcode .rem {
	color: #008000
}
.csharpcode .kwrd {
	color: #0000ff
}
.csharpcode .str {
	color: #006080
}
.csharpcode .op {
	color: #0000c0
}
.csharpcode .preproc {
	color: #cc6633
}
.csharpcode .asp {
	background-color: #ffff00
}
.csharpcode .html {
	color: #800000
}
.csharpcode .attr {
	color: #ff0000
}
.csharpcode .alt {
	background-color: #f4f4f4; margin: 0em; width: 100%
}
.csharpcode .lnum {
	color: #606060
}&lt;/style&gt;

&lt;p&gt;&lt;strong&gt;Now set the BugWorkbook as the active project.&amp;#160; &lt;/strong&gt;So what’s the result when we run this document?&amp;#160; It adds a list object bound to the data set to the active worksheet along with a dynamically created button with the caption Pivot.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/3.VSTOBugTrackerGettingthedataintoExcel_C008/image_10.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/3.VSTOBugTrackerGettingthedataintoExcel_C008/image_thumb_4.png" width="644" height="458" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;When you click on the Pivot button, a new worksheet is created with a pivot table bound to the list object on the Bug Data worksheet.&amp;#160; You are prompted during this process to set the Team filter—here we se tit to “Project – Office Client”&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/3.VSTOBugTrackerGettingthedataintoExcel_C008/image_14.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/3.VSTOBugTrackerGettingthedataintoExcel_C008/image_thumb_6.png" width="644" height="458" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;From here, it is a simple matter to add a nice pivot chart as well.&amp;#160; Click on the Options tab in the Pivot Tables tab group, then press the PivotChart button.&amp;#160; I can quickly get a nice bug chart as shown below. Pretty, but I wish the bug count was going down!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/3.VSTOBugTrackerGettingthedataintoExcel_C008/image_18.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/3.VSTOBugTrackerGettingthedataintoExcel_C008/image_thumb_8.png" width="644" height="461" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;If I save my workbook then reopen it, the hook up code will run, detect that there is already a bug list object in the workbook, and it will fetch fresh data from the web service, rebind to the bug list object to update it, and re-add the dynamic “Pivot” button on the Bug Data page.&amp;#160; I can click the Pivot button as often as I want to add new worksheets with new pivots on the data—for example, looking at different teams or the same team and different columns.&lt;/p&gt;

&lt;p&gt;Sometimes the internal Microsoft server that returns the bug data can be slow or unavailable.&amp;#160; So rather than fetch fresh data from the web server every time you open the document, I’m going to show you how cached data can let you refresh the data in the document during off times—we’re going to write a console application that can update the data in the document without starting Excel.&amp;#160; It therefore could be run nightly on all my bug workbooks to refresh their data (since I don’t really need bug data more often than nightly anyway).&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9616753" width="1" height="1"&gt;</content><author><name>Eric Carter</name><uri>http://blogs.msdn.com/Eric-Carter/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>3. VSTO Bug Tracker : A UDF</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/eric_carter/archive/2009/05/14/3-vsto-bug-tracker-a-udf.aspx" /><id>http://blogs.msdn.com/b/eric_carter/archive/2009/05/14/3-vsto-bug-tracker-a-udf.aspx</id><published>2009-05-14T21:13:17Z</published><updated>2009-05-14T21:13:17Z</updated><content type="html">&lt;p&gt;Now that we have our web service, lets get started by writing a managed UDF that uses the web method “GetColumnValue”.&amp;#160; In fact, the UDF will mirror this web method and make it so we can use it in Excel formulas.&lt;/p&gt;  &lt;p&gt;First, add a new C# or VB class library project to your solution using File &amp;gt; Add &amp;gt; New Project. Name the project BugAddIn. Next, lets add a web reference to the BugService.&lt;/p&gt;  &lt;p&gt;Now we want to add a web reference to our BugService web service.&amp;#160; Right click on the BugWorkbook project node in Solution Explorer and choose Add Service Reference...&amp;#160; Then click on the Advanced button then the Add Web Reference.. button. Click the “Web Services in this Solution” link.&amp;#160; Then click “BugService”.&amp;#160; Change the web reference name from localhost to BugService and click the Add Reference button:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/3.VSTOBugTrackerAUDF_F391/image_6.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/3.VSTOBugTrackerAUDF_F391/image_thumb_2.png" width="644" height="449" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;In your Class1.cs or Class1.vb file created for you in the new project, replace Class1 with the code shown below.&amp;#160; Replace the GUID string in the listing with your own GUID by using Generate GUID in the Tools menu. In the Generate GUID dialog box, pick option 4, Registry Format. Then click the Copy button to put the new GUID string on the clipboard. Then click Exit to exit the Generate GUID tool. Finally, select the GUID string and replace it with your new GUID string. You’ll also have to remove the { } brackets that get copied as part of the GUID.&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Imports&lt;/span&gt; System
&lt;span class="kwrd"&gt;Imports&lt;/span&gt; System.Collections.Generic
&lt;span class="kwrd"&gt;Imports&lt;/span&gt; System.Linq
&lt;span class="kwrd"&gt;Imports&lt;/span&gt; System.Text
&lt;span class="kwrd"&gt;Imports&lt;/span&gt; System.Runtime.InteropServices
&lt;span class="kwrd"&gt;Imports&lt;/span&gt; Microsoft.Win32

&lt;span class="kwrd"&gt;Namespace&lt;/span&gt; BugAddIn
    &lt;span class="rem"&gt;' Replace the Guid below with your own guid that&lt;/span&gt;
    &lt;span class="rem"&gt;' you generate using Create GUID from the Tools menu&lt;/span&gt;
    &amp;lt;Guid(&lt;span class="str"&gt;&amp;quot;6C0C5BEC-9F01-4743-97D3-CB4342644CDB&amp;quot;&lt;/span&gt;)&amp;gt; _
    &amp;lt;ClassInterface(ClassInterfaceType.AutoDual)&amp;gt; _
    &amp;lt;ComVisible(&lt;span class="kwrd"&gt;True&lt;/span&gt;)&amp;gt; _
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Class&lt;/span&gt; BugFunctions

        &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt;()
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

        &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; GetColumnValue(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; team &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; column &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; dateGathered &lt;span class="kwrd"&gt;As&lt;/span&gt; DateTime) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Double&lt;/span&gt;
            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; bugService &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; BugService.BugService()
            &lt;span class="kwrd"&gt;Return&lt;/span&gt; Convert.ToDouble(bugService.GetColumnValue(team, column, dateGathered.[&lt;span class="kwrd"&gt;Date&lt;/span&gt;].ToShortDateString()))
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt;

        &amp;lt;ComRegisterFunctionAttribute()&amp;gt; _
        &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Shared&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; RegisterFunction(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; type &lt;span class="kwrd"&gt;As&lt;/span&gt; Type)
            Registry.ClassesRoot.CreateSubKey(GetSubKeyName(type, &lt;span class="str"&gt;&amp;quot;Programmable&amp;quot;&lt;/span&gt;))
            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; key &lt;span class="kwrd"&gt;As&lt;/span&gt; RegistryKey = Registry.ClassesRoot.OpenSubKey(GetSubKeyName(type, &lt;span class="str"&gt;&amp;quot;InprocServer32&amp;quot;&lt;/span&gt;), &lt;span class="kwrd"&gt;True&lt;/span&gt;)
            key.SetValue(&lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, System.Environment.SystemDirectory + &lt;span class="str"&gt;&amp;quot;\mscoree.dll&amp;quot;&lt;/span&gt;, RegistryValueKind.[&lt;span class="kwrd"&gt;String&lt;/span&gt;])
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

        &amp;lt;ComUnregisterFunctionAttribute()&amp;gt; _
        &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Shared&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; UnregisterFunction(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; type &lt;span class="kwrd"&gt;As&lt;/span&gt; Type)
            Registry.ClassesRoot.DeleteSubKey(GetSubKeyName(type, &lt;span class="str"&gt;&amp;quot;Programmable&amp;quot;&lt;/span&gt;), &lt;span class="kwrd"&gt;False&lt;/span&gt;)
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

        &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Shared&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; GetSubKeyName(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; type &lt;span class="kwrd"&gt;As&lt;/span&gt; Type, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; subKeyName &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
            &lt;span class="kwrd"&gt;Dim&lt;/span&gt; s &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; System.Text.StringBuilder()

            s.Append(&lt;span class="str"&gt;&amp;quot;CLSID\{&amp;quot;&lt;/span&gt;)
            s.Append(type.GUID.ToString().ToUpper())
            s.Append(&lt;span class="str"&gt;&amp;quot;}\&amp;quot;&lt;/span&gt;)
            s.Append(subKeyName)

            &lt;span class="kwrd"&gt;Return&lt;/span&gt; s.ToString()
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt;
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Class&lt;/span&gt;
&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Namespace&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;



.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Linq;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Text;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Runtime.InteropServices;
&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.Win32;

&lt;span class="kwrd"&gt;namespace&lt;/span&gt; BugAddIn
{
    &lt;span class="rem"&gt;// Replace the Guid below with your own guid that&lt;/span&gt;
    &lt;span class="rem"&gt;// you generate using Create GUID from the Tools menu&lt;/span&gt;
    [Guid(&lt;span class="str"&gt;&amp;quot;5268ABE2-9B09-439d-BE97-2EA60E103EF6&amp;quot;&lt;/span&gt;)]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    [ComVisible(&lt;span class="kwrd"&gt;true&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; BugFunctions
    {
        &lt;span class="kwrd"&gt;public&lt;/span&gt; BugFunctions()
        {

        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;double&lt;/span&gt; GetColumnValue(&lt;span class="kwrd"&gt;string&lt;/span&gt; team, &lt;span class="kwrd"&gt;string&lt;/span&gt; column, DateTime dateGathered)
        {
            BugAddIn.BugService.BugService bugService = &lt;span class="kwrd"&gt;new&lt;/span&gt; BugService.BugService();
            &lt;span class="kwrd"&gt;return&lt;/span&gt; Convert.ToDouble(bugService.GetColumnValue(team, column, dateGathered.Date.ToShortDateString()));
        }

        [ComRegisterFunctionAttribute]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; RegisterFunction(Type type)
        {
            Registry.ClassesRoot.CreateSubKey(
            GetSubKeyName(type, &lt;span class="str"&gt;&amp;quot;Programmable&amp;quot;&lt;/span&gt;));
            RegistryKey key = Registry.ClassesRoot.OpenSubKey(
            GetSubKeyName(type, &lt;span class="str"&gt;&amp;quot;InprocServer32&amp;quot;&lt;/span&gt;), &lt;span class="kwrd"&gt;true&lt;/span&gt;);
            key.SetValue(&lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;,
            System.Environment.SystemDirectory + &lt;span class="str"&gt;@&amp;quot;\mscoree.dll&amp;quot;&lt;/span&gt;,
            RegistryValueKind.String);
        }

        [ComUnregisterFunctionAttribute]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; UnregisterFunction(Type type)
        {
            Registry.ClassesRoot.DeleteSubKey(
            GetSubKeyName(type, &lt;span class="str"&gt;&amp;quot;Programmable&amp;quot;&lt;/span&gt;), &lt;span class="kwrd"&gt;false&lt;/span&gt;);
        }

        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetSubKeyName(Type type, &lt;span class="kwrd"&gt;string&lt;/span&gt; subKeyName)
        {
            System.Text.StringBuilder s =
            &lt;span class="kwrd"&gt;new&lt;/span&gt; System.Text.StringBuilder();

            s.Append(&lt;span class="str"&gt;@&amp;quot;CLSID\{&amp;quot;&lt;/span&gt;);
            s.Append(type.GUID.ToString().ToUpper());
            s.Append(@&amp;quot;}\&amp;quot;);
            s.Append(subKeyName);

            &lt;span class="kwrd"&gt;return&lt;/span&gt; s.ToString();
        }
    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;With this code written (remember to replace the GUID in the listing with your own GUID that you generate using Generate GUID in the Tools menu), you need to configure the project to be registered for COM interop so Excel can see it. Go to the properties for the project by double-clicking the Properties node under the BugAddIn project in Solution Explorer. In the properties designer that appears, click the Build tab and check the check box that says Register for COM interop as shown below This will cause Visual Studio to register the assembly for COM interop when the project is built.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/3.VSTOBugTrackerAUDF_F391/image_4.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/3.VSTOBugTrackerAUDF_F391/image_thumb_1.png" width="511" height="484" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;If you are running under Vista or later, you need to run Visual Studio as administrator since registering for COM interop requires administrative privileges. If you are not already running Visual Studio as administrator, save your project and exit Visual Studio. Then find the Visual Studio 2008 icon in the start menu, right click on it and choose Run as Administrator as shown in Figure 3-8. Now that Visual Studio is running as administrator, reopen your project and choose Rebuild Solution from the Build menu. Visual Studio will do the necessary registration to make your class visible to Excel.&lt;/p&gt;

&lt;p&gt;Now that the add-in is built and registered, to load the managed automation add-in into Excel, follow these steps.&lt;/p&gt;

&lt;p&gt;1. Launch Excel and click the Microsoft Office button in the top left corner of the window.&lt;/p&gt;

&lt;p&gt;2. Choose Excel Options.&lt;/p&gt;

&lt;p&gt;3. Click the Add-Ins tab in the Excel Options dialog.&lt;/p&gt;

&lt;p&gt;4. Choose Excel Add-Ins from the combo box labeled Manage. Then click the Go button.&lt;/p&gt;

&lt;p&gt;5. Click the Automation button in the Add-Ins dialog.&lt;/p&gt;

&lt;p&gt;6. Look through the list of Automation Servers and find the class you created—it will be listed as BugAddIn.MyFunctions.&lt;/p&gt;

&lt;p&gt;By clicking OK in this dialog, you have added the BugAddIn.MyFunctions class to the list of installed automation add-ins.&lt;/p&gt;

&lt;p&gt;Now, try to use the function GetColumnValue in an Excel formula. Click an empty cell in the workbook, and then click the Insert Function button (the button with the “fx” label) in the formula bar. From the dialog of available formulas, drop down the “Or select a category” drop-down box and choose BugAddIn.MyFunctions. Then click the GetColumnValue function.&amp;#160; When you click the OK button, Excel pops up a dialog to help select function arguments from cells in the spreadsheet.&lt;/p&gt;

&lt;p&gt;After you have selected function arguments, click OK.&lt;/p&gt;

&lt;p&gt;Note that Excel and .NET have some special issues when running on a non-english locale that may cause you to see an automation add-in to fail. VSTO add-ins have some additional features that protect you from these issues.&lt;/p&gt;

&lt;p&gt;Also note that to uninstall your add-in, run regasm BugAddIn.dll /unregister at an eleveated command prompt.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9616742" width="1" height="1"&gt;</content><author><name>Eric Carter</name><uri>http://blogs.msdn.com/Eric-Carter/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>2. VSTO Bug Tracker : The Web Service</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/eric_carter/archive/2009/05/14/2-vsto-bug-tracker-the-web-service.aspx" /><id>http://blogs.msdn.com/b/eric_carter/archive/2009/05/14/2-vsto-bug-tracker-the-web-service.aspx</id><published>2009-05-14T21:11:52Z</published><updated>2009-05-14T21:11:52Z</updated><content type="html">&lt;p&gt;Within Microsoft, there is a web service already implemented that I can use in my solution to call the bug tracking system and get back the data described in the previous article.&amp;#160; For my demo, I’m going to implement a demo web service that will stand in for that internal Microsoft web service.&amp;#160; It will return the same basic data structures as the internal web service does, so when I run my own copy of VSTO bug tracker, I can swap out this demo web service for the real one.&lt;/p&gt;  &lt;p&gt;The demo web service will have three web methods.&amp;#160; The first method is called BulkDataExport.&amp;#160; This method takes a start date and an end date and returns back a dataset with all the bug data for that time period.&amp;#160; This is a simplified version of the Microsoft provided web service that I use internally.&amp;#160; That web method has more parameters to specify milestone, release, team, etc.&amp;#160;&amp;#160; But I will omit those for simplicity since my data is specific to my team.&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&amp;lt;WebMethod()&amp;gt; _
&lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; BulkDataExport(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; dateFrom &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;, _&lt;br /&gt;  &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; dateTo &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; System.Data.DataSet&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;[WebMethod()]
&lt;span class="kwrd"&gt;public&lt;/span&gt; System.Data.DataSet BulkDataExport(&lt;span class="kwrd"&gt;string&lt;/span&gt; dateFrom, &lt;span class="kwrd"&gt;string&lt;/span&gt; dateTo)&lt;/pre&gt;
&lt;style type="text/css"&gt;







.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;The second method is called to get one particular bug stat value for one particular date.&amp;#160; This will be used by the UDF I will write later.&amp;#160; This takes a particular team (milestone and release I omit) as well as the name of the column I want to retrieve (e.g. “Active”) and the date for which I want to get the value.&amp;#160; So I can effectively ask the question through this web method, “How many active bugs did the VBA team have on May 1st?”&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&amp;lt;WebMethod()&amp;gt; _
&lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; GetColumnValue(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; team &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;, _&lt;br /&gt;  &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; column &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; dateGathered &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;
&lt;style type="text/css"&gt;










.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;pre class="csharpcode"&gt;[WebMethod()]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetColumnValue(&lt;span class="kwrd"&gt;string&lt;/span&gt; team, &lt;span class="kwrd"&gt;string&lt;/span&gt; column, &lt;span class="kwrd"&gt;string&lt;/span&gt; dateGathered)&lt;/pre&gt;
&lt;style type="text/css"&gt;







.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;The third method will be used by my Word solution.&amp;#160; It takes the date and returns a dataset with twenty columns representing the 4 key metrics for my 5 teams:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&amp;lt;WebMethod()&amp;gt; _
&lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; GetDailyValues(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; dateGathered &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; DataSet&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;[WebMethod()]
&lt;span class="kwrd"&gt;public&lt;/span&gt; DataSet GetDailyValues(&lt;span class="kwrd"&gt;string&lt;/span&gt; dateGathered)&lt;/pre&gt;
&lt;style type="text/css"&gt;




.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;Let’s walk through creating this web service.&lt;/p&gt;

&lt;p&gt;Fire up Visual Studio 2008, select File &amp;gt; New &amp;gt; Project…, then expand out the Visual Basic or C# node, click the Web category, then pick ASP.NET Web Service Application.&amp;#160; Name the project &lt;strong&gt;BugService&lt;/strong&gt;, then click OK.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/2.TheDemoStoryVSTOBugTracker_F48B/image_2.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/2.TheDemoStoryVSTOBugTracker_F48B/image_thumb.png" width="644" height="459" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now, let’s implement these two methods.&amp;#160; First, let’s get a web service created.&amp;#160; Delete the auto-created Service1.asmx file from your project.&amp;#160; Right click on the project node, choose Add &amp;gt; New Item… and from the Add New Item dialog, click on the Web category, then click Web Service.&amp;#160; Name the Web Service &lt;strong&gt;BugService.asmx&lt;/strong&gt;.&amp;#160; Then click Add. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/2.TheDemoStoryVSTOBugTracker_F48B/image_4.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/eric_carter/WindowsLiveWriter/2.TheDemoStoryVSTOBugTracker_F48B/image_thumb_1.png" width="644" height="389" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Delete the “HelloWorld” web method that is created for you in the BugService.asmx file.&amp;#160; Add a “&lt;strong&gt;using System.Data;&lt;/strong&gt;” statement to the top of the file.&amp;#160; Then add a DataSet property to the BugService class that will contain our data.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;Shared&lt;/span&gt; ds &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; DataSet
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Shared&lt;/span&gt; &lt;span class="kwrd"&gt;ReadOnly&lt;/span&gt; &lt;span class="kwrd"&gt;Property&lt;/span&gt; BugData() &lt;span class="kwrd"&gt;As&lt;/span&gt; DataSet
        &lt;span class="kwrd"&gt;Get&lt;/span&gt;
            &lt;span class="kwrd"&gt;If&lt;/span&gt; ds.Tables.Count = 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;
                ds.ReadXml(&lt;span class="str"&gt;&amp;quot;C:\Users\ecarter\Documents\bugdata.xml&amp;quot;&lt;/span&gt;)
            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
            &lt;span class="kwrd"&gt;Return&lt;/span&gt; ds
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Get&lt;/span&gt;
    &lt;span class="kwrd"&gt;End&lt;/span&gt; Property&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;static&lt;/span&gt; DataSet ds = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataSet();
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; DataSet BugData
    {
        get
        {
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (ds.Tables.Count == 0)
            {
                ds.ReadXml(&lt;span class="str"&gt;&amp;quot;C:\\Users\\ecarter\\Documents\\bugdata.xml&amp;quot;&lt;/span&gt;);
            }
            &lt;span class="kwrd"&gt;return&lt;/span&gt; ds;
        }
    }&lt;/pre&gt;
&lt;style type="text/css"&gt;







.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;font size="2" face="Consolas"&gt;&lt;/font&gt;&lt;style type="text/css"&gt;









.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;As you can see, this code kind of cheats—it loads a pre-serialized data set from disk.&amp;#160; The data in this file has data that I originally obtained from Microsoft’s internal bug system.&amp;#160; For my demo, I won’t live connect to this system, so instead I’ve saved off some XML.&amp;#160; I also keep this around in a class level property so that I only have to load it once and subsequent web service calls that access this data won’t have to load all the bug data again and will therefore be quicker.&lt;/p&gt;

&lt;p&gt;I’ve provided a copy of this data so you can play along here: &lt;a title="http://ericca.members.winisp.net/bugdata.xml" href="http://ericca.members.winisp.net/bugdata.xml"&gt;http://ericca.members.winisp.net/bugdata.xml&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, my implementation of the BulkDataExport web method.&amp;#160; This method is pretty simple.&amp;#160; It just grabs the data set with all the bug data and then does a restrictive query to only return the bug data between the dateFrom and dateTo.&amp;#160; There’s some wierdness going on here with converting dates to strings and so forth—this is because I need to match the original Microsoft internal web service which has everything typed as string.&amp;#160; For C#, be sure you add a &lt;font face="consolas"&gt;using System.Data&lt;/font&gt; to the top of the class file.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    &amp;lt;WebMethod()&amp;gt; _
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; BulkDataExport(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; dateFrom &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; dateTo &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; System.Data.DataSet
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; rows &lt;span class="kwrd"&gt;As&lt;/span&gt; DataTable = BugData.Tables(&lt;span class="str"&gt;&amp;quot;Table&amp;quot;&lt;/span&gt;)

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; startDate &lt;span class="kwrd"&gt;As&lt;/span&gt; DateTime
        &lt;span class="kwrd"&gt;If&lt;/span&gt; (&lt;span class="kwrd"&gt;String&lt;/span&gt;.IsNullOrEmpty(dateFrom)) &lt;span class="kwrd"&gt;Then&lt;/span&gt;
            startDate = &lt;span class="kwrd"&gt;Date&lt;/span&gt;.MinValue
        &lt;span class="kwrd"&gt;Else&lt;/span&gt;
            startDate = System.Convert.ToDateTime(dateFrom)
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; endDate &lt;span class="kwrd"&gt;As&lt;/span&gt; DateTime
        &lt;span class="kwrd"&gt;If&lt;/span&gt; (&lt;span class="kwrd"&gt;String&lt;/span&gt;.IsNullOrEmpty(dateTo)) &lt;span class="kwrd"&gt;Then&lt;/span&gt;
            endDate = &lt;span class="kwrd"&gt;Date&lt;/span&gt;.MaxValue
        &lt;span class="kwrd"&gt;Else&lt;/span&gt;
            endDate = System.Convert.ToDateTime(dateTo)
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; query = From row &lt;span class="kwrd"&gt;In&lt;/span&gt; rows.AsEnumerable() _
                    Where System.Convert.ToDateTime(row.Field(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)(&lt;span class="str"&gt;&amp;quot;Date&amp;quot;&lt;/span&gt;)).Date &amp;gt;= startDate.Date &lt;span class="kwrd"&gt;And&lt;/span&gt; _
                    System.Convert.ToDateTime(row.Field(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)(&lt;span class="str"&gt;&amp;quot;Date&amp;quot;&lt;/span&gt;)).Date &amp;lt;= endDate.Date _
                    &lt;span class="kwrd"&gt;Select&lt;/span&gt; row

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; newrows &lt;span class="kwrd"&gt;As&lt;/span&gt; DataTable = query.CopyToDataTable()
        newrows.TableName = &lt;span class="str"&gt;&amp;quot;Table&amp;quot;&lt;/span&gt;

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; returnDataSet &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; DataSet()
        returnDataSet.Tables.Add(newrows)
        &lt;span class="kwrd"&gt;Return&lt;/span&gt; returnDataSet
    &lt;span class="kwrd"&gt;End&lt;/span&gt; Function&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;    [WebMethod()]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; System.Data.DataSet BulkDataExport(&lt;span class="kwrd"&gt;string&lt;/span&gt; dateFrom, &lt;span class="kwrd"&gt;string&lt;/span&gt; dateTo)
    {
        DataTable rows = BugData.Tables[&lt;span class="str"&gt;&amp;quot;Table&amp;quot;&lt;/span&gt;];

        DateTime startDate;
        &lt;span class="kwrd"&gt;if&lt;/span&gt; ((&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(dateFrom)))
        {
            startDate = System.DateTime.MinValue;
        }
        &lt;span class="kwrd"&gt;else&lt;/span&gt;
        {
            startDate = System.Convert.ToDateTime(dateFrom);
        }

        DateTime endDate;
        &lt;span class="kwrd"&gt;if&lt;/span&gt; ((&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(dateTo)))
        {
            endDate = System.DateTime.MaxValue;
        }
        &lt;span class="kwrd"&gt;else&lt;/span&gt;
        {
            endDate = System.Convert.ToDateTime(dateTo);
        }

        var query = from row &lt;span class="kwrd"&gt;in&lt;/span&gt; rows.AsEnumerable()
                    &lt;span class="kwrd"&gt;where&lt;/span&gt; System.Convert.ToDateTime(row.Field&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;&amp;quot;Date&amp;quot;&lt;/span&gt;)).Date &amp;gt;= startDate.Date &amp;amp;&amp;amp;
                    System.Convert.ToDateTime(row.Field&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;&amp;quot;Date&amp;quot;&lt;/span&gt;)).Date &amp;lt;= endDate.Date
                    select row;

        DataTable newrows = query.CopyToDataTable();
        newrows.TableName = &lt;span class="str"&gt;&amp;quot;Table&amp;quot;&lt;/span&gt;;

        DataSet returnDataSet = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataSet();
        returnDataSet.Tables.Add(newrows);
        &lt;span class="kwrd"&gt;return&lt;/span&gt; returnDataSet;
    }&lt;/pre&gt;
&lt;style type="text/css"&gt;







.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;







.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;Next, the implementation of GetColumnValue.&amp;#160; This also does a basic query over the data to get back the row in the table that corresponds to the team, column, and date specified.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    &amp;lt;WebMethod()&amp;gt; _
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; GetColumnValue(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; team &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; column &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; dateGathered &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; rows &lt;span class="kwrd"&gt;As&lt;/span&gt; DataTable = BugData.Tables(&lt;span class="str"&gt;&amp;quot;Table&amp;quot;&lt;/span&gt;)

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; startDate &lt;span class="kwrd"&gt;As&lt;/span&gt; DateTime = System.Convert.ToDateTime(dateGathered)

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; query = From row &lt;span class="kwrd"&gt;In&lt;/span&gt; rows.AsEnumerable() _
                    Where row.Field(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)(&lt;span class="str"&gt;&amp;quot;Team&amp;quot;&lt;/span&gt;) = team &lt;span class="kwrd"&gt;And&lt;/span&gt; _
                    row.Field(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)(&lt;span class="str"&gt;&amp;quot;Column&amp;quot;&lt;/span&gt;) = column &lt;span class="kwrd"&gt;And&lt;/span&gt; _
                    System.DateTime.Compare(System.Convert.ToDateTime(row.Field(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)(&lt;span class="str"&gt;&amp;quot;Date&amp;quot;&lt;/span&gt;)).&lt;span class="kwrd"&gt;Date&lt;/span&gt;, startDate.&lt;span class="kwrd"&gt;Date&lt;/span&gt;) = 0 _
                    &lt;span class="kwrd"&gt;Select&lt;/span&gt; row

        &lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; row &lt;span class="kwrd"&gt;In&lt;/span&gt; query
            &lt;span class="kwrd"&gt;Return&lt;/span&gt; row.Field(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)(&lt;span class="str"&gt;&amp;quot;Value&amp;quot;&lt;/span&gt;)
        &lt;span class="kwrd"&gt;Next&lt;/span&gt;

        &lt;span class="kwrd"&gt;Return&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;ERROR&amp;quot;&lt;/span&gt;
    &lt;span class="kwrd"&gt;End&lt;/span&gt; Function&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;    [WebMethod()]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetColumnValue(&lt;span class="kwrd"&gt;string&lt;/span&gt; team, &lt;span class="kwrd"&gt;string&lt;/span&gt; column, &lt;span class="kwrd"&gt;string&lt;/span&gt; dateGathered)
    {
        DataTable rows = BugData.Tables[&lt;span class="str"&gt;&amp;quot;Table&amp;quot;&lt;/span&gt;];

        DateTime startDate = System.Convert.ToDateTime(dateGathered);

        var query = from row &lt;span class="kwrd"&gt;in&lt;/span&gt; rows.AsEnumerable()
                    &lt;span class="kwrd"&gt;where&lt;/span&gt; row.Field&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;&amp;quot;Team&amp;quot;&lt;/span&gt;) == team &amp;amp;&amp;amp;
                    row.Field&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;&amp;quot;Column&amp;quot;&lt;/span&gt;) == column &amp;amp;&amp;amp;
                    System.DateTime.Compare(System.Convert.ToDateTime(row.Field&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;&amp;quot;Date&amp;quot;&lt;/span&gt;)).Date, startDate.Date) == 0
                    select row;

        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var row &lt;span class="kwrd"&gt;in&lt;/span&gt; query)
        {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; row.Field&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;&amp;quot;Value&amp;quot;&lt;/span&gt;);
        }

        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;ERROR&amp;quot;&lt;/span&gt;;
    }&lt;/pre&gt;
&lt;style type="text/css"&gt;







.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;









.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;Finally, the implementation of GetDailyValues:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;    &amp;lt;WebMethod()&amp;gt; _
    &lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; GetDailyValues(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; dateGathered &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; DataSet
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; rows &lt;span class="kwrd"&gt;As&lt;/span&gt; DataTable = BugData.Tables(&lt;span class="str"&gt;&amp;quot;Table&amp;quot;&lt;/span&gt;)

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; startDate &lt;span class="kwrd"&gt;As&lt;/span&gt; DateTime = System.Convert.ToDateTime(dateGathered)

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; query = From row &lt;span class="kwrd"&gt;In&lt;/span&gt; rows.AsEnumerable() _
                    Where System.DateTime.Compare(System.Convert.ToDateTime(row.Field(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)(&lt;span class="str"&gt;&amp;quot;Date&amp;quot;&lt;/span&gt;)).&lt;span class="kwrd"&gt;Date&lt;/span&gt;, startDate.&lt;span class="kwrd"&gt;Date&lt;/span&gt;) = 0 &lt;span class="kwrd"&gt;And&lt;/span&gt; _
                    (row.Field(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)(&lt;span class="str"&gt;&amp;quot;Column&amp;quot;&lt;/span&gt;) = &lt;span class="str"&gt;&amp;quot;Active&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;Or&lt;/span&gt; _
                     row.Field(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)(&lt;span class="str"&gt;&amp;quot;Column&amp;quot;&lt;/span&gt;) = &lt;span class="str"&gt;&amp;quot;Incoming Rate (7 Day)&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;Or&lt;/span&gt; _
                     row.Field(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)(&lt;span class="str"&gt;&amp;quot;Column&amp;quot;&lt;/span&gt;) = &lt;span class="str"&gt;&amp;quot;Resolved Fixed Rate (7 Day)&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;Or&lt;/span&gt; _
                     row.Field(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)(&lt;span class="str"&gt;&amp;quot;Column&amp;quot;&lt;/span&gt;) = &lt;span class="str"&gt;&amp;quot;Resolved Rate (7 Day)&amp;quot;&lt;/span&gt;) _
                     Order By row.Field(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)(&lt;span class="str"&gt;&amp;quot;Team&amp;quot;&lt;/span&gt;), row.Field(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)(&lt;span class="str"&gt;&amp;quot;Column&amp;quot;&lt;/span&gt;) _
                    &lt;span class="kwrd"&gt;Select&lt;/span&gt; row

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; newrows &lt;span class="kwrd"&gt;As&lt;/span&gt; DataTable = &lt;span class="kwrd"&gt;New&lt;/span&gt; DataTable(&lt;span class="str"&gt;&amp;quot;Table&amp;quot;&lt;/span&gt;)
        newrows.TableName = &lt;span class="str"&gt;&amp;quot;Table&amp;quot;&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; i &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;
        &lt;span class="kwrd"&gt;For&lt;/span&gt; i = 1 &lt;span class="kwrd"&gt;To&lt;/span&gt; 20
            newrows.Columns.Add(i.ToString())
        &lt;span class="kwrd"&gt;Next&lt;/span&gt;

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; objectArray(19) &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Object&lt;/span&gt;
        i = 0
        &lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; row &lt;span class="kwrd"&gt;In&lt;/span&gt; query
            objectArray(i) = row.Field(Of &lt;span class="kwrd"&gt;String&lt;/span&gt;)(&lt;span class="str"&gt;&amp;quot;Value&amp;quot;&lt;/span&gt;)
            i = i + 1
        &lt;span class="kwrd"&gt;Next&lt;/span&gt;

        newrows.Rows.Add(objectArray)

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; returnDataSet &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; DataSet()
        returnDataSet.Tables.Add(newrows)
        &lt;span class="kwrd"&gt;Return&lt;/span&gt; returnDataSet
    &lt;span class="kwrd"&gt;End&lt;/span&gt; Function&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;    [WebMethod()]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; DataSet GetDailyValues(&lt;span class="kwrd"&gt;string&lt;/span&gt; dateGathered)
    {
        DataTable rows = BugData.Tables[&lt;span class="str"&gt;&amp;quot;Table&amp;quot;&lt;/span&gt;];
        DateTime startDate = System.Convert.ToDateTime(dateGathered);

        var query = from row &lt;span class="kwrd"&gt;in&lt;/span&gt; rows.AsEnumerable()
                    &lt;span class="kwrd"&gt;where&lt;/span&gt; System.DateTime.Compare(System.Convert.ToDateTime(row.Field&amp;lt;String&amp;gt;(&lt;span class="str"&gt;&amp;quot;Date&amp;quot;&lt;/span&gt;)).Date, startDate.Date) == 0 &amp;amp;&amp;amp;
                    (row.Field&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;&amp;quot;Column&amp;quot;&lt;/span&gt;) == &lt;span class="str"&gt;&amp;quot;Active&amp;quot;&lt;/span&gt; ||
                     row.Field&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;&amp;quot;Column&amp;quot;&lt;/span&gt;) == &lt;span class="str"&gt;&amp;quot;Incoming Rate (7 Day)&amp;quot;&lt;/span&gt; ||
                     row.Field&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;&amp;quot;Column&amp;quot;&lt;/span&gt;) == &lt;span class="str"&gt;&amp;quot;Resolved Fixed Rate (7 Day)&amp;quot;&lt;/span&gt; ||
                     row.Field&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;&amp;quot;Column&amp;quot;&lt;/span&gt;) == &lt;span class="str"&gt;&amp;quot;Resolved Rate (7 Day)&amp;quot;&lt;/span&gt;)
                    orderby row.Field&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;&amp;quot;Team&amp;quot;&lt;/span&gt;), row.Field&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;&amp;quot;Column&amp;quot;&lt;/span&gt;)
                    select row;

        DataTable newrows = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataTable(&lt;span class="str"&gt;&amp;quot;Table&amp;quot;&lt;/span&gt;);
        newrows.TableName = &lt;span class="str"&gt;&amp;quot;Table&amp;quot;&lt;/span&gt;;
        &lt;span class="kwrd"&gt;int&lt;/span&gt; i;
        &lt;span class="kwrd"&gt;for&lt;/span&gt; (i = 1; i &amp;lt;= 20; i++)
        {
            newrows.Columns.Add(i.ToString());
        }

        &lt;span class="kwrd"&gt;object&lt;/span&gt;[] objectArray = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[20];
        i = 0;
        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var row &lt;span class="kwrd"&gt;in&lt;/span&gt; query)
        {
            objectArray[i] = row.Field&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;&amp;quot;Value&amp;quot;&lt;/span&gt;);
            i = i + 1;
        }

        newrows.Rows.Add(objectArray);

        DataSet returnDataSet = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataSet();
        returnDataSet.Tables.Add(newrows);
        &lt;span class="kwrd"&gt;return&lt;/span&gt; returnDataSet;
    }&lt;/pre&gt;
&lt;style type="text/css"&gt;




.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;You should be able to run the web service project and test it.&lt;/p&gt;

&lt;p&gt;Now that we have a working web service, lets create a UDF that uses it.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9616737" width="1" height="1"&gt;</content><author><name>Eric Carter</name><uri>http://blogs.msdn.com/Eric-Carter/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>1. VSTO Bug Tracker : The Data</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/eric_carter/archive/2009/05/14/1-vsto-bug-tracker-the-data.aspx" /><id>http://blogs.msdn.com/b/eric_carter/archive/2009/05/14/1-vsto-bug-tracker-the-data.aspx</id><published>2009-05-14T21:08:00Z</published><updated>2009-05-14T21:08:00Z</updated><content type="html">&lt;P&gt;For my TechEd&amp;nbsp;demo today, I will be showing a solution that helps me to do part of my job as a development manager: tracking the bug counts in the product.&amp;nbsp; At Microsoft, we have an internal system that tracks a ton of relevant bug stats in TFS and takes a snapshot of various key metrics in that system every day—for example, active bugs for a team on a given day day.&amp;nbsp; I will be writing a solution that brings that bug data into Excel and Word using VSTO so it can be further analyzed.&amp;nbsp; Ways I can analyze it in Excel will include using Pivot Tables and Pivot Charts against the data, grabbing this data to use in custom formulas in Excel, etc.&amp;nbsp; In Word, I can create nicely formatted bug mail that I can then send to the team.&lt;/P&gt;
&lt;P&gt;First, a bit more about the bug data.&amp;nbsp;&amp;nbsp; The bug data is tracked in a table that has these columns: Team, Column, Date, and Value.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Team&lt;/STRONG&gt; – The team we are tracking bugs for.&amp;nbsp; On my team I have 5 teams I track bugs for:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Project - VSTA &lt;/LI&gt;
&lt;LI&gt;Project - Office Server &lt;/LI&gt;
&lt;LI&gt;Project - Office Client &lt;/LI&gt;
&lt;LI&gt;Project - Pro Tools &lt;/LI&gt;
&lt;LI&gt;Project - VBA &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;STRONG&gt;Column&lt;/STRONG&gt; – The name of the bug statistic being tracked.&amp;nbsp; Some examples:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Active – number of active bugs on a given day &lt;/LI&gt;
&lt;LI&gt;Resolved Fixed Rate (7 Day) – the 7 day average of bugs that were resolved fixed &lt;/LI&gt;
&lt;LI&gt;Resolved Rate (7 Day) – the 7 day average of total bugs were resolved (some bugs may be resolved without having an actual fix occur, for example because they are duplicate bugs) &lt;/LI&gt;
&lt;LI&gt;Incoming Rate (7 Day) – the 7 day average of bugs that were opened &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;STRONG&gt;Date– &lt;/STRONG&gt;The date the bug statistic was gathered.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Value&lt;/STRONG&gt; – The value for the bug statistic on a given day, for example Active bugs for a particular team is 50 on a particular date.&lt;/P&gt;
&lt;P&gt;So, for my particular team, if I want to know the Active bug count for VSTA on May 1st, I would get back this set of values—this row in the table.&lt;/P&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=html&gt;Team&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;Project - VSTA&lt;SPAN class=kwrd&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN class=html&gt;Team&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;
&lt;SPAN class=kwrd&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=html&gt;Column&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;Active&lt;SPAN class=kwrd&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN class=html&gt;Column&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;
&lt;SPAN class=kwrd&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=html&gt;Date&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;5/1/2009&lt;SPAN class=kwrd&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN class=html&gt;Date&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=html&gt;Value&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;98&lt;SPAN class=kwrd&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN class=html&gt;Value&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;STYLE type=text/css&gt;





.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/STYLE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9616724" width="1" height="1"&gt;</content><author><name>Eric Carter</name><uri>http://blogs.msdn.com/Eric-Carter/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>If you are using Windows 7 RC and VSTO you better read this</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/eric_carter/archive/2009/05/08/if-you-are-using-windows-7-rc-and-vsto-you-better-read-this.aspx" /><id>http://blogs.msdn.com/b/eric_carter/archive/2009/05/08/if-you-are-using-windows-7-rc-and-vsto-you-better-read-this.aspx</id><published>2009-05-08T10:04:27Z</published><updated>2009-05-08T10:04:27Z</updated><content type="html">&lt;p&gt;Saurabh blogs about how to work around an error you get if you published a VSTO solution using VS2008 on a machine running the Windows 7 RC and then you try to install the solution on any machine you will see the following error: “The required version of the .NET Framework is not installed on this computer”:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/vsto/archive/2009/05/07/issues-with-installing-vsto-projects-that-were-published-from-visual-studio-2008-on-windows-7-rc-saurabh-bhatia.aspx"&gt;http://blogs.msdn.com/vsto/archive/2009/05/07/issues-with-installing-vsto-projects-that-were-published-from-visual-studio-2008-on-windows-7-rc-saurabh-bhatia.aspx&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9596112" width="1" height="1"&gt;</content><author><name>Eric Carter</name><uri>http://blogs.msdn.com/Eric-Carter/ProfileUrlRedirect.ashx</uri></author></entry></feed>