Dmitry Kostochko

HowTo: Use the View.XML property to filter Outlook items

The View object itself is simple but it has one very powerful property. This property is called XML, and it contains an xml definition of a folder view. Today we are going to look at the capabilities of the <filter> element. Using this element you can set or remove a filter for folder items programmatically.

In this sample, we filter Outlook items by one of the two fields – Subject or Body. In real projects you can use other fields as well as other conditions.

Well, let's go. To set a filter you need to add the <filter> xml element (if it was not added before) to the <view> xml element and call the Apply method:

Private Sub btnSetFilter_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles btnSetFilter.Click
    Dim sFilter As String
    Dim CurrentExplorer As Outlook.Explorer = Nothing
    Dim CurrentView As Outlook.View = Nothing
    Dim CurrentXML As XmlDocument = New XmlDocument
    Dim CurrentFilterNodes, CurrentViewNodes As XmlNodeList
    Dim CurrentFilterNode, CurrentParentNode As XmlNode
 
    If TextBox1.Text.Length > 0 Then
        If rbtSubject.Checked Then
            sFilter = "urn:schemas:httpmail:subject LIKE '%" + _
            TextBox1.Text.Trim + "%'"
        Else
            sFilter = "urn:schemas:httpmail:textdescription LIKE '%" + _
            TextBox1.Text.Trim + "%'"
        End If
 
        CurrentExplorer = TryCast(ExplorerObj, Outlook.Explorer)
        If (CurrentExplorer IsNot Nothing) Then
            CurrentView = CurrentExplorer.CurrentView
            If (CurrentView IsNot Nothing) Then
                Try
                    CurrentXML.LoadXml(CurrentView.XML)
                    CurrentFilterNodes = _
                        CurrentXML.GetElementsByTagName("filter")
                    If CurrentFilterNodes.Count > 0 Then
                        For y As Integer = 0 _
                            To CurrentFilterNodes.Count - 1
                            CurrentFilterNode = CurrentFilterNodes(y)
                            If CurrentFilterNode.HasChildNodes Then
                                For i As Integer = _
                                CurrentFilterNode.ChildNodes.Count - 1 _
                                    To 0 Step -1
                                    CurrentFilterNode.RemoveChild( _
                                        CurrentFilterNode.ChildNodes(i))
                                Next
                            End If
                        Next
                        CurrentFilterNode = CurrentFilterNodes(0)
                        CurrentFilterNode.AppendChild( _
                            CurrentXML.CreateTextNode(sFilter))
                    Else
                        CurrentViewNodes = CurrentXML. _
                            GetElementsByTagName("view")
                        If CurrentViewNodes IsNot Nothing Then
                            CurrentParentNode = CurrentViewNodes(0)
                            CurrentFilterNode = CurrentXML. _
                                CreateElement("filter")
                            CurrentParentNode.AppendChild( _
                                CurrentFilterNode)
                            CurrentFilterNode.AppendChild( _
                                CurrentXML.CreateTextNode(sFilter))
                        End If
                    End If
                    CurrentView.XML = CurrentXML.InnerXml
                    CurrentView.Apply()
                Finally
                    Marshal.ReleaseComObject(CurrentView)
                End Try
            End If
        End If
    End If
End Sub

To remove a filter you just need to remove the <filter> element from the xml definition and call the Apply method of the View object:

