Pieter van der Westhuizen

Microsoft Project 2010: COM add-in development

In this weeks’ post I’ll demonstrate how using Add-in Express for Office and .net, you can write an add-in to integrate MS Office Project 2010 and MS Office Outlook 2010 and vice versa.

Start by creating a new Visual Studio 2010 ADX COM Add-in project.

Creating a COM Add-in for Microsoft Project

Make sure you select Microsoft Outlook and Microsoft Project as the supported applications and complete the wizard.

Selecting Outlook and Project as supported applications

Switch to the AddinModule’s designer view and add a new ADXRibbonTab component, add a RibbonGroup to the RibbonTab and a RibbonButton to the RibbonGroup. Set the RibbonTab’s Ribbons property to ProjectProject – this will ensure that the RibbonTab will only be visible in MS Project. This button will be used to automatically create tasks from MS Project in MS Outlook.

Create tasks in Outlook button

Add the following code to the button’s OnClick event handler:

private void btnCreateOutlookTasks_OnClick(object sender, 
    AddinExpress.MSO.IRibbonControl control, bool pressed)
{
    Outlook.ApplicationClass app = new Outlook.ApplicationClass();
    MSProject.Project projectProject = MSProjectApp.ActiveProject;
    MSProject.Tasks projectTasks = projectProject.Tasks;
    for (int i = 1; i < = projectTasks.Count)
    {
        MSProject.Task projectTask = projectTasks[i];
        if (projectTask.ResourceNames.Contains("Project Manager"))
        {
            Outlook.TaskItem outlookTask = (Outlook.TaskItem)app.CreateItem
                (Outlook.OlItemType.olTaskItem);
            outlookTask.StartDate = (DateTime)projectTask.Start;
            outlookTask.DueDate = (DateTime)projectTask.Finish;
            outlookTask.Subject = projectTask.Name;
 
            Outlook.UserProperties outlookUserProperties = outlookTask.UserProperties;
            Outlook.UserProperty outlookUserProperty = 
                outlookUserProperties.Add("TaskUniqueId", 
                Outlook.OlUserPropertyType.olNumber);
            outlookUserProperty.Value = projectTask.UniqueID;
            Marshal.ReleaseComObject(outlookUserProperty); outlookUserProperty = null;
 
            outlookUserProperty = outlookUserProperties.Add("OtherResources",
                Outlook.OlUserPropertyType.olText);
            outlookUserProperty.Value = projectTask.ResourceNames
                .Replace(",",Environment.NewLine);
            Marshal.ReleaseComObject(outlookUserProperty); outlookUserProperty = null;
            Marshal.ReleaseComObject(outlookUserProperties); outlookUserProperties = null;
            outlookTask.Save();
            Marshal.ReleaseComObject(outlookTask); outlookTask = null;
        }
        Marshal.ReleaseComObject(projectTask); outlookTask = null;
    }
    Marshal.ReleaseComObject(projectTasks); outlookTasks = null;
    Marshal.ReleaseComObject(projectProject ); projectProject = null;
}

The code above creates all the tasks assigned to the Project Manager in Outlook, and saves the list of resources in a User property on the Outlook TaskItem.

Next, add a new Add-in Express Outlook Form to your project.

Adding a new Ad-in Express Outlook Form

Switch back to the AddinModule designer and add an ADXOutlookFormsManager. Select the newly added ADXOutlookFormsManager and click on the ellipses (…) button next to its Items property. Add a new item to the forms collection by clicking the Add button. Change the item’s InspectorItemTypes property to Task, the InspectorLayout property to BottomSubPane and finally select the ADX Outlook form you’ve added to your project previously from the dropdown list of the FormClassName property. We’ll use this form to display the resources assigned to the task in Outlook.

Add the following code to the forms’ Load event:

private void ADXOlForm2_Load(object sender, EventArgs e)
{
    object item = ((Outlook.Inspector)this.InspectorObj).CurrentItem;
    if (item is Outlook.TaskItem)
    {
        Outlook.TaskItem outlookTask = (Outlook.TaskItem)item;
        Outlook.UserProperties outlookUserProperties = outlookTask.UserProperties;
        Outlook.UserProperty outlookUserProperty = null;
        try
        {
            outlookUserProperty = outlookUserProperties["OtherResources"];
        }
        catch () {}
        if (outlookUserProperty != null)
        {
            txtResources.Text = outlookUserProperty.Value.ToString();
            Marshal.ReleaseComObject(outlookUserProperty);
        }
        Marshal.ReleaseComObject(outlookUserProperties);
    }
    Marshal.ReleaseComObject(item);
}

And add a new Outlook Item Events Class to your project.

Adding a new Outlook item events class

