Andrei Smolin

How to show an Outlook.MailItem in PrintPreview mode programmatically

The Outlook object model doesn’t allow showing the PrintPreview dialog. To show it in all Outlook versions, you need to call the Execute method of a corresponding command bar button. Also, in Outlook 2007 and 2010, you can invoke the corresponding Ribbon command using the ExecuteMso method of the Office.CommandBars class. Let’s see how to do this.

Every built-in command bar control can be identified by its ID. You find the ID using our free Built-in Control Scanner – run an Office application, run the scanner, click Scan and find all controls on all command bars available in the application. Note that Outlook inspector window supports command bars of its own, so to get the ID of a built-in command bar control in an Outlook inspector, you need to open that inspector first.

On the screenshot below, you can see the Print Preview button selected in the Built-in Control Scanner window:

Print Preview button in the Control Scanner window

That is, the ID of the Print Preview button in the command bar system is 109. It is the same in all Office applications.

Now, let’s find that command bar button programmatically:

C# sample for Outlook 2000 – 2010:

void ShowPrintPreview()
{
    Outlook.Inspector inspector = OutlookApp.ActiveInspector();
    if (inspector != null)
    {
        Office.CommandBars cBars = inspector.CommandBars;
        Office.CommandBarControls cControls =
            cBars.FindControls(Office.MsoControlType.msoControlButton, 109, Type.Missing, Type.Missing);
        if (cControls.Count != 0)
        {
            Office.CommandBarButton printPreviewButton = cControls[1] as Office.CommandBarButton;
            printPreviewButton.Execute();
            Marshal.ReleaseComObject(printPreviewButton);
        }
        else
            MessageBox.Show("The PrintPreview button isn't available in the UI. Probably, the user has removed it.");
        Marshal.ReleaseComObject(cBars);
        Marshal.ReleaseComObject(inspector);
    }
    else
        MessageBox.Show("This function requires an inspector window being open");
}

That is, for the active inspector window, the code gets all command bar buttons whose ID equals to 109 and invokes the Execute method for the first of them. Note that the user may remove that button from the UI and this may prevent your code from showing the inspector in the PrintPreview mode.

That code will also work in Outlook 2007 – 2010, because, although they introduced the Ribbon UI in Outlook 2007 inspectors, the built-in command bars are left in the UI, though invisible. With the Ribbon UI, you may want to use the following approach:

C# sample for Outlook 2007, 2010:

void ShowPrintPreview12AndHigher()
{
    Outlook.Inspector inspector = OutlookApp.ActiveInspector();
    if (inspector != null)
    {
        Office.CommandBars cBars = inspector.CommandBars;
        cBars.ExecuteMso("FilePrintPreview");
        Marshal.ReleaseComObject(cBars);
        Marshal.ReleaseComObject(inspector);
    }
    else
        MessageBox.Show("This function requires an inspector window being open");
}

The code above executes the FilePrintPreview Ribbon command. Note that the command name is also the ID of the corresponding built-in Ribbon control. You can download IDs of built-in controls at Microsoft; for Office 2007, see here; for Office 2010, see this page. The download installs Excel files; the Control Name column of each contains the IDs of almost all built-in Ribbon controls for the corresponding Ribbon.

ShowPrintPreview12AndHigher (see above) will work only if your code refers to an interop for Office 2007 or Office 2010. But even if your code uses interops for an older Outlook version, you can use late binding to call CommandBars.ExecuteMso(…) when your add-in is loaded in Outlook 2007 and 2010:

C# sample for Outlook 2007, 2010:

void ShowPrintPreview12AndHigherLateBinding()
{
    Outlook.Inspector inspector = OutlookApp.ActiveInspector();
    if (inspector != null)
    {
        Office.CommandBars cBars = inspector.CommandBars;
        string olVersion = this.HostVersion.Substring(0, 2);
        if (olVersion == "12" || olVersion == "14")
            cBars.GetType().InvokeMember("ExecuteMso", System.Reflection.BindingFlags.InvokeMethod,
                null, cBars, new object[1] { "FilePrintPreview" });
        Marshal.ReleaseComObject(cBars);
        Marshal.ReleaseComObject(inspector);
    }
    else
        MessageBox.Show("This function requires an inspector window being open");
}

On request, I can provide the VB.NET versions of the functions above.

Good luck!

You may also be interested in

Supporting several Office versions in an add-in. Interop assemblies and late binding.

2 Comments

  • Walter ZAMBOTTI says:

    Please post the VB.NET versions of these functions.

  • Andrei Smolin (Add-in Express Team) says:

    Hello Walter,

    Private Sub ShowPrintPreview()
    Dim inspector As Outlook.Inspector = OutlookApp.ActiveInspector
    If (Not (inspector) Is Nothing) Then
    Dim cBars As Office.CommandBars = inspector.CommandBars
    Dim cControls As Office.CommandBarControls = cBars.FindControls(Office.MsoControlType.msoControlButton, 109, Type.Missing, Type.Missing)
    If (cControls.Count <> 0) Then
    Dim printPreviewButton As Office.CommandBarButton = CType(cControls(1), Office.CommandBarButton)
    printPreviewButton.Execute
    Marshal.ReleaseComObject(printPreviewButton)
    Else
    MessageBox.Show(“The PrintPreview button isn’t available in the UI. Probably, the user has removed it.”)
    End If
    Marshal.ReleaseComObject(cBars)
    Marshal.ReleaseComObject(inspector)
    Else
    MessageBox.Show(“This function requires an inspector window being open”)
    End If
    End Sub

    Private Sub ShowPrintPreview12AndHigher()
    Dim inspector As Outlook.Inspector = OutlookApp.ActiveInspector
    If (Not (inspector) Is Nothing) Then
    Dim cBars As Office.CommandBars = inspector.CommandBars
    cBars.ExecuteMso(“FilePrintPreview”)
    Marshal.ReleaseComObject(cBars)
    Marshal.ReleaseComObject(inspector)
    Else
    MessageBox.Show(“This function requires an inspector window being open”)
    End If
    End Sub

    Private Sub ShowPrintPreview12AndHigherLateBinding()
    Dim inspector As Outlook.Inspector = OutlookApp.ActiveInspector
    If (Not (inspector) Is Nothing) Then
    Dim cBars As Office.CommandBars = inspector.CommandBars
    Dim olVersion As String = Me.HostVersion.Substring(0, 2)
    If ((olVersion = “12”) _
    OrElse (olVersion = “14”)) Then
    cBars.GetType.InvokeMember(“ExecuteMso”, System.Reflection.BindingFlags.InvokeMethod, Nothing, cBars, New Object() {“FilePrintPreview”})
    End If
    Marshal.ReleaseComObject(cBars)
    Marshal.ReleaseComObject(inspector)
    Else
    MessageBox.Show(“This function requires an inspector window being open”)
    End If
    End Sub

Post a comment

Have any questions? Ask us right now!