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
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?
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.
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
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.
When I try to lunch Outlook 2007, I get an error message “can not view Outlook, invalid XML”. Any ideas?
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?
I was wodering if anyone know how to get the count of filetring contacts items
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.
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
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.
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
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.
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.
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
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.
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
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.
Hi Dmitry
Thanks for your support, I will check with your code and get back to you.
Regards
Raghunathan S