Introduction
The Microsoft Outlook Connector is written in C# using the .NET 1.1
Framework. It attempts to abstract the data access with Microsoft Outlook and
visual components using the data. Data from your Microsoft Outlook application
can be exported to an XML file by simply checking the folder options and
clicking Export. The source provides a simple example of mapping the COM object
properties to a XML-friendly DataSet
that could be used in any .NET
application.
Background
This component for exporting Outlook objects stemmed from a couple years
passively looking for a sync between my database and Outlook. I somehow stumbled
on a VBA article on it (http://www.devasp.com/search/res/r9981.html)
and decided to make a C# app to do the same.
Using the code
The primary function of the DataExportForm
retrieves information
from the user's Microsoft Outlook application via a custom connector which
translates the Interop COM objects into basic DataSet
s. We should
all be aware of how handy DataSet
s can be so lets look at how our
form gets the information for the datagrid.
private DataSet getCheckedItemSet()
{
DataSet ds = new DataSet();
OutlookConnector outlook = new OutlookConnector();
pgFolderProgress.Value = 0;
outlook.ItemProcessed += new OutlookItemProcessed(outlook_ItemProcessed);
pgFolderProgress.Maximum = lstExportObjects.CheckedItems.Count;
foreach (ListViewItem obj in lstExportObjects.CheckedItems)
{
pgFolderProgress.Value++;
pgItemProgress.Value = 0;
switch (obj.Index)
{
case 0:
pgItemProgress.Maximum = outlook.getFolderCount(
Outlook.OlDefaultFolders.olFolderCalendar);
ds.Merge(outlook.getCalendarDataSet());
break;
case 1:
pgItemProgress.Maximum = outlook.getFolderCount(
Outlook.OlDefaultFolders.olFolderContacts);
ds.Merge(outlook.getContactDataSet());
break;
case 2:
pgItemProgress.Maximum = outlook.getFolderCount(
Outlook.OlDefaultFolders.olFolderInbox);
ds.Merge(outlook.getInboxDataSet());
break;
case 3:
pgItemProgress.Maximum = outlook.getFolderCount(
Outlook.OlDefaultFolders.olFolderNotes);
ds.Merge(outlook.getNoteDataSet());
break;
case 4:
pgItemProgress.Maximum = outlook.getFolderCount(
Outlook.OlDefaultFolders.olFolderTasks);
ds.Merge(outlook.getTaskDataSet());
break;
default:
Debug.WriteLine("Unsupported Export: " + obj.Index);
break;
}
}
outlook.Dispose();
return ds;
}
Now how exactly does the OutlookConnector
get it? You'll have to
download the source to see the finer details of handling the Interop connection.
Rest assured that it implements the IDisposable
interface and works
through MAPI to retrieve Outlook folder information. All of the Outlook
connectivity is handled on instantiation which makes retrieval pretty easy, as
seen here in the OutlookConnector.getContactDataSet()
method.
public DataSet getContactDataSet()
{
Outlook.ContactItem item;
DataSet rv = new DataSet();
rv.DataSetName = "Contacts";
rv.Tables.Add("Contact");
rv.Tables[0].Columns.Add("FirstName");
rv.Tables[0].Columns.Add("LastName");
rv.Tables[0].Columns.Add("CompanyName");
rv.Tables[0].Columns.Add("Email");
rv.Tables[0].Columns.Add("HomePhone");
rv.Tables[0].Columns.Add("WorkPhone");
try
{
objFolder = objNamespace.GetDefaultFolder(
Outlook.OlDefaultFolders.olFolderContacts);
Debug.WriteLine(objFolder.Items.Count + " Contacts found.");
foreach (System.Object _item in objFolder.Items)
{
item = (Outlook.ContactItem) _item;
rv.Tables[0].Rows.Add(new object[] {
item.FirstName,
item.LastName,
item.CompanyName,
item.Email1Address,
item.HomeTelephoneNumber,
item.BusinessTelephoneNumber
});
this.ItemProcessed();
}
Debug.WriteLine(rv.Tables[0].Rows.Count + " Contacts exported.");
}
catch (System.Exception e)
{
Console.WriteLine(e);
}
return rv;
}
Points of Interest
If your system does not have Microsoft Office Outlook 2003 you may have to
change the References used by the "OutlookConnector" project. That is to say,
if you received a build error described as "The type of namespace name 'Outlook' could
not be found", you probably don't have Office 2003. Simply expand the project references,
remove the afflicted items, and add the COM Library appropriate for your system. If
someone has a dynamic way to handle this, I'd be curious to see you've done.
History
I wanted to limit this project to a single evening so it currently uses
untyped DataSets. The real advantage of this application would come from using
strong types and hooking in some DataAdapter(s) to really try to sync with some
other system. I will probably end up tying in a MySQL data adapter in the coming
weeks as time permits but if someone starts/finishes before I get to it, please
let me know.
Version 1.1
Connector looping was switched to an incrementing localized integer since Office 10
does not implement a GetEnumerator()
method. We have to use our own counter
in a for
loop instead. Also, here are some details on fixing your References
between Office versions.