Export Your OPML from Outlook
Lately I have fallen in love with Office programming, but I’m still a complete n00b at it. I was pilfering through my RSS feeds the other day, and realized I didn’t have a way to export the feeds list as OPML. Hmm… good time to open Visual Studio and start tinkering. Here is what I came up with.
Create the Project
To get started, go to the C# node in the New Project window, and you’ll find a sub-node called Office, and another called 2007. Click on the 2007 node, and create a new Outlook 2007 Add-In project (remember that Outlook 2003 didn’t have RSS support out of the box).
That creates a project with a file called ThisAddIn.cs. Open that file, and you’ll see some code like this already stubbed out.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;
namespace OutlookAddIn2
{
public partial class ThisAddIn
{
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
#region VSTO generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
#endregion
}
}
Sweet, you’re halfway there! Next, we’ll add some using statements.
using System.Xml;
using System.Windows.Forms;
Add functions that will add a CommandBar and a CommandButton. I put them into separate functions here only for readability, you could have put all of this in one big honking method if you wanted to.
private void AddCommandBar()
{
//Add the command bar
bar = Globals.ThisAddIn.Application.ActiveExplorer().CommandBars.Add(
"RSS Feeds",
Office.MsoBarPosition.msoBarTop,
false,
true);
bar.Protection = Office.MsoBarProtection.msoBarNoCustomize;
bar.Visible = true;
}
private void AddCommandButton()
{
//Add a command button to the bar
button = bar.Controls.Add(
Office.MsoControlType.msoControlButton,
Type.Missing,
Type.Missing,
Type.Missing,
true) as Office.CommandBarButton;
button.Caption = "Export OPML";
button.Click += new Office._CommandBarButtonEvents_ClickEventHandler(button_Click);
}
When our newly created button is clicked, we want to pop open a Save File dialog. That’s really easy, we just use the good ol’ Windows Forms stuff to do that.
void button_Click(Office.CommandBarButton Ctrl, ref bool CancelDefault)
{
//Launch the Save File Dialog
System.Windows.Forms.SaveFileDialog saveDialog =
new System.Windows.Forms.SaveFileDialog();
saveDialog.Filter = "OPML files|*.opml";
saveDialog.Title = "Save OPML file";
saveDialog.ShowDialog();
if (saveDialog.FileName.Length > 0)
{
ExportOPML(saveDialog.FileName);
System.Windows.Forms.MessageBox.Show("Saved OPML to " + saveDialog.FileName);
}
}
Next is our function to actually export the OPML for our feeds.
private void ExportOPML(string fileName)
{
XmlWriter writer = XmlWriter.Create(fileName);
writer.WriteStartDocument();
writer.WriteStartElement("opml");
writer.WriteAttributeString("version", "1.0");
writer.WriteStartElement("head");
writer.WriteEndElement(); //head
writer.WriteStartElement("body");
ExportRSSFeedList(writer);
writer.WriteEndElement(); //body
writer.WriteEndElement(); //opml
writer.WriteEndDocument();
writer.Flush();
writer.Close();
}
Getting the RSS URL From Outlook
Now that we have the basic structure of our add-in, we need to dig into the RSS feeds themselves in Outlook. Thankfully, my friend Andrew Coates was kind enough to point me to the following post to show how to get to the RSS feeds.
private void ExportRSSFeedList(XmlWriter writer)
{
// Find the RSS feeds folder
Outlook.Application app = this.Application;
Outlook.MAPIFolder folder = app.GetNamespace("MAPI").GetDefaultFolder(
Outlook.OlDefaultFolders.olFolderRssFeeds);
EnumRssFeeds(folder, writer);
}
Finally, we add our custom EnumRssFeeds method.
private void EnumRssFeeds(Outlook.MAPIFolder parentFolder, XmlWriter writer)
{
if (parentFolder != null)
{
// Iterate through the sub-folders
foreach (Outlook.Folder childFolder in parentFolder.Folders)
{
Outlook.StorageItem item =
childFolder.GetStorage("IPM.Sharing.Binding.In",
Outlook.OlStorageIdentifierType.olIdentifyByMessageClass);
writer.WriteStartElement("outline");
writer.WriteAttributeString("text", childFolder.Name);
if (item != null && item.Subject != null)
{
writer.WriteAttributeString("xmlUrl", item.Subject);
}
EnumRssFeeds(childFolder, writer);
writer.WriteEndElement();
}
}
}
That’s it! If you hit F5 and run the project, Outlook will pop open, and your new menu bar and button will appear. Click on it, and you can export your RSS feeds in Outlook as OPML.
I am still trying to reverse the process, I want to figure out how to import OPML and create new RSS subscriptions. Yeah, I know that Outlook does this already, but it doesn’t honor the structure in the OPML file. Maybe I can get AC to use Outlook for RSS feeds again.
For More Information
https://social.msdn.microsoft.com/forums/en-US/vsto/thread/de270997-75cd-4dd2-9ff5-e8ca11940437/
Saving Files Using the SaveFileDialog Component
Microsoft Office Outlook Programming Using VSTO 3.0 and C#: Part 1 (shows how to add a toolbar and button)
Comments
Anonymous
April 06, 2009
Excellent post! I just installed a new feed reader and wanted to export my Outlook feeds. I did have to add a few things to the code that were missing; local variables for the bar and button and a call to add them in the startup. Other than that everything worked perfectly. Microsoft.Office.Core.CommandBar bar; Microsoft.Office.Core.CommandBarButton button; private void ThisAddIn_Startup(object sender, System.EventArgs e) { AddCommandBar(); AddCommandButton(); }Anonymous
April 06, 2009
Thanks, Paul... I forgot to add those parts back into the post. Glad it helped.Anonymous
April 18, 2009
There was a question on one of the internal lists today: "Looking for a no-brainer way to demo just