Reestablish links to Outlook contacts after exporting a mailbox

Sooner or later, every administrator of a Microsoft Exchange Server 5.5 (or earlier) system needs to move a mailbox from one site or container to another. A classic solution is to export the entire mailbox to a personal store (.pst) file, add the new mailbox, then import the .pst data into the new mailbox. Alternatively, you can use the Microsoft BackOffice Resource Kit's Exmerge utility to help automate that process.

Many administrators discover only after the fact that exporting to a .pst file and importing into a new mailbox breaks all the links between Microsoft Outlook items and related contacts. (Moving items within a mailbox doesn't break the links, as importing and exporting does.) For example, if after importing you double-click a link in the Contacts box on a task item, you get the error message The name or distribution list has been deleted and is no longer a valid Address Book entry. The operation failed. An object could not be found.

The message is accurate if not particularly helpful. By exporting and importing, you've actually created new contact items, and Outlook no longer has the original contact items that you linked to. Outlook provides no way to reconnect the links to their related contact items, other than to retype the contact names in the Contacts box.

In most cases, you can restore the links with the VBA ReconnectLinks subroutine in Listing 1, page 110, which examines all the items in a folder that the user selects and attempts to find the related contacts in the user's default Contacts folder. The code gets the name of each link and tries to find a matching contact in the Contacts folder. If the code finds a match, it deletes the old link and creates a new link to that matching contact. (The code can't find links that the user might have made to contacts in a different folder; you'll still need to fix those manually.)

Reading Listing 1's code gives you a fine opportunity to learn about the Links collection, which stores all the connections to contacts and displays them in an Outlook item's Contacts box. (In an email message, you must click View, Options to see the Contacts box.)

If you look in the Object Browser (press F2 while you're working in VBA), you'll see that every Outlook item object (e.g., AppointmentItem, MailItem) supports a Links collection, even NoteItem (the Outlook equivalent of sticky notes). Like other collections, Links has a Count property that lets you know how many links the item has, and the three standard collection methods: Add, Item, and Remove.

To get an object reference to a particular Link object in the Links collection, you use the Item method. At callout A in Listing 1, the code gets the Count from the Links collection, then counts down from that number to 1, using the Item method to obtain each Link in turn.

The code counts down in a For ... Next loop instead of a For Each ... Next loop because later the code removes the broken Link objects. If you remove an item inside a For Each ...Next loop, you end up skipping items because the parent application resets the index counter. I start with the Link that has the highest index number and work down so that I can replace each one in turn. To remove a Link from the Links collection, you need to specify its index:

colLinks.Remove i

A user can simply type a name into the Contacts box and create a link, even if no matching contact exists. However, a program that needs to add a Link to the Links collection must first obtain a valid ContactItem object. The Add method requires a ContactItem as an argument:

colLinks.Add objContact

A Link object has two primary properties: Name and Item. If the link is connected to a valid Outlook contact, the Item property returns the linked ContactItem. In the case of disconnected links, however, trying to access the Item results in a runtime error because the link is broken. (That's why Listing 1 contains the On Error Resume Next statement.)

Even though the Item property causes a problem, the program can still get the value of the Name property. After a little experimentation, I found that the text that Outlook uses for the Name property for a Link object is the FullName property of the corresponding ContactItem. This clue is what you need to find the item in the current default Contacts folder that corresponds to the broken link. The code at callout B assumes that just one contact has that name and uses the Find method to locate that contact. The Find method returns the first match for the search string that you provide as an argument (strFind, in this example).

One caution about using the ReconnectLinks routine: Outlook has a known memory-leak problem when processing large Items collections in a For Each ... Next loop. If you have folders with thousands of items that need to be relinked, you might want to move a few hundred items at a time into a temporary folder, run ReconnectLinks, then move the items back into their original folder. Increasing your Windows pagefile size might also help you avoid the memory leak. The Microsoft article "OL2000: Memory or Performance Problems Looping Through Items" ( also suggests a possible solution if the items you need to process use custom forms.

To learn more about using the Links collection to link items to contacts, see the following Exchange & Outlook UPDATE newsletter articles at "Linking Outlook Contacts," InstantDoc ID 20353, and "More About Links," InstantDoc ID 20475.