Outlook Export Calendar to Word Add-in

I have been working with a number of customers over the years that come from the world of Lotus Notes. And one of the areas they often complain about with regards to Outlook is the calendar printing options. There are certain things you just cannot do in Outlook from the printing perspective that leaves them wont for more.

So, I have been working over the years on this add-in. This has actually gone through a few iterations – the current version 1.2.0.9 is the most recent and most fully-featured version.

The full source code is on GitHub, here. It is totally open source and free to use, modify, etc. Here is what it can do:

addin

  • Printing calendars not available in Outlook by default.
  • The ability to create your own custom calendar
  • The ability to combine calendars for multiple people at once:
    • Displaying only overlapping schedules on the same calendar
    • Displaying all meetings including overlapping meeting
  • The ability to export in daily, weekly, by-weekly, tri-weekly or monthly formats.

The exact details on customization, installation and usage are all covered in the user guide, here.

Getting Appointments on a specific date from Outlook

I was working on proof of concept Outlook add-in for a customer when I ran into  series of distressing exceptions trying to access specific recurring appointments from the calendar. There seems to be a great many ways to get a list of appointments for a specific date, but you may find the .Start date of these vary wildly. I went down a path using GetRecurrencePattern().GetOccurrence(DateTime.Now), and I got this exception a LOT:

“You changed one of the recurrences of this item, and this instance no longer exists. Close any open items and try again.”

After doing some more searching, I found that I was going about it all wrong. Now, I will be the first to say that I am not the strongest in the Outlook Object Model. Excel, Word and especially PowerPoint are by bread and butter. But sometimes, Outlook can be just downright confusing. Disappointed smile

In the end, this is what I came up with to get a list of all the appointments on a given date in a specific users calendar that you select from the Address list:

Outlook.Recipient LobjRecipient = null;
// crete a select names dialog
Outlook.SelectNamesDialog LobjSnd = MobjOutlook.Session.GetSelectNamesDialog();
// limit to the TO box
LobjSnd.NumberOfRecipientSelectors = Outlook.OlRecipientSelectors.olShowTo;
LobjSnd.AllowMultipleSelection = false; // there can be only one
LobjSnd.Display(); // display it
// do we have resolved names
if (!LobjSnd.Recipients.ResolveAll())
{
LobjRecipient = null; // NO
return; // exit out
}
else
{
LobjRecipient = LobjSnd.Recipients[1]; // yes
}
LobjSnd = null;
// open the shares Calendar folder
Outlook.MAPIFolder LobjFolder = MobjOutlook.ActiveExplorer().Session.GetSharedDefaultFolder(
LobjRecipient, Outlook.OlDefaultFolders.olFolderCalendar)
as Outlook.MAPIFolder;
// get all the items
Outlook.Items LobjItems = LobjFolder.Items;
LobjItems.Sort("[Start]"); // sort the items by start date
LobjItems.IncludeRecurrences = true; // be sure to include recurrences
string LstrDay = DateTime.Now.ToShortDateString(); // today
// set the find string to today 0:00 to 23:59:59
string LstrFind = "[Start] <= \"" + LstrDay + " 11:59 PM\"" +
" AND [End] > \"" + LstrDay + " 12:00 AM\"";
// find the first appointment for the day
Outlook.AppointmentItem LobjAppt = LobjItems.Find(LstrFind);
while (LobjAppt != null)
{
// ...do your thing here...

// get the next item
LobjAppt = LobjItems.FindNext();
}

Add-in to Check for Double Resource Booking

I was working with a customer today that had an issue where one some occasions they were double-booking, triple booking or even booking up to 30 conference rooms for the same meeting. They were looking for a way to prevent this from happening because once booked and auto-accepted by the room, they were unable to “cancel” without an administrator. So, I wrote them some code that essentially does a check to make sure if they have more than one resource/room scheduled for a meeting it will prompt them to ask them if they are sure they want to do this. The trick – in this sample – is to put all the resources you care about into a text file called “MeetingRooms.txt” in the installation folder. It will read it into memory and then check to make sure no more than one is scheduled or it will stop the user from making the mistake.

You will need to start off creating a Visual Studio 2010 / Outlook 2010 / .NET 4.0 Add-in…Here is the code:

public partial class ThisAddIn
{
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
// attach to the Item Send Event
Application.ItemSend += new Outlook.ApplicationEvents_11_ItemSendEventHandler(Application_ItemSend);
}

void Application_ItemSend(object Item, ref bool Cancel)
{
// try to cast to a Meeting Item
Outlook.MeetingItem meet = Item as Outlook.MeetingItem;
if (meet != null) // is it a meeting item - not null
{
// load the list of conference rooms from the install folder
List<string> rooms = new List<string>();
string path = System.Reflection.Assembly.GetExecutingAssembly().Location + "\\MeeingRooms.txt";
StreamReader sr = new StreamReader(path);
while (!sr.EndOfStream)
{
// save as lowercase -- we will compare this way
rooms.Add(sr.ReadLine().ToLower());
}

int cnt = 0;
// no loop through all the recipients
foreach (Outlook.Recipient r in meet.Recipients)
{
// if the recipient is in the List of rooms we count it
if (rooms.Contains(r.Name.ToLower()))
cnt++;

// now if we get more than one -- we have a problem
if (cnt > 1)
{
// notify the user they are about to send a meeting request
// that will book more than one room
DialogResult result = MessageBox.Show("You have more than one conference room on " +
"this meeting request. \n\n" +
"Are you sure you want to continue?", "Resource Conflict",
MessageBoxButtons.YesNoCancel, MessageBoxIcon.Hand);
// if the user hits cancel or no, we will
// cancel the send
if (result != DialogResult.Yes)
Cancel = true;
else
// otherwise, allow it
Cancel = false;

// exit for loop
break;
}
else
{
Cancel = false;
}
}
}
else
{
Cancel = false;
}
}

You need the following using statements:

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;
using System.Windows.Forms;
using System.IO;

Outlook Calendar Cleaner

I encountered an odd problem while working with a customer that was porting from Lotus Notes to Office 365 (Exchange) and ended up creating a new tool called the Outlook Calendar Cleaner.

The customer had a mixed environment of Mac and Windows and in certain conditions appointment items were disappearing on the Mac Office Outlook calendar, but still appearing in Outlook Web Access (OWA) and if the delegate was in Windows, they would still see the appointment on their view of the owners calendar.

The issue turns out to be that in the conversion a multi-line subject in an appointment item (supported in Lotus, but not in Exchange), has the new line character converted to a start of text (SOT) character or ASCII code 0x02. The problem is that this is an invalid character in XML and the Exchange Web Services implementation on Mac O/S X does not properly parse this character. This causes the process to hang and all appointments which were being imported on that thread are not copied over. Net effect – they appear to be missing in Mac Outlook.

So, I created a tool to correct the problem. The Outlook Calendar Cleaner is a very specific tool targeting this problem. You can to open the users Exchange Account (Office 365 account) in Outlook 2010 for Windows and run the tool in Windows and it will clean any appointments found to have this special character.

I have posted the Outlook Calendar Cleaner tool on Codeplex (along with the source code). Here:

https://outlookcalendarclean.codeplex.com/