Private Sub btnClearFilter_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles btnClearFilter.Click
    Dim CurrentExplorer As Outlook.Explorer = Nothing
    Dim CurrentView As Outlook.View = Nothing
    Dim CurrentXML As XmlDocument = New XmlDocument
    Dim CurrentFilterNodes As XmlNodeList
    Dim CurrentFilterNode As XmlNode
 
    CurrentExplorer = TryCast(ExplorerObj, Outlook.Explorer)
    If (CurrentExplorer IsNot Nothing) Then
        CurrentView = CurrentExplorer.CurrentView
        If CurrentView IsNot Nothing Then
            Try
                CurrentXML.LoadXml(CurrentView.XML)
                CurrentFilterNodes = CurrentXML. _
                    GetElementsByTagName("filter")
                If CurrentFilterNodes.Count > 0 Then
                    For y As Integer = CurrentFilterNodes.Count - 1 _
                        To 0 Step -1
                        CurrentFilterNode = CurrentFilterNodes(y)
                        If CurrentFilterNode.HasChildNodes Then
                            For i As Integer = _
                            CurrentFilterNode.ChildNodes.Count - 1 _
                              To 0 Step -1
                                CurrentFilterNode.RemoveChild( _
                                    CurrentFilterNode.ChildNodes(i))
                            Next
                        End If
                    Next
                End If
                CurrentView.XML = CurrentXML.InnerXml()
                CurrentView.Apply()
            Finally
                Marshal.ReleaseComObject(CurrentView)
            End Try
        End If
    End If
End Sub

That’s it! But that’s not the only element contained in the XML property. Good luck with the rest of them!

You may also be interested in:

Outlook customization: Reading pane, Outlook bar and To-Do bar
Creating Outlook add-in step-by-step

Available downloads:

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

