Dmitry Kostochko

HowTo: Search in Outlook items programmatically

You can search in Outlook folders and sub folders in 3 different ways: by using the Items.Restrict method, Items.Find in liaison with Items.FindNext and Application.AdvancedSearch. The first two have essential limitations in use – they work only for one Items collection of MAPIFolder, are executed synchronously, and not all fields of Outlook items by a long shot can be used for searching.

The AdvancedSearch method is the most powerful and convenient way of search, it can search in Outlook sub folders as well, and it is this method that we are going to dwell on today.

Well, here goes. The description of the AdvancedSearch method in VB.NET is as follows (C# sample is available for download at the end of the post):

Function AdvancedSearch(ByVal Scope As String,_
  Optional ByVal Filter As Object = Nothing,_
  Optional ByVal SearchSubFolders As Object = Nothing,_
  Optional ByVal Tag As Object = Nothing)_
  As Microsoft.Office.Interop.Outlook.Search

Parameters:

  • Scope. It is the range of search, usually a path to a folder.
  • Filter. This is the most complicated parameter. It determines what we are searching for. Its syntax should correspond to the syntax of SQL Server queries (among others, we can use such a nice operator as LIKE), which is very comfortable indeed. However, it not that easy to specify how column names should look like, but the following MSDN article will definitely be of much help.
  • SearchSubFolders. Determines whether to search in folder’s subfolders.
  • Tag. This is a search identifier. You will need it when handling the AdvancedSearchComplete event.

In our VB.NET example, we use an instance of an Advanced Outlook Form to give the end-user the ability to start search:

Private Sub Button1_Click(_
  ByVal sender As System.Object,_
  ByVal e As System.EventArgs) Handles Button1.Click
    Dim CurrentFolder As Outlook.MAPIFolder
    Dim CurrentOutlookApp As Outlook.Application
    Dim sFilter, sScope As String
 
    Me.ListView1.Items.Clear()
    If RadioButton1.Checked Then
        sFilter = "urn:schemas:httpmail:subject LIKE '%"_
            + TextBox1.Text.Trim + "%'"
    Else
        sFilter = "urn:schemas:httpmail:textdescription LIKE '%"_
            + TextBox1.Text.Trim + "%'"
    End If
    If Me.OutlookAppObj IsNot Nothing Then
        CurrentOutlookApp = TryCast(Me.OutlookAppObj, Outlook.Application)
        If Me.FolderObj IsNot Nothing Then
            Try
                CurrentFolder = TryCast(Me.FolderObj, Outlook.MAPIFolder)
                sScope = "'" + CurrentFolder.FolderPath._
                    Replace("'", "''") + "'"
                oSearch = CurrentOutlookApp.AdvancedSearch(_
                    sScope, sFilter, True, "Search1")
            Catch ex As Exception
                System.Windows.Forms.MessageBox.Show(ex.Message)
            End Try
        End If
    End If
End Sub

Handle the AdvancedSearchComplete event and fill in System.Windows.Forms.ListView with search results:

Public Sub adxOutlookEvents_AdvancedSearchComplete(_
  ByVal sender As System.Object,_
  ByVal hostObj As System.Object)_
   Handles adxOutlookEvents.AdvancedSearchComplete
    Dim myForm As ADXOlForm1 = Nothing
    Dim CurrentResults As Outlook.Results = Nothing
    Dim CurrentSearch As Outlook.Search = Nothing
    Dim lvListItem As System.Windows.Forms.ListViewItem
    Dim OldCursor As System.Windows.Forms.Cursor
    Dim objItem As Object
 
    myForm = AdxOlFormsManager1.Items(0)._
        GetCurrentForm(AddinExpress.OL.EmbeddedFormStates.Visible)
    If myForm IsNot Nothing Then
        OldCursor = myForm.Cursor
        Try
            myForm.Cursor = Windows.Forms.Cursors.WaitCursor
            CurrentSearch = CType(hostObj, Outlook.Search)
            If CurrentSearch IsNot Nothing Then
                If CurrentSearch.Tag = "Search1" Then
                    CurrentResults = CurrentSearch.Results
                    If CurrentResults.Count > 0 Then
                        myForm.ListView1.BeginUpdate()
                        For i As Integer = 1 To CurrentResults.Count
                            objItem = CurrentResults.Item(i)
                            lvListItem =_
                              New System.Windows.Forms.ListViewItem
                            With lvListItem
                                .Text = objItem.SenderName
                                .SubItems.Add(objItem.Subject)
                                .SubItems.Add(_
                                  objItem.ReceivedTime.ToString())
                                .SubItems.Add(objItem.EntryID)
                            End With
                            myForm.ListView1.Items.Add(lvListItem)
                        Next
                        myForm.ListView1.Items(0).Selected = True
                        myForm.ListView1.EndUpdate()
                    Else
                        System.Windows.Forms.MessageBox.Show(_
                          "0 items were found.")
                    End If
                End If
            End If
        Catch ex As Exception
            System.Windows.Forms.MessageBox.Show(ex.Message)
        Finally
            If CurrentResults IsNot Nothing Then
                Marshal.ReleaseComObject(CurrentResults)
            End If
            myForm.Cursor = OldCursor
        End Try
    End If
End Sub

The search process is VERY fast indeed. It normally takes just a few seconds from executing the AdvancedSearch method to raising the AdvancedSearchComplete event. Retrieving objects from the Results collection is much slower. But even here there is some room for improvement: you can use the SetColumns method of the Results collection to cache certain fields for fast access. That's all for today.

You may also be interested in:

Special features for Outlook plug-in development
How to write Outlook add-in: toolbars, buttons, ribbons, menus

Available downloads:

C# sample Outlook add-in for VS 2005  
VB.NET sample Outlook add-in for VS 2005

10 Comments

  • Oliver Giesen says:

    Can this AdvancedSearch also search recursively (i.e. with subfolders) inside Public Folders and folders inside shared mailboxes? Just asking because the Advanced Find dialog in Outlook could not…

  • Dmitry Kostochko (Add-in Express Team) says:

    It can search recursively in Exchange Mailboxes, but cannot in Public Folders. Also, searching across multiple Stores simultaneously is not possible.

  • Oliver Giesen says:

    That’s great to hear (about the secondary mailboxes)! We recently had a request where this would definitely come in handy. I’ll have a look at this next week.

  • Simon Miller says:

    Phew looks very complicated. How about a normal search tool which is able to search both your contacts and your addresses and is pretty fast, too? I use lookeen and am pretty happy with it.

  • Dmitry Kostochko (Add-in Express Team) says:

    Thank you for the idea. We will try to create a how-to sample of such kind.

  • Mike Baxter says:

    Thanks, very helpful article and exactly what I was looking for. I expected that it would have been easy to find info on searching outlook folder but all the others (many) that I looked at were demonstrating how to use the Find and Restrict methods on the Items collection. I tried both of the afore mentioned methods and found them to be very limited and pretty much useless.
    Thanks again.

  • Prathima says:

    I have a small question here. I have shared mailbox apart from the main mailbox and am not able to search on shared mailbox. I just need the mails under inbox folder of the share mailbox. I am able todo restrict but why cannot i do advancedsearch.The application is just freezing when i do advanced search for shared mailbox in winforms.

  • Dmitry Kostochko (Add-in Express Team) says:

    Hi Prathima,

    What value do you pass in the Scope parameter of the AdvancedSearch method?

  • Nishant says:

    Nice Article!

    The solution which i have downloaded from here is giving Add in Express error. Do you have any idea about this?

    Actually what i need to do is, i need to search mails which has “XYZ” word exists in subject line & then programatically add reminders to those mails. Let me know if you have any source code for the same.

    Thank you!

  • Dmitry Kostochko (Add-in Express Team) says:

    Hi Nishant,

    Thank you for your kind words!

    >> The solution which i have downloaded from here is giving Add in Express error. Do you have any idea about this?

    I have just re-tested the solution, it works for me without any errors. I may assume that you don’t have our Add-in Express for Office and .NET product installed and that is why the error occurs on your side.

    >> Actually what i need to do is, i need to search mails which has “XYZ” word exists in subject line & then programatically add reminders to those mails. Let me know if you have any source code for the same.

    Sorry, we don’t have a ready-made source code of such kind.

Post a comment

Have any questions? Ask us right now!