Pieter van der Westhuizen

Creating modular Office add-ins using Add-in Express

When creating a new Office extension with Add-in Express for Office and .net you have the option to design your entire add-in user interface using our visual designers, by simply dropping the various components on the design surface of the AddinModule.

This is fine for most Office add-ins especially when you do not require a lot of custom user interface elements and customization. However, when you start to have many components your AddinModule‘s design surface can quickly become very crowded and hard to maintain.

Also, what if you want to enable or disable certain aspects of your add-in depending on the edition or version of your product the user bought?

Luckily Add-in Express has you covered! If you select the AddinModule and check its properties, you may notice a property called Modules. This property contains a collection of ADXAddinAdditionalModule items.

Modular add-in’s architecture

Before we jump into some code, let’s take a high level look at the architecture of a modular add-in first. We’ll create a modular add-in for Microsoft Outlook 2010 and our sample add-in will have the following three parts:

  • Main Add-in – This will be our main add-in and will contain the AddinModule class and the Outlook Explorer UI elements;
  • Contacts Module – This module will contain Outlook Contact specific functionality and Contact Inspector UI elements, which the user will be able to turn on or off; and
  • Tasks Module – Another additional module that contains Outlook Task specific functionality and Inspector UI elements that can be switched on or off.

Creating the main Outlook add-in

We’ll be using Visual Studio 2012 with Add-in Express for Office and .net 7.0, but this approach will work equally well in Visual Studio 2005, 2008 and 2010. First, create a new ADX COM Add-in project.

Creating a new COM Add-in for Outlook in Visual Studio 2012

Choose the minimum Office version you’d like to support and which Microsoft Office application you’d like your add-in to support; in this example we’ll develop an add-in for Microsoft Office Outlook 2010 and 2013.

Open the AddinModule in the MainAddin project and add an ADXRibbonTab component onto its designer surface, then right-click and select Properties:

  1. Change the Caption property to My Modular Addin
  2. Set the Ribbons property to OutlookExplorer

Next, add a Ribbon Group to the Ribbon tab, by clicking on the ADXRibbonGroup button in the visual designer toolbar.

Adding a new Ribbon group using a visual designer

Configure the Ribbon Groups’ properties:

  1. Set the Caption property to Configuration

Add two checkbox controls (ADXRibbonCheckBox) to the Ribbon Group and set their properties as follows:

  1. Change the first checkbox (Name) property to enableContactsRibbonCheckBox;
  2. Set the first checkbox Caption property to Enable Contacts Module;
  3. Change the second checkbox (Name) property to enableTasksRibbonCheckBox; and
  4. Change the second checkbox Caption property to Enable Tasks Module.

Custom Ribbon tab with a ribbon group and 2 buttons in the Add-in Express visual designer

Adding additional modules to your Outlook add-in

At this point you have a choice to either add an additional module inside the MainAddin project or create separate projects for each one. Personally I prefer splitting my modules into separate projects, so we’ll take that approach.

Add a new Class Library project to your add-in solution in Visual Studio and call it ContactsModule.

Adding a new Class Library project to the existing Visual Studio 2012 solution

Next, add a COM Add-in Additional Module item, called AddinModule, to the class library and click OK.

Adding a new COM add-in module to the project

Before the ContactsModule project will build, you need to add a reference to the System.Windows.Forms and System.Drawing assemblies.

Selecting required assemblies

Next, select ContactsModule Properties… from the Project menu and click on the Assembly Information… button in the Application tab. Check the Make assembly COM-Visible checkbox and click OK.

Making the assembly COM-Visible

Whilst still on the Properties window, click on the Build tab and check the Register for COM interop checkbox.

Registering the assembly

Adding the module UI for Outlook contact and task items

Switch to the design surface of the AddinModule in the ContactsModule project. Here you can add a number of components, but not all. Components such as the Application-Level events, task pane managers and Outlook Forms managers cannot be added to an AdditionalModule and must be created on the Main Module.

Go ahead and add a new Ribbon Tab component to the AddinModule design surface and view its properties.

  1. Change the Caption property to Contacts Tab; and
  2. Change the Ribbons property to OutlookContact.

Next, add a Ribbon Group to the Ribbon tab and set the Caption property to Contact Actions

Add a button to the Ribbon Group and configure its prop
erties:

  1. Change Caption to Send to CRM; and
  2. Set the Size property to Large.

The design of your Outlook ribbon tab should resemble the following image:

Design of the new Ribbon tab

Repeat the above process and add a new Class Library called TasksModule. This project will be used for our Task specific module. With this module, we’ll add another Ribbon Tab that will only be visible for Outlook tasks.

Loading additional modules at runtime

Now that we’ve created our additional modules it’s time to load and display them depending on whether the module is enabled. First, we need to add the two additional modules to the MainAddins’ Module property. Open the MainAddins’ AddinModule designer surface and click the elipses (…) next to the Modules property.

Adding additional modules to the Modules collection

Add two items to connect the additional modules to the main one. Set the ModuleProgID property of the tasks module to TasksModule.AddinModule and the ModuleProgID property of the contacts module to ContactsModule.AddinModule.

Setting the ModuleProgID property

Next, we need to add two settings to our MainAddin project, called ContactsModuleEnabled and TasksModuleEnabled.

Adding settings to the main add-in project

Add references to the two additional modules to the MainAddin project by right-clicking on the MainModule project name and selecting Add Reference… from the context-menu. Click on the Solutions tab and check both checkboxes in the list.

Adding two class library projects to the References section of the main project

Next, add OnClick event handlers for the two check boxes we’ve added earlier:

C# code example:

