Windows IT Pro is the leading independent community for IT professionals deploying Microsoft Windows server and client applications and technologies.
  
  
  Advanced Search 


October 2001

Making Contact


RSS
Subscribe to Windows IT Pro | See More Visual Basic (VB) Articles Here | Reprints | Or get the Monthly Online Pass—only $5.95 a month!

Download the Code Here

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" (http://support.microsoft.com/support/kb/articles/q293/7/96.asp) 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 http://www.win2000mag.com: "Linking Outlook Contacts," InstantDoc ID 20353, and "More About Links," InstantDoc ID 20475.

End of Article



Reader Comments
<P>Change the vb code to allow for a manual pick of contacts folder, ie not hardcoded. If you have contacts stored in another folder, this is very appriciated.<br><br></P>

<P>Sub ReconnectLinks()<br>
&nbsp;&nbsp;Dim objApp As Application<br>
&nbsp;&nbsp;Dim objNS As NameSpace<br>
&nbsp;&nbsp;Dim objFolder As MAPIFolder<br>
&nbsp;&nbsp;Dim colItems As Items<br>
&nbsp;&nbsp;Dim objItem As Object<br>
&nbsp;&nbsp;Dim colLinks As Links<br>
&nbsp;&nbsp;Dim objLink As Link<br>
&nbsp;&nbsp;Dim colContacts As Items<br>
&nbsp;&nbsp;Dim objContact As ContactItem<br>
&nbsp;&nbsp;Dim strFind As String<br>
&nbsp;&nbsp;Dim intCount As Integer<br>
&nbsp;&nbsp;Dim myFolder1 As MAPIFolder<br>
<br><br>

&nbsp;&nbsp;Set objApp = CreateObject("Outlook.Application")<br>
&nbsp;&nbsp;Set objNS = objApp.GetNamespace("MAPI")<br>
&nbsp;&nbsp;'set contacts folder<br>
&nbsp;&nbsp;Set myFolder1 = objNS.PickFolder<br>
&nbsp;&nbsp;'set tasks folder<br>
&nbsp;&nbsp;Set objFolder = objNS.PickFolder<br>
&nbsp;&nbsp;If TypeName(objFolder) <> "Nothing" Then<br>
&nbsp;&nbsp;&nbsp;&nbsp;'Set colContacts = objNS.GetDefaultFolder(olFolderContacts).Items
&nbsp;&nbsp;&nbsp;&nbsp;Set colContacts = myFolder1.Items<br>
&nbsp;&nbsp;&nbsp;&nbsp;Set colItems = objFolder.Items<br>
&nbsp;&nbsp;&nbsp;&nbsp;For Each objItem In colItems<br><br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set colLinks = objItem.Links<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;intCount = colLinks.Count<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If intCount > 0 Then<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;For i = intCount To 1 Step -1<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set objLink = colLinks.Item(i)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;On Error Resume Next<br><br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If objLink.Item Is Nothing Then<br><br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strFind = "[FullName] = " & AddQuotes(objLink.Name)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set objContact = colContacts.Find(strFind)<br><br>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If Not objContact Is Nothing Then<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' remove the old link<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;colLinks.Remove i<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' add the replacement link<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;colLinks.Add objContact<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;End If<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;End If<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Next<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If Not objItem.Saved Then<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;objItem.Save<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;End If<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;End If<br>
&nbsp;&nbsp;&nbsp;&nbsp;Next<br>
&nbsp;&nbsp;End If<br><br>

&nbsp;&nbsp;Set objLink = Nothing<br>
&nbsp;&nbsp;Set colLinks = Nothing<br>
&nbsp;&nbsp;Set objItem = Nothing<br>
&nbsp;&nbsp;Set objItems = Nothing<br>
&nbsp;&nbsp;Set objFolder = Nothing<br>
&nbsp;&nbsp;Set objNS = Nothing<br>
&nbsp;&nbsp;&nbsp;&nbsp;Set objApp = Nothing<br>
End Sub<br><br>

Private Function AddQuotes(MyText) As String<br>
&nbsp;&nbsp;&nbsp;&nbsp;AddQuotes = Chr(34) & MyText & Chr(34)<br>
End Function<br></P>

Göran Eriksson October 10, 2002


