Pieter van der Westhuizen

Creating and modifying MS Project files programmatically

In my last two articles we looked at the MS Project object model and how to customize the MS Project UI. In this article, we’ll take what we’ve learned and explore how you can use data from other sources to either create or add to your MS Project files.

Create an MS Project file from scratch

Creating a MS Project file is relatively straight-forward. You’ll first need to create a new reference to the MS Project Application object and add a new project to its Projects collection by calling the Projects collections’ Add method.

The Add method accepts three parameters, the first is DisplayProjectInfo. Setting this property to true, will display the Project Information dialog with which the user can specify certain project properties.

Project Information dialog

The second parameter, Template, specifies the file name and path for a template to use, for creating the project. FileNewDialog is the last parameter and when set to true, displays a dialog where the user can select the template to use when creating the new project file. If the Template parameter is set to true, this parameter will be ignored.

MS Project templates

The following code will create a new Microsoft Project file after displaying the project properties and template dialog windows:

static void Main(string[] args)
{
    MSProject.Application projApp = null;
    MSProject.Projects projects = null;
    MSProject.Project project = null;
    try
    {
        projApp = new MSProject.Application();
        projects = projApp.Projects;
        project = projects.Add(true, null, true);
        project.SaveAs("C:\\Temp\\YourProject.mpp");
        projApp.Quit();
    }
    finally
    {
        if (project != null) Marshal.ReleaseComObject(project);
        if (projects != null) Marshal.ReleaseComObject(projects);
        if (projApp != null) Marshal.ReleaseComObject(projApp);
    }
}

Adding tasks, resources and milestones to a MS Project

To add tasks and resources to the newly created project you would need to first get a reference to the newly added project and its Tasks collection property. You would then call the Add method of the Tasks collection in order to add a new task to the project.

Interestingly, to add a resource to a task you do not need to create a resource by adding it to the projects’ Resources collection. By setting the task objects’ ResourcesNames property, MS Project will automatically add the resource to the projects’ resource list. You can also add more than one resource at a time by setting the ResourceNames property to multiple resource names separated by the list separator character specified in the Windows Regional and Language Options.

To mark a task as a milestone, set its Milestone property to true. The code below, adds four tasks to the project passed into the method as a parameter. Note how we assign two resources to the first task and set the third task as a milestone:

static void AddTasksResourceMilestone(MSProject.Project project)
{
    MSProject.Tasks tasks = null;
    MSProject.Task task1 = null;
    MSProject.Task task2 = null;
    MSProject.Task task3 = null;
    MSProject.Task task4 = null;
    try
    {
        tasks = project.Tasks;
 
        task1 = tasks.Add("Write and Sing Song");
        task1.Start = project.Start;
        task1.Duration = 480;
        task1.ResourceNames = "John,Paul";
 
        task2 = tasks.Add("Play Guitar");
        task2.Start = ((DateTime)task1.Finish).AddDays(1);
        task2.Predecessors = task1.ID.ToString();
        task2.Duration = 960;
        task2.ResourceNames = "George";
 
        task3 = tasks.Add("Play Drums");
        task3.Start = ((DateTime)task2.Finish).AddDays(1);
        task3.Milestone = true;
        task3.Predecessors = task2.ID.ToString();
        task3.Duration = 1440;
        task3.ResourceNames = "Ringo";
 
        task4 = tasks.Add("Play Bass");
        task4.Start = ((DateTime)task3.Finish).AddDays(1);
        task4.Predecessors = task3.ID.ToString();
        task4.Duration = 480;
        task4.ResourceNames = "Ringo";
    }
    finally
    {
        if (task4 != null) Marshal.ReleaseComObject(task4);
        if (task3 != null) Marshal.ReleaseComObject(task3);
        if (task2 != null) Marshal.ReleaseComObject(task2);
        if (task1 != null) Marshal.ReleaseComObject(task1);
        if (tasks != null) Marshal.ReleaseComObject(tasks);
    }
}

Import tasks and resources from Outlook into MS Project

With what we know so far, we can import tasks relatively easy from Outlook to MS Project and vice-versa. We’ll first create a new ribbon tab for Outlook (using Add-in Express for Office and .net) with which the user can import the selected tasks or contacts to MS Project as either tasks or resources.

Creating a new ribbon tab for Outlook to import the selected tasks or contacts to MS Project.

The following code will prompt the user to choose the Microsoft Project file to which they want to add the selected Outlook tasks. It will then loop through the selected items in Outlook, check whether the user selected Outlook task items and then add it to the MS Project file’s active project. We’ll add the following code to the “Add selected tasks as MS Project Tasks” button’s OnClick event:

private void createTasksRibbonButton_OnClick(object sender, 
    IRibbonControl control, bool pressed)
{
    MSProject.Application msProjApp = null;
    Outlook.Explorer currExplorer = null;
    Outlook.Selection selection = null;
    Outlook.TaskItem task = null;
    object item = null;
    MSProject.Project activeProject = null;
    MSProject.Tasks projectTasks = null;
 
    try
    {
        diagFileOpen.ShowDialog();
        if (!string.IsNullOrEmpty(diagFileOpen.FileName))
        {
            msProjApp = new MSProject.Application();
            msProjApp.FileOpenEx(diagFileOpen.FileName);
            activeProject = msProjApp.ActiveProject;
            projectTasks = activeProject.Tasks;
 
            currExplorer = OutlookApp.ActiveExplorer();
            selection = currExplorer.Selection;
 
            for (int i = 1; i <= selection.Count; i++)
            {
                item = selection[i];
                if (item is Outlook.TaskItem)
                {
                    task = item as Outlook.TaskItem;
                    projectTasks.Add(task.Subject);
                }
                Marshal.ReleaseComObject(item);
            }
            msProjApp.FileCloseEx(MSProject.PjSaveType.pjSave);
            msProjApp.Quit();
        }
    }
    finally
    {
        if (projectTasks != null) Marshal.ReleaseComObject(projectTasks);
        if (activeProject != null) Marshal.ReleaseComObject(activeProject);
        if (selection != null) Marshal.ReleaseComObject(selection);
        if (currExplorer != null) Marshal.ReleaseComObject(currExplorer);
        if (msProjApp != null) Marshal.ReleaseComObject(msProjApp);
    }
}

To add Outlook contacts to a MS Project file as resources, add the following code to the “Add selected contacts as MS Project Resources” button’s OnClick event:

private void createResourcesRibbonButton_OnClick(object sender,
    IRibbonControl control, bool pressed)
{
    MSProject.Application msProjApp = null;
    Outlook.Explorer currExplorer = null;
    Outlook.Selection selection = null;
    Outlook.ContactItem contact = null;
    object item = null;
    MSProject.Project activeProject = null;
    MSProject.Resources projectResources = null;
 
    try
    {
        diagFileOpen.ShowDialog();
        if (!string.IsNullOrEmpty(diagFileOpen.FileName))
        {
            msProjApp = new MSProject.Application();
            msProjApp.FileOpenEx(diagFileOpen.FileName);
            activeProject = msProjApp.ActiveProject;
            projectResources = activeProject.Resources;
 
            currExplorer = OutlookApp.ActiveExplorer();
            selection = currExplorer.Selection;
 
            for (int i = 1; i <= selection.Count; i++)
            {
                item = selection[i];
                if (item is Outlook.ContactItem)
                {
                    contact = item as Outlook.ContactItem;
                    projectResources.Add(contact.FullName);
                }
                Marshal.ReleaseComObject(item);
            }
 
            msProjApp.FileCloseEx(MSProject.PjSaveType.pjSave);
            msProjApp.Quit();
        }
    }
    finally
    {
        if (projectResources != null) Marshal.ReleaseComObject(projectResources);
        if (activeProject != null) Marshal.ReleaseComObject(activeProject);
        if (item != null) Marshal.ReleaseComObject(item);
        if (selection != null) Marshal.ReleaseComObject(selection);
        if (currExplorer != null) Marshal.ReleaseComObject(currExplorer);
        if (msProjApp != null) Marshal.ReleaseComObject(msProjApp);
    }
}

Export MS Project’s tasks and contacts into MS Outlook

The reverse of what we’ve done is also possible. Before we export resources as contacts and tasks as tasks in Outlook, we’ll first add a new ribbon tab in MS Project:

Creating a new ribbon tab MS Project to export the selected tasks or contacts to Outlook.

To export MS Project tasks into Outlook, use the following code:

private void importTasksRibbonButton_OnClick(object sender, 
    IRibbonControl control, bool pressed)
{
    Outlook.Application outlookApp = null;
    MSProject.Project currProject = null;
    MSProject.Selection selection = null;
    MSProject.Tasks selectedTasks = null;
    MSProject.Task pjTask = null;
    Outlook.TaskItem olTask = null;
 
    try
    {
        outlookApp = new Outlook.Application();
        currProject = MSProjectApp.ActiveProject;
 
        selection = MSProjectApp.ActiveSelection;
        selectedTasks = selection.Tasks;
 
        for (int t = 1; t <= selectedTasks.Count; t++)
        {
            pjTask = selectedTasks[t];
            olTask = outlookApp.CreateItem(
                Outlook.OlItemType.olTaskItem) as Outlook.TaskItem;
            olTask.Subject = pjTask.Name;
            olTask.Save();
            Marshal.ReleaseComObject(pjTask);
            Marshal.ReleaseComObject(olTask);
        }
        outlookApp.Quit();
    }
    finally
    {
        if (selectedTasks != null) Marshal.ReleaseComObject(selectedTasks);
        if (selection != null) Marshal.ReleaseComObject(selection);
        if (currProject != null) Marshal.ReleaseComObject(currProject);
        if (outlookApp != null) Marshal.ReleaseComObject(outlookApp);
    }
}

