VSTO
VSTO
VSTO
The Microsoft .NET Development Series is supported and developed by the leaders and experts of
Microsoft development technologies including Microsoft architects and DevelopMentor instructors. The
books in this series provide a core resource of information and understanding every developer needs in order
to write effective applications and managed code. Learn from the leaders how to maximize your use of the
Visual Studio Tools
for Office
Visual Studio Tools
.NET Framework and its programming languages.
Lippert
Carter
ADO.NET and System.Xml v. 2.0—The Beta 0-201-77018-0 —Don Box
Version, 0-321-24712-4 Architect, Microsoft Corporation
Shawn Wildermuth, Pragmatic ADO.NET: Data
Alex Homer, Dave Sussman, Rob Howard, Access for the Internet World, 0-201-74568-2
ASP.NET v. 2.0—The Beta Version, Paul Yao and David Durant, .NET Compact
0-321-25727-8 Framework Programming with C#, 0-321-17403-8
James S. Miller and Susann Ragsdale, The Paul Yao and David Durant, .NET Compact
Common Language Infrastructure Annotated Framework Programming with Visual Basic .NET,
Standard, 0-321-15493-2 0-321-17404-6
Eric Carter
For more information go to www.awprofessional.com/msdotnetseries/
Eric Lippert
Draftman.qxd 4/27/05 1:44 PM Page 1
DRAFT MANUSCRIPT
Books Available
September 2005
• Whence DataSets?
o A Disconnected Strategy
o Rolling Your Own DataSet Filling Code
o Working With Many Tables
• Typed DataSets
• Creating Data-Bound View Controls With The Designer
o Creating DataBound Excel Documents With ListObject
and XmlMappedRange
o Complex and Simple Data Binding
o Data Binding In Word Documents
• ADO.NET Data Binding: Looking Behind The Scenes
o Binding Managers Manage Currency
o Using Binding Sources as Proxies
• Binding-Related Extensions To View and View Control Classes
o Extensions to the List Object View Control in Excel
New Data-related List Object View Control
Properties and Methods:
New Data-related List Object Events:
New Exception:
• Master-Detail Data Binding
• Conclusion
• Introduction to Add-ins
Outlook Add-ins
• Scenarios for using Add-ins
• How an Add-In Is Registered
o Registry Location of an Add-in:
HKEY_CURRENT_USER or
HKEY_LOCAL_MACHINE
o Registry Entries Required for an Add-in
• Implementing IDTExtensibility2
o Startup Order
o OnAddInsUpdate Method
o OnBeginShutdown Method
o OnConnection Method
o OnDisconnection Method
o OnStartupComplete Method
o A Simple Implementation
• Writing an Add-in Using Visual Studio
o Changing the Add-in Project to be More Office Specific
o Setting the Start Action
o My Add-in Project Doesn't Work Anymore--What
Happened?
o A Simple Word Add-in
• The Pitfalls of MsCoree.dll
o Com Interop and REGASM.EXE
o Mscoree.dll and Managed Add-ins
o Problems with Using Mscoree.dll to Load your add-in
Problem 1: Mscoree.dll Can Be Disabled
Causing All Managed Add-ins to Stop Loading
Problem 2: Mscoree.dll Cannot Be Signed
Problem 3: Mscoree.dll loads all add-ins into the
same AppDomain
• Shimming: A Solution to the Problems With MsCoree.dll
How to build a Shim DLL
• Conclusion
Preface
Three years ago as the first release of Visual Studio .NET and the .NET
Framework were nearing completion; a few of us at Microsoft realized that
Office programming was going to miss the .NET wave unless we did
something about it.
What had come before was Visual Basic for Applications (VBA), a
simple development environment integrated into all the Office applications.
Each Office application had a rich object model that was accessed via a
technology known as COM. Millions of developers identified themselves as
“Office developers” and used VBA and the Office COM object models to do
everything from automating repetitive tasks to creating complete business
solutions that leveraged the rich features and user interface of Office. These
developers realized that their users were spending their days in Office. By
building solutions that ran inside of Office, they not only made their users
happy, but they were able to create solutions that did more and cost less by
reusing functionality already available in the Office applications.
Unfortunately, because of some limitations of VBA, Office programming
was starting to get a bad rap. Solutions developed in VBA by small
workgroups or individuals would gain momentum and a professional
developer would have to take them over and start supporting them. To a
professional developer, the VBA environment felt simple and limited and of
course it enforced a single language—Visual Basic. VBA embedded code in
every customized document, which made it hard to fix bugs and update
solutions as a bug would get replicated in documents across the enterprise.
Security weaknesses in the VBA model caused by a rash of worms and macro
viruses that made enterprises turn VBA off.
Visual Studio .NET and the .NET Framework provided a way to address
all these problems. There was a huge opportunity to not only combine the
richness of the new .NET Framework and developer tools with the powerful
platform that Office has always provided for developers but to also solve the
problems that were plaguing VBA. The result of this realization was Visual
Studio Tools for Office or VSTO.
The first version of VSTO was simple, but it accomplished the key goal
of letting professional developers use the full power of Visual Studio .NET
and the .NET Framework to put code behind Excel 2003 and Word 2003
documents and templates. It let professional developers develop Office
solutions in VB.NET and C#. It solved the problem of embedded code by
linking a document to a .NET assembly rather than embedding it in the
document. It also introduced a new security model that used .NET code
access security to prevent worms and macro viruses.
The second version of VSTO known as VSTO 2005, the version of VSTO
covered by this book, is even more ambitious. It brings with it functionality
never available to the Office developer before such as data binding and
data/view separation, design time views of Excel and Word documents inside
Visual Studio, rich support for Windows Forms controls in the document, the
ability to create custom Office task panes, server side programming support
against Office—and that’s just scratching the surface. Although the primary
target of VSTO is the professional developer, that doesn’t mean that building
an Office solution with VSTO is rocket science. VSTO makes it possible to
create very rich applications with just a few lines of code.
This book tries to put into one place all the information you will need to
be successful using VSTO to program against Word 2003, Excel 2003,
Outlook 2003, and InfoPath 2003. It introduces the Office object models and
covers most commonly used objects in those object models. In addition, this
book will help you avoid some pitfalls that result from the COM origins of the
Office object models.
This book will also give you an insider view of all the rich features of
VSTO. We participated in the design and implementation of many of these
features. We can therefore speak from the unique perspective of living and
breathing VSTO for the past three years. Programming Office using VSTO is
powerful and fun. We hope you enjoy using VSTO as much as we enjoyed
writing about it and creating it.
Eric Carter
Eric Lippert
May 2005
About the authors
Eric Carter
Eric Carter is a Lead Developer on the Visual Studio Tools for Office (VSTO)
team at Microsoft. He helped invent, design, and implement many of the
features that are in VSTO today. Previously at Microsoft he worked on
Visual Studio for Applications, the Visual Studio Macros IDE, and Visual
Basic for Applications for Office 2000 and Office 2003.
Eric Lippert
Eric Lippert's primary focus during his nine years at Microsoft has been on
improving the lives of developers by designing and implementing useful
programming languages and development tools. He's worked on the Windows
Scripting family of technologies and, most recently, Visual Studio Tools For
Office.
Chapter 2
Introduction to Office
Solutions
Hosted Code
The add-in and code behind patterns are sometimes called hosted code
which means that your code runs in the same process as the Office
application.
Discovery of Hosted Code
In order for code to run in the Office application process, the Office
application must be able to discover your code, load the code into its process
space, and run your code. Office add-ins are registered in the registry so
Office can find and start them. Using the registry seems a little non-.NET but
this is necessary because Office 2003 talks to add-ins as if they were COM
objects through COM interop.
The code behind a document pattern does not require a registry entry.
Instead, code is associated with a document by adding some special properties
to the document file. Office reads these properties when the document opens
then Office loads the code associated with the document.
Context Provided to Hosted Code
It is critical that your hosted code get context—it needs to get the
Application object or Document object for the Office application into which it
is loading. COM add-ins are provided with context through an interface
implemented by the add-in class. Outlook add-ins in VSTO are provided with
context through a class created in the project that represents the application
being customized. Code behind a document in VSTO is provided with
context through a class created in the project that represents the document
being customized.
Entry Point for Hosted Code
At startup, Office calls into an entry point where your code can run for the
first time and register for events that may occur later in the session. For a
COM add-in, this entry point is the OnConnection method of the
IDTExtensibility2 interface implemented by the COM add-in. For a VSTO
Outlook add-in and VSTO code behind a document this entry point is the
Startup event handler.
namespace ConsoleApplication
{
class Program
{
static bool exit = false;
myExcelApp.SheetBeforeDoubleClick += new
Excel.AppEvents_SheetBeforeDoubleClickEventHandler(myExce
lApp_SheetBeforeDoubleClick);
Listing 2-1 also illustrates how an automation executable can yield time
back to the Office application. A reference to the System.Windows.Forms
assembly must be added to the project. After a event handlers are hooked up,
System.Windows.Forms.Application.DoEvents() is called in a loop to allow
the Excel application to run normally. If the user double clicks on a cell,
Office yields time back to the event handler in the automation executable. In
the handler for the double click event, we set the static variable exit to true
which will cause the loop calling DoEvents to exit and the automation
executable to exit.
You can see the lifetime management of Excel in action by running the
automation executable in Listing 2-1 and exiting Excel without double
clicking on a cell. Excel will continue to run in a hidden state, waiting for the
console application to release its reference to Excel’s Application object.
Visual Studio adds the reference to the Word 2003 PIA and adds
additional references to the stdole, VBIDE, and Microsoft.Office.Core PIAs
as shown in Figure 2-4. These additional PIAs are ones that the Word PIA
depends on. Stdole is a PIA that contains the definition of some of the types
that COM object models need. VBIDE is the PIA for the object model
associated with the VBA editor integrated into Office. Microsoft.Office.Core
(office.dll) is the PIA for common functionality shared by all the Office
applications such as the object model for the toolbars and menus.
Figure 2-4: When you add the Word 2003 PIA, dependent PIA references are
automatically added to the project.
Now that the proper references have been added to our console
application, let’s start writing code. Double click on Program.cs in the
Solution Explorer window to edit the main source code file for the console
application. If you have outlining turned on, you will see the text “using …”
at the top of the Program.cs file with a + sign next to it. Click on the + sign to
expand out the code where the using directives are placed. Add the following
three using directives so we can use objects from the Word PIA and the
Microsoft.Office.Core PIA as well as classes in the System.IO namespace.
using Office = Microsoft.Office.Core;
using Word = Microsoft.Office.Interop.Word;
using System.IO;
We are now ready to write some real code that automates Word to create
a table after reading a text input file in the wiki table format. The entire
listing of our program is shown in Listing 2-3. Rather than explain every line
of code in that listing, we will focus on the lines of code that automate Word.
We assume the reader has some knowledge of how to read a text file in .NET
and parse a string via the Split method. We will briefly touch on some objects
in the Word object model here, but Chapters 6 through 8 cover the Word
object model in much more detail.
The first thing we do in Listing 2-3 is declare a new instance of the Word
application object by adding this line of code to Main method of our program
class.
Word.Application theApplication = new Word.Application();
theApplication.Visible = true;
Next, we want to create a new empty Word document into which we will
generate our table. We do this by calling the Add method on the Documents
collection returned by Word’s application object. The Add method takes four
optional parameters that we want to omit. Optional parameters in Word
methods are specified as omitted by passing by reference a variable
containing the special value Type.Missing. We declare a variable called
missing that we set to Type.Missing and pass it by reference to each
parameter we wish to omit as shown here:
With a document created, we want to read the input text file specified by
the command line argument passed to our console application. We want to
parse that text file to calculate the number of columns and rows. Once we
know the number of columns and rows, we use the line of code below to get a
Range object from the Document object. By passing our missing variable to
the optional parameters, the Range method will return a range that includes
the entire text of the document.
Word.Range range = theDocument.Range(ref missing, ref
missing);
We then use our Range object to add a table by calling the Add method of
the Tables collection returned by the Range object. We pass the Range object
again as the first parameter to the Add method to specify that we want to
replace the entire contents of the document with the table. We also specify
the number of rows and columns we want.
Word.Table table = range.Tables.Add(
range,
rowCount,
columnCount,
ref missing,
ref missing);
The Table object has a Cell method that takes a row and column and
returns a Cell object. The Cell object has a Range property that returns a
Range object for the cell in question that we can use to set the text and
formatting of the cell. The code that sets the cells of the table is shown
below. Note that as in most of the Office object models, the indices are 1-
based meaning they start with one as the minimum value rather than being 0-
based and starting with zero as the minimum value.
Code to set the formatting of the table by setting the table to size to fit
contents and bolding the header row is shown below. We use the Row object
returned by table.Rows[1] which also has a Range property that returns a
Range object for the row in question. Also, we encounter code that sets the
first row of the table to be bolded. One would expect to be able to write the
code table.Rows[1].Range.Bold = true, but Word’s object model
expects an int value (0 or 1) rather than a bool. This is one of many
examples you will come across where the Office object models don’t match
.NET guidelines because of their origins in COM.
// Format table
table.Rows[1].Range.Bold = 1;
table.AutoFitBehavior(Word.WdAutoFitBehavior.wdAutoFitCon
tent);
Finally, there is some code at the end of the program that forces Word to
quit without saving changes:
If we don’t write this code, Word will stay running even after the console
application exits. Once you show the Word window by setting the
Application object’s Visible property to true, Word puts the lifetime of the
application in the hands of the end user rather than the automating program.
So even when the automation executable exits, Word will continue running.
To force Word to exit we must call the Quit method on Word’s Application
object. If this program didn’t make the Word window visible—say for
example it created the document with the table then saved it to a file all
without showing the Word window—it would not have to call Quit because
Word would exit when the program exited and released all its references to
the Word objects.
To run the console application in listing 2-3, you must create a text file
that contains the text in Listing 2-2. Then pass the file name of the text file as
a command line argument to the console application. You can set up the
debugger to do this by right clicking on the WordWiki project in Solution
Explorer and choosing Properties. Then click on the Debug tab and set the
Command line arguments field to the name of your text file.
Listing 2-3: The complete WordWiki implementation.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Office = Microsoft.Office.Core;
using Word = Microsoft.Office.Interop.Word;
namespace WordWiki
{
class Program
{
static void Main(string[] args)
{
Word.Application theApplication = new
Word.Application();
theApplication.Visible = true;
row = reader.ReadLine();
}
// Create a table
Word.Range range = theDocument.Range(ref missing,
ref missing);
Word.Table table = range.Tables.Add(range,
rowCount, columnCount, ref missing, ref missing);
// Populate table
int columnIndex = 1;
int rowIndex = 1;
rowIndex++;
}
// Format table
table.Rows[1].Range.Bold = 1;
table.AutoFitBehavior(Word.WdAutoFitBehavior.wdAutoFitCon
tent);
Office Add-Ins
The second pattern used in Office development is the add-in pattern. This
book will cover several types of Office add-ins. These include VSTO add-ins
for Outlook, COM add-ins for Excel and Word, and Automation add-ins for
Excel:
• VSTO add-ins for Outlook. This new VSTO 2005 feature makes it
extremely easy to create an add-in for Outlook 2003. The model is
the most “.NET” of all the add-in models and is very similar to the
VSTO 2005 code behind model for documents. Chapter 23
describes this model in detail.
• COM add-ins for Excel and Word. A C# class in a class library
project can implement the IDTExtensibility2 interface and register in
the registry as a COM object and COM add-in. Through COM
interop, Office creates the C# class and talks to it. Chapter 24
describes the creation of COM add-ins and some issues that make
COM add-in development problematic.
• Automation add-ins for Excel. These managed classes expose
public functions that Excel can use in formulas. The C# class must
register in the registry as a COM object. Through COM interop,
Excel can create an automation add-in and use its public methods in
formulas. Automation add-ins and their use in Excel formulas are
discussed in Chapter 3.
There are some Office add-in technologies that this book will not discuss.
Application level Smart Tags add-ins and Smart Documents add-ins are not
discussed because VSTO provides a much easier way of accessing Smart Tag
and Smart Document functionality, albeit at the document or template level
rather than at the application level. For more information on VSTO’s support
for Smart Tags and Smart Documents, see Chapter 15 and Chapter 16.
VSTO creates a project with references to the Outlook 2003 PIA, the core
Office PIA, and other needed references as shown in Figure 2-6. VSTO also
adds a project item to the project called ThisApplication.cs. This project item
contains a C# class that you will add to when implementing your Outlook
add-in.
Figure 2-6: The Outlook add-in project in Solution Explorer.
If you double click on the ThisApplication.cs project item, you will see
the code shown in Listing 2-4. There is a simple Startup and Shutdown event
handler where you can write code that executes on the startup and shutdown
of the add-in. The ThisApplication class derives from an aggregate of the
Outlook Application object. This allows you to access properties and
methods of the Outlook Application object by writing code like
this.Inspectors.Count in the ThisApplication class.
Listing 2-4: The initial code in the ThisApplication class in an Outlook add-
in project.
using System;
using System.Windows.Forms;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace OutlookAddin1
{
public partial class ThisApplication
{
private void ThisApplication_Startup(object sender,
System.EventArgs e)
{
}
private void ThisApplication_Shutdown(object sender,
System.EventArgs e)
{
}
Looking at Listing 2-4 you may wonder about the use of “partial” in the
class definition. VSTO uses partial classes which are a new feature of .NET
that allows you to define part of a class in one file and another part of a class
in a second file and then compile them together as one class. VSTO uses this
feature to hide some additional generated code associated with the
ThisApplication class from you to reduce the complexity of the class where
you write your code. The final ThisApplication class will be compiled from
the partial class in Listing 2-4 and additional code in a partial class generated
by VSTO that is hidden from you.
We are going to add to the code in Listing 2-4 to create an add-in to that
will solve an annoying problem—people replying inadvertently to an e-mail
sent out to a mailing alias that contains a large number of people. Unless you
have “Vice President” in your title, you probably do not want to be sending e-
mail to more than, say, 25 people at any given time. We are going to create an
add-in that will warn you if you do this and give you the “This is a potentially
career limiting move. Are you sure you want to send this e-mail to 25,000
people?” message.
Outlook’s Application object has an ItemSend event that fires whenever
a user sends an email. We will add additional code to the Startup method of
the ThisApplication class to hookup an event handler for the ItemSend event
as shown in Listing 2-5. Because the ThisApplication class derives from an
aggregate of Outlook’s Application object, we can write the code
“this.ItemSend” because ItemSend is an event raised by the ThisApplication
base class. The ItemSend event handler takes an object parameter called
Item which is the Outlook item being sent. Because Item could be any of a
number of things such as a meeting request or an e-mail message, Item is
passed as an object instead of as a specific type. The ItemSend event
handler also has a bool parameter passed by reference called Cancel that can
be set to true to prevent the Outlook item from being sent.
In our ItemSend event handler we need to check to see if the Item
parameter which is passed as an object is actually an e-mail. The easiest
way to achieve this is to use the as keyword to try to cast the Item parameter
to an Outlook.MailItem. If the cast succeeds, the resulting value will be non-
null and we will know that the item being sent is an Outlook.MailItem and
therefore an e-mail message. We can then iterate through the Recipients
collection on the MailItem object and check to see if we are sending to any
recipient lists that include more than 25 people. Each Recipient object in the
Recipients collection has an AddressEntry property that returns an
AddressEntry object. The AddressEntry object has a Members property that
returns a collection that we can check the count of. If we find the count to be
more than 25, we will show a dialog and ask the user if they really want to
send the mail. If the user clicks the No button, we will set the Cancel
parameter of the ItemSend event to true to cancel the sending of career
limiting e-mail.
Listing 2-5: A ThisApplication Class in an Outlook add-in project that
handles the ItemSend event and checks for more than 25 recipients.
using System;
using System.Windows.Forms;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace OutlookAddin1
{
public partial class ThisApplication
{
private void ThisApplication_Startup(object sender,
System.EventArgs e)
{
this.ItemSend += new
Outlook.ApplicationEvents_11_ItemSendEventHandler(ThisApp
lication_ItemSend);
}
if (result == DialogResult.No)
{
Cancel = true;
break;
}
}
}
}
}
When you run the project with the code shown in Listing 2-4, Outlook
launches and the add-in loads. Try sending a mail to an alias that includes
more than 25 people—you might want to go offline first in case you mistyped
the code. If all works right, the add-in will display a dialog box warning you
that you are sending an e-mail to more than 25 people and you will be able to
cancel the send of the e-mail. Exit Outlook to end your debugging session.
VSTO Outlook add-ins are discussed in more detail in chapter 23. The
Outlook object model is discussed in Chapters 9 through 11.
namespace ExcelWorkbook1
{
public partial class Sheet1
{
private void Sheet1_Startup(object sender,
System.EventArgs e)
{
// Initial entry point.
// This code gets run first when the code behind is
created
// The context is implicit in the Sheet1 class
MessageBox.Show("Code behind the document
running.");
MessageBox.Show(this.Name + " is the sheet name.
");
}
/// <summary>
/// Required method for Designer support - do not
modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new
System.EventHandler(Sheet1_Startup);
this.Shutdown += new
System.EventHandler(Sheet1_Shutdown);
}
#endregion
}
}
Figure 2-7: Using the New Project dialog to create an Excel Workbook
project.
We will create an Excel Workbook project using C#. If you already have
a workbook which you would like to add VSTO 2005 customization code
behind, the dialog box shown in Figure 2-8 pops up and asks you where it can
be found. This time we will just start from scratch, creating a new, blank
workbook.
Figure 2-8: Selecting the workbook to associate with your code behind.
Once we have created the project, the designer view appears as shown in
Figure 2-9.
Figure 2-9: The design view for VSTO 2005 Excel code behind.
There are a few interesting things to notice in Figure 2-9. First, Excel is
running inside the Visual Studio 2005 IDE as a designer, just the same as a
Windows Forms designer would when developing a Windows Forms project.
Second, look at the menu bar as shown in Figure 2-10. VSTO merges the
Visual Studio menus (Build, Debug, and so on) and the Excel menu items
(Format, Data, and so on) together. Menu items that appear in both Visual
Studio and Excel (Tools, for example) merge by adding a sub menu to the
Visual Studio menu such as Microsoft Office Excel Tools that can be selected
to see the Excel Tools menu.
Figure 2-10: The merging of Visual Studio and Excel menus.
Third, notice in Figure 2-9 that the toolbox contains a new category:
Excel Controls. When designing a document using Visual Studio you can
create named ranges and list objects using the Excel menu items familiar to
Excel users, or the toolbox idiom familiar to Visual Studio users.
Fourth, notice that the properties window shows properties of the selected
object—in this case, Sheet1. You can use the properties window to edit
properties of Excel’s objects the same way that you would edit properties of
controls and forms in a Windows Forms project.
Fifth, notice that the Solution Explorer has four classes in it already.
Each underlying Excel Worksheet and Workbook object is represented by a
.NET class that you can extend and customize. As you make changes to the
document in the designer, the code behind updates automatically. For
example, let’s drag a ListObject from the toolbox onto the Sheet1 designer,
and draw it to be ten rows by four columns as shown in Figure 2-11.
Figure 2-11: Creating a ListObject in the designer.
As you can see from the properties window, the designer has chosen a
default name for the new list object. We could edit it, but in this example, we
will keep the default name List1.
Let’s take a look at the code behind this worksheet and make some simple
changes to it. Right-click on Sheet1.cs in the Solution Explorer and select
View Code. We are going to briefly illustrate two VSTO features—
ActionsPane and ListObject databinding. We will declare a Windows Forms
button as a member variable of the class and call it myButton. In the Startup
event, we will show that button in the Document Actions task pane of Excel
by adding it to the ActionsPane’s Controls collection. This will cause Excel
to show the Document Actions task pane and display our button. We will
also handle the Click event of the button and when the button is clicked we
will databind our list object to a randomly generated DataTable. This code is
shown in Listing 2-7.
Listing 2-7: A VSTO 2005 code behind class that illustrates adding a
control to the Document Actions task pane and databinding a ListObject
control to a DataTable.
using System;
using System;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
namespace ExcelWorkbook1
{
public partial class Sheet1
{
Button myButton = new Button();
DataTable table;
Globals.ThisWorkbook.ActionsPane.Controls.Add(myButton);
}
List1.DataSource = table;
}
#endregion
}
}
Build and run the code, and sure enough Excel starts up, the Startup event
is raised for the sheet, and the button is added to the actions pane. Click the
button and a random DataTable is generated and bound to the ListObject as
shown in Figure 2-12. Exit Excel to end your debugging session.
Figure 2-11: The result of running Listing 2-7 and clicking on the button we
added to the Document Actions task pane.
The Microsoft .NET Development Series is supported and developed by the leaders and experts of
Microsoft development technologies including Microsoft architects and DevelopMentor instructors. The
books in this series provide a core resource of information and understanding every developer needs in order
to write effective applications and managed code. Learn from the leaders how to maximize your use of the
Visual Studio Tools
for Office
Visual Studio Tools
.NET Framework and its programming languages.
Lippert
Carter
ADO.NET and System.Xml v. 2.0—The Beta 0-201-77018-0 —Don Box
Version, 0-321-24712-4 Architect, Microsoft Corporation
Shawn Wildermuth, Pragmatic ADO.NET: Data
Alex Homer, Dave Sussman, Rob Howard, Access for the Internet World, 0-201-74568-2
ASP.NET v. 2.0—The Beta Version, Paul Yao and David Durant, .NET Compact
0-321-25727-8 Framework Programming with C#, 0-321-17403-8
James S. Miller and Susann Ragsdale, The Paul Yao and David Durant, .NET Compact
Common Language Infrastructure Annotated Framework Programming with Visual Basic .NET,
Standard, 0-321-15493-2 0-321-17404-6
Eric Carter
For more information go to www.awprofessional.com/msdotnetseries/
Eric Lippert