Then, add the following code to ProcessWrite :

public override void ProcessWrite(AddinExpress.MSO.ADXCancelEventArgs e)
{
    Outlook.TaskItem outlookTask = (Outlook.TaskItem)this.ItemObj;
    MSProject.ApplicationClass projectApp = new MSProject.ApplicationClass();
    projectApp.FileOpenEx(@"C:\ProjectPlans\NwindPlan.mpp");
 
    Outlook.UserProperties outlookUserProperties = outlookTask .UserProperties;
    Outlook.UserProperty outlookUserProperty = null;
    try
    {
        outlookUserProperty = outlookUserProperties["TaskUniqueId"];
    }
    catch () {}
    Marshal.ReleaseComObject(outlookUserProperties);
    if (outlookUserProperty != null)
    {
 
        MSProject.Project projectProject = MSProjectApp.ActiveProject;
        MSProject.Tasks projectTasks = projectProject.Tasks;
        MSProject.Task projectTask = projectTasks.get_UniqueID(
           (int)outlookUserProperty.Value);
        projectTask.PercentComplete = outlookTask.PercentComplete;
        Marshal.ReleaseComObject(projectTask);
        Marshal.ReleaseComObject(projectTasks);
        Marshal.ReleaseComObject(projectProject);
        projectApp.FileCloseEx(MSProject.PjSaveType.pjSave);
 
        Marshal.ReleaseComObject(outlookUserProperty);
    }
    Marshal.ReleaseComObject(projectApp);
}

Next, add a new ADXOutlookAppEvents component to the AddinModule designer, and double-click its InspectorActivate property in order to generate the event handler code for it. The code in the InspectorActivate event must look like this:

private void adxOutlookEvents_InspectorActivate
    (object sender, object inspector, string folderName)
{
    Outlook._Inspector olInsp = (Outlook._Inspector)inspector;
    object item = olInsp.CurrentItem;
     if (item is Outlook.TaskItem)
       {
          itemEvents.ConnectTo(item, true);
        }
}

Be sure to declare the itemEvents object in your AddinModule class:

private OutlookItemEvents itemEvents = null;

Also add the following to your AddinModule StartupComplete event:

private void AddinModule_AddinStartupComplete(object sender, EventArgs e)
{
    itemEvents = new OutlookItemEvents(this);
}

What we’ve done now, is to add logic to create the tasks in MS Outlook as well as the ability to update the task percentage, which also automatically updates the MS Project plan. Additionally, we’ve added a region to the task item in Outlook to display the resources assigned to the specific task e.g.:

A region added to the task item in Outlook

And as easy as that and you have integration between MS Outlook and MS Project 2010.

Thank you for reading! Until next time, keep coding.

4 Comments

  • https://secure.gravatar.com/avatar/43ab3772bfc2f6633904869cd0b8341f?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Diego Mejía says:

    Hi! Pieter.
    I’m working on my company to integrate a system created some years ago on C# with Outlook 2007 and MS Project, and i was wondering some things:

    1. With this code, can i create tasks on Outlook and those tasks will be integrated to an specific project file and vice versa?
    2. If for example the MS Project program is off (I do not have the program and file open) and i create a new task on Outlook, “the add-in” can add the new task to the project file automatically, and vice versa?
    3. There is an web-version of Outlook and Ms Project… This code works on them too?
    4. Can i integrate this solution to another sistem like a C# application?

  • https://secure.gravatar.com/avatar/e1a4c2b21a5186e0b27c1c601f418b76?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Pieter van der Westhuizen says:

    Hi Diego,

    1. Yes, you would be able to create tasks in both Outlook and MS Project.
    2. Mmm…I haven’t tried it, but in theory it should be possible to still use the MS Project object module without the application actually running.
    3. No, the code wont work on the web version.
    4. Yes, you would be able to use the MS Project object model from a C# application.

    Thank you for your comment.

    Kind regards,
    Pieter

  • https://secure.gravatar.com/avatar/ea48d208962762b62f18bb997d708858?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Aniket sathe says:

    Sir, I want to create app using Vb with asp.net. So can you give me guidelines.

  • https://secure.gravatar.com/avatar/e1a4c2b21a5186e0b27c1c601f418b76?s=32&d=https%3A%2F%2Fsecure.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Pieter van der Westhuizen says:

    Hi There,

    Not really sure which app you have in mind. If you want to create a web app using asp.net have a look at http://www.asp.net/

    If you want to create an App for Office, have a look at our blog. You can find all blog entries about Apps for Office at http://www.add-in-express.com/creating-addins-blog/tag/apps-for-office/

    Hope this helps!

Post a comment

Have any questions? Ask us right now!