18 Comments

  • anup says:

    On calling currentView.Apply(), my view is not getting applied, I tried saving the view, and got the following error on Imap mailbox, this works fine for exchange mailbox

    System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
    at Microsoft.Office.Interop.Outlook.View.Save()

    Any idea?

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

    After calling the Apply method you can try to programmatically switch to another folder (say Outbox) and then switch back to your IMap mailbox. I think this will help apply your changes.

  • Marc Francois says:

    I’m trying to get a list of the elements contained in this .xml property and was pointed to https://msdn.microsoft.com/en-us/library/bb207155.aspx by Eugene.. unfortunately this article doesn’t list all of the elements or their accepted values.

    I was wondering if anyone had a more comprehensive list? Googling doesn’t seem to reveal anything useful

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

    As far as I remember there is no documentation that contains the description of all the elements. I can suggest adding a field (or making other changes) manually and then analyzing the changes in the XML property.

  • Jim Swaney says:

    When I try to lunch Outlook 2007, I get an error message “can not view Outlook, invalid XML”. Any ideas?

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

    I have just retested the sample with Outlook 2007 SP2. I applied and removed several filters but did not see any error messages. Did you change the source code of the sample?

  • Mahmoud says:

    I was wodering if anyone know how to get the count of filetring contacts items

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

    You can try to use the Items.Restrict method. This method returns a filtered collection and in this way you will get the Count property.

  • Raghunathan S says:

    Hi,

    I am working on a Outlook 2010 Add-In using Visual Studio 2010 and .NET Framework 4.0 on a Windows 7 64bit Machine.

    Requirement:
    Programmatically filter the Mail Items in a Folder using the View.Filter property which were Received on a particular date

    I tried the following code (Please correct me if i’m wrong)

    Outlook.Application thisApp = this.Application;
    Outlook.Explorer thisExp = thisApp.ActiveExplorer();
    Outlook.MAPIFolder thisFolder = thisExp.CurrentFolder;
    string query = “\”urn:schemas:httpmail:datereceived\” = ’12/9/2009 2:08 PM'”;
    thisFolder.CurrentView.Filter = query;
    thisFolder.CurrentView.Save();
    thisFolder.CurrentView.Apply();

    But it is not returning any mail item, even though there are mails which were received on this [12/9/2008 2:08 PM] particular time.

    Please help me out with this. URGENT!!!!

    Thanks in Advance

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

    Hi Raghunathan,

    Thank you for the code sample, it was very helpful. I’d suggest using the following filter:
    “urn:schemas:httpmail:datereceived” >= ‘8/17/2013 12:00 AM’ AND
    “urn:schemas:httpmail:datereceived” < '8/18/2013 12:00 AM' Also, please have a look at this MSDN article, I think it can be useful: Filtering Items Using a Date-time Comparison.

  • Raghunathan S says:

    Hi Dmitry,

    Thanks for your prompt reply.

    By using the code snippet that you’ve mentioned above i am getting all the mails from 8/17/2013 12:00 AM to 8/18/2013 12:00 AM.

    What I need a View Filter for filtering a particular date time (exactly)

    Thanks

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

    Hi Raghunathan,

    In fact, Outlook explorer does not always display exactly the time when an email item actually arrived. Firstly, when using DASL queries (the Filter property implies using DASL) you need to specify date/time as Coordinated Universal Time (UTC) values. Secondly, you need to operate time ranges because it looks like Outlook stores seconds in its private data and by specifying the exact time in minutes you are likely to get an empty result.

    So, I would suggest using a filter like this:

    “urn:schemas:httpmail:datereceived” >= ‘8/19/2013 2:58 PM’ AND
    “urn:schemas:httpmail:datereceived” < '8/19/2013 2:59 PM' In this way you will get all emails arrived today between 2:58:00 PM – 2:58:59 PM.

  • Raghunathan S says:

    Hi Dmitry

    AWESOME!!! Thanks for the prompt reply.

    We tried the same and it worked fine in Outlook 2007, whereas in Outlook 2010 and 2013 >= condition failed. So we modified the condition like this

    “urn:schemas:httpmail:datereceived” > ’8/19/2013 2:58:13 PM’ AND
    “urn:schemas:httpmail:datereceived” < ’8/19/2013 2:58:15 PM’

    inorder to filter the mail received exactly on 8/19/2013 2:58:14 PM.

    The above filter condition works perfectly for 2007,2010,2013 versions of Office Outlook

    Thanks So Much for the reply. Will disturb you soon with another query.

  • Raghunathan says:

    Hi Dmitry,

    How to get the updated view xml every time when the user changes the view by
    Grouping, Sorting etc.

    Everytime when I try to access the ActiveExplorer().CurrentFolder.CurrentView.XML property it returns the XML which doesn’t reflect any UI changes (Grouping, Sorting.. ) done by the user.

    Steps:

    I have created a outlook add-in for Outlook 2007 from Visual Studio 2010 with .NET Framework 4.0.

    In the ThisAddIn_Startup Event i’m creating a new command bar with 2 buttons and click event for the buttons

    Button1 click event i’m applying a filter as how u have mentioned in this post, by modifying the ViewXML.

    Same way, in Button2 click i’m removing the applied filter.

    By default my view is grouped by message type. when I click button1 filter is getting applied and the grouping persists

    now, I’m removing the grouping of the view. and when I click Button1 filter is getting removed and view is getting refresh BUT GROUPING COMES BACK.

    Hope I’ve conveyed my issue clearly.
    Please help me out with this.

    Regards
    Raghunathan S

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

    Hi Raghunathan,

    I have just tested the issue you described and was not able reproduce it. The XML property of the View object returns the modified xml after each change.

  • Raghunathan says:

    Hi Dmitry,

    Can you show me the code sample of how you retrieved the view xml, on which event from which object etc.

    It would be of a great help if u can share the code.

    Thanks in Advance

    Regards
    Raghunathan s

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

    Hi Raghunathan,

    My test code is very simple, please see it below, it is invoked by clicking a ribbon button in Outlook explorer:

    Outlook._Explorer activeExplorer = OutlookApp.ActiveExplorer();
    if (activeExplorer != null)
    try
    {
    Outlook.MAPIFolder currentFolder = activeExplorer.CurrentFolder;
    if (currentFolder != null)
    try
    {
    Outlook.View currentView = currentFolder.CurrentView;
    if (currentView != null)
    try
    {
    System.IO.File.WriteAllText(“C:\\Temp\\CurrentView.xml”, currentView.XML);
    }
    finally { Marshal.ReleaseComObject(currentView); }
    }
    finally { Marshal.ReleaseComObject(currentFolder); }
    }
    finally { Marshal.ReleaseComObject(activeExplorer); }

    After I changed the view settings (grouping, sorting), I clicked the button and examined the content of the CurrentView.xml file. I noticed changes in the groupby -> order and orderby -> order xml nodes.

  • Raghunathan says:

    Hi Dmitry

    Thanks for your support, I will check with your code and get back to you.

    Regards
    Raghunathan S

Post a comment

Have any questions? Ask us right now!