private void enableTasksRibbonCheckBox_OnClick(object sender,
	IRibbonControl control, bool pressed)
{
    Properties.Settings.Default.TasksModuleEnabled =
		enableTasksRibbonCheckBox.Pressed;
    Properties.Settings.Default.Save();
}
 
private void enableContactsRibbonCheckBox_OnClick(object sender,
	IRibbonControl control, bool pressed)
{
    Properties.Settings.Default.ContactsModuleEnabled =
		enableContactsRibbonCheckBox.Pressed;
    Properties.Settings.Default.Save();
}

Add another event handler for the AddinModule’s AddinStartupComplete event. In this event we’ll load the values that were saved in the settings file:

private void AddinModule_AddinStartupComplete(object sender,
	EventArgs e)
{
    enableContactsRibbonCheckBox.Pressed =
		Properties.Settings.Default.ContactsModuleEnabled;
    enableTasksRibbonCheckBox.Pressed =
		Properties.Settings.Default.TasksModuleEnabled;
}

Finally, because the additional module project contains Ribbon controls we need to add the code to enable the modules in the AddinModule’s OnRibbonBeforeCreate event:

private void AddinModule_OnRibbonBeforeCreate(object sender,
	string ribbonId)
{
    tasksAddinAdditionalModuleItem.Enabled =
		enableTasksRibbonCheckBox.Pressed;
    contactsAddinAdditionalModuleItem.Enabled =
		enableContactsRibbonCheckBox.Pressed;
}

In case you’re wondering what the ModuleProgID should be, you can find it by opening the additional module’s code view:

The ProgId attribute of the additional module

After all the code is in place, you can build, register and run your add-in, and the Ribbon Tabs for the Contact and Task inspectors should be visible if the appropriate checkbox is checked.

Using this approach enables you to create a fully featured modular add-in for Microsoft Office Outlook, Excel, Word and other apps and gives you the option to add and remove components of your add-in depending on the users’ preference.

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

Available downloads:

This sample Outlook plig-in was developed using Add-in Express for Office and .net:
C# modular add-in for Outlook 2010 and 2013.

10 Comments

  • http://0.gravatar.com/avatar/0c59a5d2bb8e2b222cf90d7c94362aa4?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Leo Romano says:

    Hi Pieter,
    Is it possible to remove a lot of this design-time “tight coupling” and use IoC or Dependency Injection to connect these add-ins at run-time? Any ideas? Examples?

    My guess is that it is not really do able and mainly because in the end there is COM to deal with but your insight would be greatly appreciated.

    Thanks,
    Leo

  • http://0.gravatar.com/avatar/ab4ec2858cfdf1e44dadf8c50fae314d?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Dmitry Kostochko (Add-in Express Team) says:

    Hi Leo,

    I am a bit confused by your question. When saying “these add-ins” did you actually mean additional modules (because there is just one add-in in this example)? If so, IoC/DI will probably work as well, I don’t see any obstacles. You can create all objects at run-time, the key thing is to pass them to the Add-in Express core in the proper moment.

    If you are asking about something else, please clarify.

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

    Hi Leo,

    Although I’ve never done it myself IoC or Dependecy Injection should work.
    I found a good example of using IoC/DI with VSTO here: http://vstocontrib.codeplex.com/ but everything in there should also apply when creating ADX add-ins for Office.

    Thanks for you comment!

    -P

  • http://0.gravatar.com/avatar/0c59a5d2bb8e2b222cf90d7c94362aa4?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Leo Romano says:

    Thanks Dmitry and Pieter for the information. I’ll look over that project and see what its about.

    Take care,

    Leo

  • http://1.gravatar.com/avatar/13c44ef2d9d79dcca761a584be868def?s=32&d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Oliver says:

    Is the “Additional Module” functionality planned (or already possible?) for the VCL version of ADX, too? I always found it rather clunky to be forced to have everything (especially BackStage Views) on the one addin module…

  • Hi Oliver,

    We have never thought of adding additional modules in the VCL edition because in Add-in Express for Office and Delphi all nested controls are collection items while in the .NET edition they are components. As you probably know .NET components are added to the .cs or .vb source file which grows in size immensely, this was one of the reasons why we introduced additional modules.

    Thank you for the idea anyway!

  • http://0.gravatar.com/avatar/a553ca1a130aa74a4b4515d73b875547?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Ariel Mears says:

    This solution is great but i’m using an COM add-in module to contain my forms that I’m using in a solution module. I’m dynamically applying the solution formclass but can’t figure out how to apply the form name correctly. Can you offer some advice?

    Thanks for the help!

  • http://0.gravatar.com/avatar/ab4ec2858cfdf1e44dadf8c50fae314d?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Dmitry Kostochko (Add-in Express Team) says:

    Hi Ariel,

    You can use the fully qualified name of your form (including namespace), for example:
    MyClassLibrary.MyNamespace.MyForm

  • http://0.gravatar.com/avatar/a553ca1a130aa74a4b4515d73b875547?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Ariel Mears says:

    When I try to use the fully qualified name I end up with an error:
    A TeamViewContentManager.Views.frmWorkspace form instance has not been created.

  • http://0.gravatar.com/avatar/ab4ec2858cfdf1e44dadf8c50fae314d?s=32&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D32&r=G Dmitry Kostochko (Add-in Express Team) says:

    Hi Ariel,

    Oh, sorry, my fault. The ADXAddinAdditionalModule component that can be used in an additional class library can contain only UI components such as command bars, ribbon tabs, backstage views and Outlook solution modules. Advanced Outlook forms, advanced task panes and their managers should be located in the main add-in assembly. Sorry again for misleading you.

Post a comment

Have any questions? Ask us right now!