John Clarkson
Microsoft Corporation
February 1999
Summary: Describes how to create and distribute add-ins in Microsoft® Word 97 (this example also requires Microsoft Outlook® 98) by using .dot files containing Microsoft Visual Basic® for Applications (VBA) code. (9 printed pages) Covers:
Introduction
Creating Word Add-ins
Loading Word Add-ins
Triggering Add-in Code
Creating the AddressBook Report Add-in
The AddressBook Add-in Code
Distributing Your Solution
Conclusion
Usually you use .dot files to build templates in Word, but you can also use them to create add-ins. This article show you how to create a sample add-in, launched from the Tools menu, that opens a new Word document and copies into it the contents of the Outlook Personal Address Book.
Because we're going to be taking a template and dressing it up as an add-in, let's define what add-ins and templates are. Word Help defines add-ins as "supplemental programs that extend the capabilities of Word by adding custom commands and specialized features." A template is defined as a "special kind of document that provides basic tools for shaping a final document." Templates can contain the following elements:
Microsoft Access, PowerPoint®, and Excel all offer separate file types (.mda, .ppa, and .xla, respectively) to store add-ins. Word only offers .dot files, so we're setting out here to create a Word add-in in a template (.dot) file.
The general process for using Visual Basic for Applications to create a Word .dot add-in runs like this:
There are three ways to load add-ins in Word 97:
Sub LoadingProgrammatically
AddIns.Add FileName:= "c:\addin.dot"
End Sub
To add an add-in to the collection without loading it, pass in False for the optional install argument. The following procedure is an example of programmatically adding an add-in to the AddIns collection without loading it:
Sub LoadingProgrammatically
AddIns.Add FileName:= "c:\addin.dot", install:=False
End Sub
If you have any initialization work to do when an add-in loads, or cleanup work to do when it unloads, you'll want to be able to run code automatically when the loading and unloading occur. Use auto macros to run code automatically when an add-in is loaded or unloaded.
For more information, click AutoExec in the Word Help index to display the "Auto Macros" Help topic.
This section describes the code and procedures to create the AddressBook Report add-in. The add-in installs itself automatically when Word is loaded, adding a custom command to the Tools menu. When the command is selected, the add-in opens a new document in Word, sets a reference to the Personal Address Book in Outlook, and copies the addresses to the Word document.
Note This example was created on a system that uses Outlook 98. Results may differ if you use a previous version of Outlook. It also depends on the presence of a Personal Address Book (.pab file). The code includes an error trap that shuts the solutions down if an address book is not found.
Option Explicit
Sub AutoExec()
' Adds an item to the Tools menu.
' This procedure runs automatically when the add-in loads.
Dim offCmdBrPp As CommandBarPopup ' This will be set to
' the Tools menu.
Dim offCmdBtn As CommandBarButton ' This will be set to
' the Project command.
' Create an object variable referring to the Tools menu.
Set offCmdBrPp = _
Application.CommandBars("Menu Bar").Controls("Tools")
' If the Address Book Report command already exists, delete it.
On Error Resume Next
offCmdBrPp.Controls("Address Book Report").Delete
' Add a command in the 4th position on the Tools menu.
Set offCmdBtn = _
offCmdBrPp.Controls.Add(Type:=msoControlButton, Before:=4)
' Set properties on the new command.
With offCmdBtn
.Caption = "Address Book Report"
.OnAction = "ListAddresses"
End With
End Sub
Sub AutoExit()
' Deletes an item on the Tools menu.
' This procedure runs automatically when the add-in unloads.
' If the AddressBook Report command exists, delete it.
On Error Resume Next
Application.CommandBars("Menu Bar").Controls _
("Tools").Controls("Address Book Report").Delete
End Sub
Sub ListAddresses()
' This procedure adds Outlook addresses to a new Word document.
' Called by the OnAction property in the AutoExec procedure.
Dim olList As AddressList ' Outlook address book.
Dim olEntry As AddressEntry ' Outlook address item.
Dim appOutl As Outlook.Application
Dim olNmSpc As Outlook.NameSpace
Dim wrdReportPara As Word.Range
Dim intRepeat As Integer
' Set a reference to an Outlook addresss book.
Set appOutl = New Outlook.Application
Set olNmSpc = appOutl.GetNamespace("MAPI")
' If your system doesn't have a PAB installed,
' the solution will end.
On Error GoTo NoPABAvailable
Set olList = olNmSpc.AddressLists("Personal Address Book")
' Open a new blank document.
Documents.Add
' Add and format text.
' Add 5 paragraphs.
For intRepeat = 0 To 4
ActiveDocument.Paragraphs.Add
Next intRepeat
' Set this object to the 4th paragraph.
Set wrdReportPara = ActiveDocument.Paragraphs(4).Range
' Add and format text.
wrdReportPara.InsertBefore Text:="Address Book"
With wrdReportPara.Font
.Name = "arial"
.Size = 12
.Bold = True
.Italic = True
End With
' Select a range, add a paragraph.
Set wrdReportPara = wrdReportPara.Next
Call AddPara(wrdReportPara)
' Add addresses to the active document.
For Each olEntry In olList.AddressEntries
wrdReportPara.InsertBefore olEntry.Name
Call AddPara(wrdReportPara)
wrdReportPara.InsertBefore olEntry.Address
Call AddPara(wrdReportPara)
Call AddPara(wrdReportPara)
Next
' If your system doesn't have a PAB installed,
' the solution will end.
NoPABAvailable:
MsgBox "Personal Address Book is not available." _
vbTab "Shutting down."
End
' Clean up object variables.
Set olList = Nothing
Set olNmSpc = Nothing
Set appOutl = Nothing
Set wrdReportPara = Nothing
End Sub
Sub AddPara(wrdReportPara As Word.Range)
' This procedure adds a paragraph and resets the current Range.
' Called from the ListAddresses procedure.
ActiveDocument.Paragraphs.Add
Set wrdReportPara = wrdReportPara.Next
End Sub
Note If you set the folder location first, you may find that when you set the file type, Windows automatically transfers you to the \Templates folder. This is not where you want the file to be located, so set it back to the \Startup folder (or follow the order just shown).
The most interesting issues in the code for this add-in are initializing and cleanup, and setting the appropriate reference to the Outlook object library.
The AutoExec and AutoExit procedures run when the add-in is loaded and unloaded and are a convenient location for initialization and cleanup code. In this case we're adding an AddressBook Report command to the Tools menu, which will be used to launch the add-in.
One minor hurdle in customizing Word menus is determining the name of the particular command bar you want to work with. You can solve this by printing a list of all command bar names, and then combining guesswork with a process of elimination to find the right one. This procedure prints the name of each command bar to the Immediate window:
Sub PrintNames()
For Each CommandBar In CommandBars()
Debug.Print CommandBar.Name
Next CommandBar
End Sub
The AutoExec procedure contains code that initializes the add-in. The most important task is adding the AddressBook Report custom command to the Tools menu.
Set objCmdBtn = _
objCmdBrPp.Controls.Add(Type:=msoControlButton, Before:=4)
The OnAction property of the CommandBarButton object identifies which procedure runs when the command is selected.
With objCmdBtn
.Caption = "AddressBook Report"
.OnAction = "ListAddresses"
End With
The AutoExit procedure is called when the AddressBook Report selection is cleared in the Templates and Add-ins dialog box. Placing code in AutoExit that deletes the custom command allows users to remove the command and continue working in Word.
Application.CommandBars("Menu _
Bar").Controls("Tools").Controls("AddressBook Report").Delete
The ListAddresses procedure is used to set a reference to Outlook and add data to the Word document. However, first we need to add a new document:
Documents.Add
and insert blank paragraphs and a formatted heading:
For intRepeat = 0 To 4
ActiveDocument.Paragraphs.Add
Next intRepeat
Set objRange = ActiveDocument.Paragraphs(4).Range
objRange.InsertBefore Text:="Address Book"
With objRange.Font
.Name = "arial"
.Size = 12
.Bold = True
.Italic = True
End With
The Outlook data we're looking for is contained in the AddressLists collection, which contains the Outlook address book hierarchy. This statement sets a reference to the Personal Address Book:
Set objList = objNmspc.AddressLists("Personal Address Book")
Of course you can modify this add-in to print the contents of other address books. To see what address books are available on your system, run the following procedure:
Sub ListAddressBooks()
Dim objList As AddressList ' Outlook address book.
Dim objEntry As AddressEntry ' Outlook address item.
Dim appOutl As Outlook.Application
Dim objNmspc As Outlook.NameSpace
Set appOutl = New Outlook.Application
Set objNmspc = appOutl.GetNamespace("MAPI")
For Each AddressList In objNmspc.AddressLists
Debug.Print AddressList.Name
Next AddressList
End Sub
The AddressEntries property of an Outlook AddressList object is referenced to retrieve each record. A For Each...Next loop is used to iterate through the Outlook address book and call a procedure that inserts spaces in the report.
For Each objEntry In objList.AddressEntries
objRange.InsertBefore objEntry.Name
Call AddPara(objRange)
objRange.InsertBefore objEntry.Address
Call AddPara(objRange)
Call AddPara(objRange)
Next
Your solution will be more valuable and easier to use if it's easy to distribute and install. With even the simplest solution there's great value in having it wrapped up in a setup application that walks the user through the installation process and ensures that all the correct pieces go in the proper places on the user's machine. Use the Setup Wizard included with the Microsoft Office 97 Developer Edition to handle packaging and installation issues. For more information, see the section "Distributing Your Solution with the Setup Wizard" in the article "Distributing Microsoft Excel 97, Word 97, and PowerPoint 97 Solutions."
This article provided step-by-step procedures, complete sample code, and comments explaining the code for a sample solution creating an add-in in a Word 97 template file. The concepts and code in this article could easily be used to create other add-ins packaged in .dot (template) files and exposed to users as custom menu commands in Word 97.