Exporting contacts from MS Project into Outlook will work in a similar fashion. This time you’ll need to use the MS Project Selection objects Resources property in order to get a list of selected resources in MS Project:

private void importContactsRibbonButton_OnClick(object sender,
    IRibbonControl control, bool pressed)
{
    Outlook.Application outlookApp = null;
    MSProject.Project currProject = null;
    MSProject.Selection selection = null;
    MSProject.Resources selectedResources = null;
    MSProject.Resource resource = null;
    Outlook.ContactItem contact = null;
 
    try
    {
        outlookApp = new Outlook.Application();
        currProject = MSProjectApp.ActiveProject;
 
        selection = MSProjectApp.ActiveSelection;
        selectedResources = selection.Resources;
 
        for (int r = 1; r <= selectedResources.Count; r++)
        {
            resource = selectedResources[r];
            contact = outlookApp.CreateItem(
                Outlook.OlItemType.olContactItem) as Outlook.ContactItem;
            contact.FullName = resource.Name;
            contact.Save();
            Marshal.ReleaseComObject(resource);
            Marshal.ReleaseComObject(contact);
        }
 
        outlookApp.Quit();
 
    }
    finally
    {
        if (selectedResources != null) Marshal.ReleaseComObject(selectedResources);
        if (selection != null) Marshal.ReleaseComObject(selection);
        if (currProject != null) Marshal.ReleaseComObject(currProject);
        if (outlookApp != null) Marshal.ReleaseComObject(outlookApp);
    }
}

Import tasks from MS Excel into MS Project

Lastly, we’ll add a ribbon tab in MS Excel to import the selected cells into MS Project as tasks. We’ll add one more ribbon tab, this time for MS Excel.

Creating a new ribbon tab MS Excel to import the selected cells into MS Project as tasks.

We’ll assume the user will select two columns in Excel, one containing the task name and the other the task start date, for example:

The selected cells to export to MS Project.

The following code will then loop through the selected Excel rows and add the tasks in MS Project, after prompting the user to select the target MS Project file:

private void importExcelTasksRibbonButton_OnClick(object sender,
    IRibbonControl control, bool pressed)
 {
     MSProject.Application msProjApp = null;
     MSProject.Project activeProject = null;
     MSProject.Tasks projectTasks = null;
     MSProject.Task task = null;
     Excel.Range selectedRange = null;
     Excel.Range taskNameRange = null;
     Excel.Range taskDateRange = null;
 
     try
     {
         diagFileOpen.ShowDialog();
         if (!string.IsNullOrEmpty(diagFileOpen.FileName))
         {
             msProjApp = new MSProject.Application();
             msProjApp.FileOpenEx(diagFileOpen.FileName);
             activeProject = msProjApp.ActiveProject;
             projectTasks = activeProject.Tasks;
 
             selectedRange = ExcelApp.Selection as Excel.Range;
 
             for (int i = 1; i <= selectedRange.Rows.Count; i++)
             {
                 taskNameRange = (Excel.Range)selectedRange[i, 1];
                 string taskName = taskNameRange.Value2.ToString();
                 task = projectTasks.Add((taskName));
                 taskDateRange = (Excel.Range) selectedRange[i, 2];
                 task.Start = taskDateRange.Value;
                 Marshal.ReleaseComObject(task);
             }
             msProjApp.FileCloseEx(MSProject.PjSaveType.pjSave);
             msProjApp.Quit();
         }
     }
     finally
     {
         if (taskDateRange != null) Marshal.ReleaseComObject(taskDateRange);
         if (taskNameRange != null) Marshal.ReleaseComObject(taskNameRange);
         if (selectedRange != null) Marshal.ReleaseComObject(selectedRange);
         if (projectTasks != null) Marshal.ReleaseComObject(projectTasks);
         if (activeProject != null) Marshal.ReleaseComObject(activeProject);
         if (msProjApp != null) Marshal.ReleaseComObject(msProjApp);
     }
 }

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

Available downloads:

This sample MS Project add-in was developed using Add-in Express for Office and .net:

Sample MS Project add-in (C#)

MS Project 2013 development in Visual Studio

Post a comment

Have any questions? Ask us right now!