Running XP Home Edition with XP Office Pro:
Gave very erratic results -- some worked, others didn't. Blanked out names, etc. Changed the REGISTRY as suggested, but there was no difference. Standard form replaced custom form here and there, etc.

norm hadley June 29, 2003


Hello! I was very pleased to find this article, since the hundreds of links in my OL2002 .pst file were lost when I was required to export/import everything to fix another problem. However, not being a Visual Basic expert, I can't figure out how to actually run the code you provide with this article. I tried renaming the .txt file to .vbs and that didn't work. Can you tell me how to run the code? Thank you!

Don Ferguson November 28, 2003


Goran, take a look at the Namespace.PickFolder method, which returns a MAPIFolder that the user selects.

Sue Mosher January 28, 2004


Don, copy and paste the code from the .txt file into an Outlook VBA module. If you need really, really basic info, see http://www.win2000mag.com/Articles/Index.cfm?ArticleID=21522

Sue Mosher January 28, 2004


Hi Sue Mosher,
I see that Object Link name doesn't contain the Preffix Name, In this case the script doesn't work because objLink.Name <> FullName. So one suggestion is to parse ObjLink.name into FirstName, MiddleName, LastName and use them as criteria for search. I hope this is not just an error in My outlook contacts. Thanks for your Article.

Alami April 07, 2004


I ran the script, but nothing seems to happen. The script says it's running and finishes in less than 30 seconds. I have thousands of contacts so I expected it to run for a while. The error is not fixed after running the script.

I'm running OL 2000 SP-3 under Win2K. I ran the script by importing it into OL's VB engine, using Run Macro, and clicking my Contacts folder. Do I need to do anything else?

Robert July 07, 2004


I found another fix that worked perfectly:
http://support.microsoft.com/?kbid=242074
This is a utility to clear OL's nickname cache.

Robert July 07, 2004


Check out this great tutorial on using Microsoft Outlook for managing your ebay & amazon sales, or use it as an Outlook programming quickstart:

http://www.321books.co.uk/ebooks/outlook-vba-tutorial.htm



mal4mac September 17, 2004 (Article Rating: )


You must be a registered user or online subscriber to comment on this article. Please log on before posting a comment. Are you a new visitor? Register now




Top Viewed ArticlesView all articles
Command Prompt Tricks

One reader shares his tip for setting up the command prompt to reflect a remote path. ...

WinInfo Short Takes: Week of November 23, 2009

An often irreverent look at some of the week's other news, including some post-PDC some soul searching, a Google Chrome OS announcement and a Microsoft response, Windows 7 off to a supposedly strong start, the Jonas Brothers and Xbox 360, and so much more ...

2009 Windows IT Pro Editors' Best and Community Choice Awards

Picking a favorite product from an impressive crowd of competitive offerings is never an easy task, and such was the case with our Editors' Best and Community Choice awards this year. ...


Exchange Server and Outlook Whitepapers Email Controls and Regulatory Compliance

Take Control of Your Email: Understand the Business Reasons for Email Storage Management

Related Events Deep Dive into Windows Server 2008 R2 presented by John Savill

Bail Out Your Exchange Environment

Check out our list of Free Email Newsletters!

Exchange Server and Outlook eBooks Spam Fighting and Email Security for the 21st Century

Understanding and Leveraging Code Signing Technologies

The Expert's Guide for Exchange 2003: Preparing for, Moving to, and Supporting Exchange Server 2003

Related Exchange Server and Outlook Resources Introducing Left-Brain.com, the online IT bookstore
Looking for books, CDs, toolkits, eBooks? Prime your mind at Left-Brain.com

Discover Windows IT Pro eLearning Series!
Clear & detailed technical information and helpful how-to's, all in our trademark no-nonsense format

Exchange & Outlook UPDATE eNewsletter
News, strategies, products, and developments in Exchange Server and Outlook messaging.

Windows IT Pro Home Register FAQ for Windows WinInfo News
Europe Edition About Us Contact Us/Customer Service Media Kit Affiliates / Licensing  
SQL Server Magazine Office & SharePoint Pro DevProConnections IT Job Hound
Left-Brain.com Technology Resource Directory asp.netPRO ITTV Windows SuperSite 
 
 Windows IT Pro is a Division of Penton Media Inc.
 © 2009 Penton Media, Inc. Terms of Use | Privacy Statement