I want to list(Extract) the Outlook Appointments by Date by using C#. I used restrict method to do that,
sSearch = "[Start] >= ' " + startDate + " ' and [Start] <= ' " + endDate + " '";
But, if the day after End Date(endDate) has a All Day appointment it is also listed. How to overcome from this problem ????
http://msdn.microsoft.com/en-us/library/office/gg619398(v=office.14).aspx
private void DemoAppointmentsInRange()
{
Outlook.Folder calFolder =
Application.Session.GetDefaultFolder(
Outlook.OlDefaultFolders.olFolderCalendar)
as Outlook.Folder;
DateTime start = DateTime.Now;
DateTime end = start.AddDays(5);
Outlook.Items rangeAppts = GetAppointmentsInRange(calFolder, start, end);
if (rangeAppts != null)
{
foreach (Outlook.AppointmentItem appt in rangeAppts)
{
Debug.WriteLine("Subject: " + appt.Subject
+ " Start: " + appt.Start.ToString("g"));
}
}
}
/// <summary>
/// Get recurring appointments in date range.
/// </summary>
/// <param name="folder"></param>
/// <param name="startTime"></param>
/// <param name="endTime"></param>
/// <returns>Outlook.Items</returns>
private Outlook.Items GetAppointmentsInRange(
Outlook.Folder folder, DateTime startTime, DateTime endTime)
{
string filter = "[Start] >= '"
+ startTime.ToString("g")
+ "' AND [End] <= '"
+ endTime.ToString("g") + "'";
Debug.WriteLine(filter);
try
{
Outlook.Items calItems = folder.Items;
calItems.IncludeRecurrences = true;
calItems.Sort("[Start]", Type.Missing);
Outlook.Items restrictItems = calItems.Restrict(filter);
if (restrictItems.Count > 0)
{
return restrictItems;
}
else
{
return null;
}
}
catch { return null; }
}
Similar to Tam Tam's. Just a little less code. I spent all day looking for a basic sample I could use in LinqPad. This is what I ended up with.
//using Microsoft.Office.Interop.Outlook
Application a = new Application();
Items i = a.Session.GetDefaultFolder(OlDefaultFolders.olFolderCalendar).Items;
i.IncludeRecurrences = true;
i.Sort("[Start]");
i = i.Restrict("[Start] >= '10/1/2013' AND [End] <= '10/2/2013'");
var r =
from ai in i.Cast<AppointmentItem>()
select new {ai.Start,ai.Duration,ai.Subject};
r.Dump();
Related
I'm still fairly new to the C# language and started learning more about methods this week. I am having an issue getting my error messages to display on my form. Any assistance to point me in the right direction and to understand what I am missing will be GREATLY appreciated. After several hours I managed to get public int calcAge(int aGE) to work, however, private void ErrorReturns(string errorStringReturn) has been causing me a royal headache.
private void executeButton_Click(object sender, EventArgs e)
{
string textBox = nameTextBox.Text;
DateTime today = DateTime.Now;
DateTime futurePicker = futureDateTimePicker.Value;
int AGE = 0;
string errorString = null;
int ageCalculation = calcAge(AGE);
ErrorReturns(errorString);
responseLabel.Text = "Hello " + textBox + "! You will be " + ageCalculation + " on " + futurePicker.ToShortDateString() + '\n' + "A date that is " + (futurePicker - today).Days + " days from now";
}
public int calcAge(int aGE)
{
DateTime birthdatePicker = birthDateTimePicker.Value;
DateTime futurePicker = futureDateTimePicker.Value;
aGE = futurePicker.Year - birthdatePicker.Year;
if (futurePicker < birthdatePicker.AddYears(aGE))
{
aGE--; // Decrement years if the Day has not passed yet.
}
return aGE;
}
private void ErrorReturns(string errorStringReturn)
{
DateTime today = DateTime.Now;
DateTime birthdatePicker = birthDateTimePicker.Value;
DateTime futurePicker = futureDateTimePicker.Value;
if (futurePicker < today)
{
responseLabel.Text = "ERROR -- DATE MUST BE IN THE FUTURE -- Please select a date in the future.";
}
else if (birthdatePicker > today)
{
responseLabel.Text = "ERROR -- DATE MUST BE IN THE PAST -- Please select a date in the past.";
}
}
What does errorString ? It is not used in the code provided...
Else the problem is that you always set the label text with:
responseLabel.Text = "Hello " + textBox + "! You will be " + ageCalculation + " on " + futurePicker.ToShortDateString() + '\n' + "A date that is " + (futurePicker - today).Days + " days from now";
Even if you set it before using the ErrorReturns method.
You can do that:
private bool CheckDate()
{
DateTime today = DateTime.Now;
DateTime birthdatePicker = birthDateTimePicker.Value;
DateTime futurePicker = futureDateTimePicker.Value;
if ( futurePicker < today )
{
responseLabel.Text = "ERROR -- DATE MUST BE IN THE FUTURE -- Please select a date in the future.";
return false;
}
else
if ( birthdatePicker > today )
{
responseLabel.Text = "ERROR -- DATE MUST BE IN THE PAST -- Please select a date in the past.";
return false;
}
else
return true;
}
And now you can write:
private void executeButton_Click(object sender, EventArgs e)
{
string textBox = nameTextBox.Text;
DateTime today = DateTime.Now;
DateTime futurePicker = futureDateTimePicker.Value;
int AGE = 0;
string errorString = null;
int ageCalculation = calcAge(AGE);
if ( CheckDate() )
responseLabel.Text = "Hello " + textBox + "! You will be " + ageCalculation + " on " + futurePicker.ToShortDateString() + '\n' + "A date that is " + ( futurePicker - today ).Days + " days from now";
}
I have not checked the logic of what you do, here it only solve the display.
To have a better UX you should not use the same label, but another thing, another label/image in red, or a message box, for example, so the user is better advised of what's happend.
On top of what other colleagues already mentioned regarding passing the "errorStringReturn" as null (which does not make any sense), are you sure that any of the conditionals above are reached?
Please, make a test and change the following to "futurePicker", just to see if you are able to return the error to the responseLabel.
else if (futurePicker > today)
{
responseLabel.Text = "ERROR -- DATE MUST BE IN THE PAST -- Please select a date in the past.";
}
Another question, does the responseLabel shows the message "Hello.." in the beginning?
My problem is, I can't access and so iterate Outlook's shared calendars. I've tried several ways but they all take me back to the default calendar (i.e. my account calendar).
I tried to loop in the subfolders, the GetSharedDefaultFolder() method and using different types of objects of the Interop library but I couldn't solve it.
Here are the methods I've tried. To run the program (in particular GetMethod3() and GetMethod5()) you have to set the string "email" with your own email.
using System;
using System.Text;
using Microsoft.Office.Interop.Outlook;
namespace OutlookTest {
class Program {
static void Main(string[] args) {
OutlookSharedCalendar outlookSharedCalendar = new OutlookSharedCalendar();
}
}
public class OutlookSharedCalendar{
Microsoft.Office.Interop.Outlook.Application oApp;
NameSpace oNameSpace = null;
MAPIFolder oMAPIFolder = null;
MAPIFolder objFolder = null;
MAPIFolder objSubFolder = null;
Explorer objExplorer;
AppointmentItem objCalenderItem;
Folders objOutlookFolders;
AddressEntry addrEntry = null;
Items oCalendarItems = null;
string email = "myemail#email.com";
public OutlookSharedCalendar() {
AppStart();
GetMethod1();
AppEnd();
AppStart();
GetMethod2();
AppEnd();
AppStart();
GetMethod3();
AppEnd();
AppStart();
GetMethod4();
AppEnd();
AppStart();
GetMethod5();
AppEnd();
}
public void GetMethod1() {
oMAPIFolder = oApp.Session.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
oCalendarItems = (Items)oMAPIFolder.Items;
oCalendarItems.IncludeRecurrences = true;
foreach(AppointmentItem item in oCalendarItems) {
if(item.IsRecurring) {
RecurrencePattern oRP = item.GetRecurrencePattern();
DateTime first = new DateTime(2018, 01, 01, item.Start.Hour, item.Start.Minute, 0);
DateTime last = new DateTime(2019, 10, 31);
AppointmentItem recur = null;
for(DateTime cur = first; cur <= last; cur = cur.AddDays(1)) {
recur = oRP.GetOccurrence(cur);
Console.WriteLine(recur.Subject + " - " + cur.ToLongDateString() + " - " + recur.Body);
}
}
else {
Console.WriteLine(item.Subject + " -> " + item.Start.ToLongDateString());
}
}
}
public void GetMethod2() {
int intFolderCtr;
int intSubFolderCtr;
int intAppointmentCtr;
// >> Initialize The Base Objects
objOutlookFolders = oApp.Session.Folders;
// >> Loop Through The PST Files Added n Outlook
for(intFolderCtr = 1; intFolderCtr <= objOutlookFolders.Count; intFolderCtr++) {
objFolder = objOutlookFolders[intFolderCtr];
objExplorer = objFolder.GetExplorer();
// >> Loop Through The Folders In The PST File
for(intSubFolderCtr = 1; intSubFolderCtr <= objExplorer.CurrentFolder.Folders.Count; intSubFolderCtr++) {
objSubFolder = objExplorer.CurrentFolder.Folders[intSubFolderCtr];
// >> Check if Folder Contains Appointment Items
if(objSubFolder.DefaultItemType == OlItemType.olAppointmentItem) {
// >> Loop Through Appointment Items
for(intAppointmentCtr = 1; intAppointmentCtr <= objSubFolder.Items.Count; intAppointmentCtr++) {
// >> Get Teh Calender Item From The Calender Folder
objCalenderItem = objSubFolder.Items[intAppointmentCtr];
// >> Process Appointment Item Accordingly
Console.WriteLine(objCalenderItem.Subject + " - " + objCalenderItem.Start + " - " + objCalenderItem.Body + " - " + objCalenderItem.Location);
}
}
}
}
}
public void GetMethod3() {
DateTime dtFrom = new DateTime(DateTime.Now.Year, 01, 01);
DateTime dtTo = new DateTime(DateTime.Now.Year, 12, 31);
Recipient teamMember = oApp.Session.CreateRecipient(email);
MAPIFolder sharedCalendar = oApp.Session.GetSharedDefaultFolder(teamMember, OlDefaultFolders.olFolderCalendar);
if(sharedCalendar.DefaultMessageClass != "IPM.Appointment" || teamMember.DisplayType != 0) {
return; //Calendar not shared.
}
string restrictCriteria = "[Start]<=\"" + dtTo.ToString("g") + "\"" + " AND [End]>=\"" + dtFrom.ToString("g") + "\"";
Items results = sharedCalendar.Items.Restrict(restrictCriteria);
foreach(AppointmentItem item in results) {
Console.WriteLine(item.Subject + " - " + item.Start + " - " + item.Body + " - " + item.Location);
}
}
public void GetMethod4() {
oMAPIFolder = oApp.Session.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
DateTime dtEnd = new DateTime(DateTime.Now.Year, 12, 31);
DateTime dtStart = new DateTime(DateTime.Now.Year, 01, 01);
string restrictCriteria = "[Start]<=\"" + dtEnd.ToString("g") + "\"" +
" AND [End]>=\"" + dtStart.ToString("g") + "\"";
StringBuilder strBuilder = null;
Items folderItems = null;
Items resultItems = null;
AppointmentItem appItem = null;
int counter = default(int);
object item = null;
strBuilder = new StringBuilder();
folderItems = (Items)oMAPIFolder.Items;
folderItems.IncludeRecurrences = true;
folderItems.Sort("[Start]");
resultItems = folderItems.Restrict(restrictCriteria);
item = resultItems.GetFirst();
do {
if(item != null) {
if(item is AppointmentItem) {
counter++;
appItem = item as AppointmentItem;
Console.WriteLine(appItem.Subject + " -> " + appItem.Start.ToLongDateString());
strBuilder.AppendLine("#" + counter.ToString() +
"\tStart: " + appItem.Start.ToString() +
"\tSubject: " + appItem.Subject +
"\tLocation: " + appItem.Location);
}
item = resultItems.GetNext();
}
}
while(item != null);
}
public void GetMethod5() {
addrEntry = oApp.Session.CurrentUser.AddressEntry;
if(addrEntry.Type == "EX") {
Recipient recip = oApp.Session.CreateRecipient(email);
if(recip.Resolve()) {
Folder folder = oApp.Session.GetSharedDefaultFolder(recip, OlDefaultFolders.olFolderCalendar) as Folder;
foreach(AppointmentItem item in folder.Items) {
Console.WriteLine(item.Subject + " - " + item.Start + " - " + item.Body + " - " + item.Location);
}
}
}
}
public void AppStart() {
// >> Start Outlook
oApp = new Microsoft.Office.Interop.Outlook.Application();
}
public void AppEnd() {
// >> Close Application
oApp.Quit();
// >> Release COM Object
System.Runtime.InteropServices.Marshal.ReleaseComObject(oApp);
oApp = null;
}
}
}
I hope I can get advice on the code or if someone knows a viable alternative to Interop. Thank you all in advance.
The NameSpace.GetSharedDefaultFolder method is used to get a Folder object that represents the specified default folder for the specified user. For example, with minor changes:
public void GetMethod3() {
DateTime dtFrom = new DateTime(DateTime.Now.Year, 01, 01);
DateTime dtTo = new DateTime(DateTime.Now.Year, 12, 31);
Recipient teamMember = oApp.Session.CreateRecipient(email);
teamMember.Resolve();
if(teamMember.Resolved)
{
MAPIFolder sharedCalendar = oApp.Session.GetSharedDefaultFolder(teamMember, OlDefaultFolders.olFolderCalendar);
if(sharedCalendar.DefaultMessageClass != "IPM.Appointment" || teamMember.DisplayType != 0) {
return; //Calendar not shared.
}
string restrictCriteria = "[Start]<=\"" + dtTo.ToString("g") + "\"" + " AND [End]>=\"" + dtFrom.ToString("g") + "\"";
Items results = sharedCalendar.Items.Restrict(restrictCriteria);
foreach(AppointmentItem item in results) {
Console.WriteLine(item.Subject + " - " + item.Start + " - " + item.Body + " - " + item.Location);
}
}
}
As you may see the recipient should be resolved against your address book before trying to access a shared calendar. The Recipient.Resolve method attempts to resolve a Recipient object against the Address Book.
Following is a code that a did in comparison between dates. Is it possible to use that code for strings also. OR Is there any sol?
protected void Button1_Click(object sender, EventArgs e)
{
int uid = Convert.ToInt32(dlFaculty.SelectedValue);
string starttime = Convert.ToString((Convert.ToInt32(dlHour.SelectedItem.Text)) + ":" + (Convert.ToInt32(dlMinute.SelectedItem.Text)) + " " + dlAMPM.SelectedItem.Text);
string endtime = Convert.ToString((Convert.ToInt32(dlHour1.SelectedItem.Text)) + ":" + (Convert.ToInt32(dlMinute1.SelectedItem.Text)) + " " + dlAMPM1.SelectedItem.Text);
DateTime startdate = Convert.ToDateTime(txtStartDate.Text);
DateTime enddate = Convert.ToDateTime(txtEndDate.Text);
DataTable oTable = new DataTable();
Boolean flag = true;
string SQL = "select startdate,enddate from BatchMaster where usermasterid=" + uid + " AND starttime='" + starttime + "' AND endtime='" + endtime + "'";
oTable = DbHelper.ExecuteTable(DbHelper.CONSTRING, CommandType.Text, SQL, null);
//coursemasterid = 0;
//string s = subjectsid;
if (oTable.Rows.Count > 0)
{
DataRow dr = oTable.Rows[0];
if ((Convert.ToDateTime(dr["startdate"]) <= startdate && Convert.ToDateTime(dr["enddate"]) >= startdate) || (Convert.ToDateTime(dr["startdate"]) <= enddate && Convert.ToDateTime(dr["enddate"]) >= enddate))
{
//lblavailability.Visible = true;
flag = false;
// lblavailability.Text = "Not Available.";
}
lblavailability.Visible = true;
if (flag == true)
{
lblavailability.CssClass = "textgreen";
lblavailability.Text = "Available.";
}
else
{
lblavailability.CssClass = "errorbold";
lblavailability.Text = "Not Available.";
}
}
else
{
lblavailability.CssClass = "textgreen";
lblavailability.Visible = true;
lblavailability.Text = "Available.";
}
}
You're essentially talking about the behaviour of
Convert.ToDateTime("23:00:10")
As per MSDN "It completes missing month, day, and year information with the current date.", so if you make sure that your time is always in HH and not hh format (that it uses 24h convention), you should be able to use a similar approach to the one above.
That is if you're sure that your code will not span midnight... :)
I need the current appointment. If no current appointment then the next or even previous appointment.
I figure to use Restrict to limit the set of appointments, and then choose either the first or last appointment depending on the restrict argument (e.g. Restrict to appointments ending after current time, or appointments starting before current time).
I'm having trouble with the string filter needed as argument.
A simple VB example (code stump):
myStart = Format(Date, "mm/dd/yyyy hh:mm AMPM")
strRestriction = "[Start] <= '" & myStart & "'"
'Restrict the Items collection
Set oResItems = oItems.Restrict(strRestriction)
'Sort
oResItems.Sort "[Start]"
I am attempting to do the same in C#.
// Create the Outlook application.
Outlook.Application oApp = new Outlook.Application();
// Get the NameSpace and Logon information.
// Outlook.NameSpace oNS = (Outlook.NameSpace)oApp.GetNamespace("mapi");
Outlook.NameSpace oNS = oApp.GetNamespace("mapi");
//Log on by using a dialog box to choose the profile.
oNS.Logon(Missing.Value, Missing.Value, true, true);
// Get the Calendar folder.
Outlook.MAPIFolder oCalendar = oNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
// Get the Items (Appointments) collection from the Calendar folder.
oItems = oCalendar.Items;
oItems.IncludeRecurrences = true;
// THIS IS THE PROBLEM AREA
String filter = "[Start] <= '" + DateTime.Now.ToString("MM/dd/yyyy hh:mm AMPM") + "'";
Outlook.Items restrictedItems = oItems.Restrict(filter);
// Take the last item on the list - should be current or next appointment
restrictedItems.Sort("[Start]");
Outlook.AppointmentItem oAppt = restrictedItems.GetLast();
// Done. Log off.
oNS.Logoff();
I imagine since the filter is a string, the date format needs to be yyyy/mm/dd HH:mm:ss? I can't find any documentation on how to manipulate the [Start], like parsing it to a date or something.
Depending on the date format, I will either get the wrong appointment, or will be unable to use GetLast due to the filter excluding all appointments.
I've seen examples, but either they loop through the appointments (too inefficient), or the date formats look like they can't be trusted to return the correct appointment (For example https://social.msdn.microsoft.com/Forums/vstudio/en-US/c6a8bd21-6534-43be-b23e-1068651da92e/retrieve-appointment-items-from-outlook-2007-calendar-restrict?forum=vsto, which seems to have the date hardcoded instead if using DateTime.Now.)
UPDATE: I'm currently looping through like shown below. Any suggestions for more efficient code?
DateTime currentTime = DateTime.Now;
foreach (Outlook.AppointmentItem item in oItems)
{
if (item.Start <= currentTime && item.End.Subtract(new TimeSpan(0, 10, 0)) > currentTime)
{
appointmentArrayList.Add(item);
}
}
This is your issue:
DateTime.Now.ToString("MM/dd/yyyy hh:mm AMPM")
What I think you're going for is:
DateTime.Now.ToString("MM/dd/yyyy hh:mm tt", CultureInfo.InvariantCulture)
By following the information found here, I was able to get it to work using "yyyy-MM-dd HH:mm" as the format string for the toString call.
Hope this helps.
This code works to show Outlook appointments from today onwards:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
DemoAppointmentsInRange();
}
private void DemoAppointmentsInRange()
{
Application a = new Application();
Microsoft.Office.Interop.Outlook.Folder calFolder = a.Session.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderCalendar) as Microsoft.Office.Interop.Outlook.Folder;
DateTime start = DateTime.Now;
DateTime end = start.AddDays(5);
Microsoft.Office.Interop.Outlook.Items rangeAppts = GetAppointmentsInRange(calFolder, start, end);
if (rangeAppts != null)
{
foreach (Microsoft.Office.Interop.Outlook.AppointmentItem appt in rangeAppts)
{
Response.Write("Subject: " + appt.Subject + " "+" Start: "+appt.Start.ToString()+" "+"End:"+appt.End.ToString()+"<br/>");
}
}
}
private Microsoft.Office.Interop.Outlook.Items GetAppointmentsInRange(
Microsoft.Office.Interop.Outlook.Folder folder, DateTime startTime, DateTime endTime)
{
string filter = "[Start] >= '"+ startTime.ToString("g")+ "' AND [End] <= '" + endTime.ToString("g") + "'";
//Response.Write(filter);
try
{
Microsoft.Office.Interop.Outlook.Items calItems = folder.Items;
calItems.IncludeRecurrences = true;
calItems.Sort("[Start]", Type.Missing);
Microsoft.Office.Interop.Outlook.Items restrictItems = calItems.Restrict(filter);
if (restrictItems.Count > 0)
{
return restrictItems;
}
else
{
return null;
}
}
catch
{
return null;
}
}
}
I couldn't figure out DateTime format, but I found this article:
https://learn.microsoft.com/en-us/office/vba/outlook/how-to/search-and-filter/filtering
Then I realized that they have a concept called "DASL Queries", reading furthermore I found this related to filtering with DateTime:
https://learn.microsoft.com/en-us/office/vba/outlook/how-to/search-and-filter/filtering-items-using-a-date-time-comparison
And I've decided to get all today's AppointmentItem(s) this way:
public enum MacroName
{
today,
tomorrow,
yesterday,
next7days,
last7days,
nextweek,
thisweek,
lastweek,
nextmonth,
thismonth,
lastmonth
}
private Outlook.Items GetAppointmentsWithMacro(Outlook.Folder folder, MacroName macro)
{
string strFilter = "#SQL=%" + macro.ToString() + "(\"urn:schemas:calendar:dtstart\")%";
try
{
Outlook.Items calItems = folder.Items;
calItems.IncludeRecurrences = true;
calItems.Sort("[Start]", Type.Missing);
Outlook.Items restrictItems = calItems.Restrict(strFilter);
if (restrictItems.Count > 0)
{
return restrictItems;
}
else
{
return null;
}
}
catch { return null; }
}
I want to be safest as possible because it seems that filtering by DateTime is related to local DateTime settings. By using the "today" macro I was able for the first time to extract the correct information from Outlook appointments store
How can I get all items from a specific calendar (for a specific date).
Lets say for instance that I have a calendar with a recurring item every Monday evening. When I request all items like this:
CalendarItems = CalendarFolder.Items;
CalendarItems.IncludeRecurrences = true;
I only get 1 item...
Is there an easy way to get all items (main item + derived items) from a calendar?
In my specific situation it can be possible to set a date limit but it would be cool just to get all items (my recurring items are time limited themselves).
I'm using the Microsoft Outlook 12 Object library (Microsoft.Office.Interop.Outlook).
I've studied the docs and this is my result:
I've put a time limit of one month hard-coded, but this is just an example.
public void GetAllCalendarItems()
{
Microsoft.Office.Interop.Outlook.Application oApp = null;
Microsoft.Office.Interop.Outlook.NameSpace mapiNamespace = null;
Microsoft.Office.Interop.Outlook.MAPIFolder CalendarFolder = null;
Microsoft.Office.Interop.Outlook.Items outlookCalendarItems = null;
oApp = new Microsoft.Office.Interop.Outlook.Application();
mapiNamespace = oApp.GetNamespace("MAPI"); ;
CalendarFolder = mapiNamespace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderCalendar);
outlookCalendarItems = CalendarFolder.Items;
outlookCalendarItems.IncludeRecurrences = true;
foreach (Microsoft.Office.Interop.Outlook.AppointmentItem item in outlookCalendarItems)
{
if (item.IsRecurring)
{
Microsoft.Office.Interop.Outlook.RecurrencePattern rp = item.GetRecurrencePattern();
DateTime first = new DateTime(2008, 8, 31, item.Start.Hour, item.Start.Minute, 0);
DateTime last = new DateTime(2008, 10, 1);
Microsoft.Office.Interop.Outlook.AppointmentItem recur = null;
for (DateTime cur = first; cur <= last; cur = cur.AddDays(1))
{
try
{
recur = rp.GetOccurrence(cur);
MessageBox.Show(recur.Subject + " -> " + cur.ToLongDateString());
}
catch
{ }
}
}
else
{
MessageBox.Show(item.Subject + " -> " + item.Start.ToLongDateString());
}
}
}
I believe that you must Restrict or Find in order to get recurring appointments, otherwise Outlook won't expand them. Also, you must Sort by Start before setting IncludeRecurrences.
I wrote similar code, but then found the export functionality:
Application outlook;
NameSpace OutlookNS;
outlook = new ApplicationClass();
OutlookNS = outlook.GetNamespace("MAPI");
MAPIFolder f = OutlookNS.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
CalendarSharing cs = f.GetCalendarExporter();
cs.CalendarDetail = OlCalendarDetail.olFullDetails;
cs.StartDate = new DateTime(2011, 11, 1);
cs.EndDate = new DateTime(2011, 12, 31);
cs.SaveAsICal("c:\\temp\\cal.ics");
LinqPad snipped that works for me:
//using Microsoft.Office.Interop.Outlook
Application a = new Application();
Items i = a.Session.GetDefaultFolder(OlDefaultFolders.olFolderCalendar).Items;
i.IncludeRecurrences = true;
i.Sort("[Start]");
i = i.Restrict(
"[Start] >= '10/1/2013 12:00 AM' AND [End] < '10/3/2013 12:00 AM'");
var r =
from ai in i.Cast<AppointmentItem>()
select new {
ai.Categories,
ai.Start,
ai.Duration
};
r.Dump();
If you need want to access the shared folder from your friend, then you can set your friend as the recipient. Requirement: his calendar must be shared first.
// Set recepient
Outlook.Recipient oRecip = (Outlook.Recipient)oNS.CreateRecipient("abc#yourmail.com");
// Get calendar folder
Outlook.MAPIFolder oCalendar = oNS.GetSharedDefaultFolder(oRecip, Outlook.OlDefaultFolders.olFolderCalendar);
There is no need to expand recurring items manually. Just ensure you sort the items before using IncludeRecurrences.
Here is VBA example:
tdystart = VBA.Format(#8/1/2012#, "Short Date")
tdyend = VBA.Format(#8/31/2012#, "Short Date")
Dim folder As MAPIFolder
Set appointments = folder.Items
appointments.Sort "[Start]" ' <-- !!! Sort is a MUST
appointments.IncludeRecurrences = True ' <-- This will expand reccurent items
Set app = appointments.Find("[Start] >= """ & tdystart & """ and [Start] <= """ & tdyend & """")
While TypeName(app) <> "Nothing"
MsgBox app.Start & " " & app.Subject
Set app = appointments.FindNext
Wend
public void GetAllCalendarItems()
{
DataTable sample = new DataTable(); //Sample Data
sample.Columns.Add("Subject", typeof(string));
sample.Columns.Add("Location", typeof(string));
sample.Columns.Add("StartTime", typeof(DateTime));
sample.Columns.Add("EndTime", typeof(DateTime));
sample.Columns.Add("StartDate", typeof(DateTime));
sample.Columns.Add("EndDate", typeof(DateTime));
sample.Columns.Add("AllDayEvent", typeof(bool));
sample.Columns.Add("Body", typeof(string));
listViewContacts.Items.Clear();
oApp = new Outlook.Application();
oNS = oApp.GetNamespace("MAPI");
oCalenderFolder = oNS.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderCalendar);
outlookCalendarItems = oCalenderFolder.Items;
outlookCalendarItems.IncludeRecurrences = true;
// DataTable sample = new DataTable();
foreach (Microsoft.Office.Interop.Outlook.AppointmentItem item in outlookCalendarItems)
{
DataRow row = sample.NewRow();
row["Subject"] = item.Subject;
row["Location"] = item.Location;
row["StartTime"] = item.Start.TimeOfDay.ToString();
row["EndTime"] = item.End.TimeOfDay.ToString();
row["StartDate"] = item.Start.Date;
row["EndDate"] = item.End.Date;
row["AllDayEvent"] = item.AllDayEvent;
row["Body"] = item.Body;
sample.Rows.Add(row);
}
sample.AcceptChanges();
foreach (DataRow dr in sample.Rows)
{
ListViewItem lvi = new ListViewItem(dr["Subject"].ToString());
lvi.SubItems.Add(dr["Location"].ToString());
lvi.SubItems.Add(dr["StartTime"].ToString());
lvi.SubItems.Add(dr["EndTime"].ToString());
lvi.SubItems.Add(dr["StartDate"].ToString());
lvi.SubItems.Add(dr["EndDate"].ToString());
lvi.SubItems.Add(dr["AllDayEvent"].ToString());
lvi.SubItems.Add(dr["Body"].ToString());
this.listViewContacts.Items.Add(lvi);
}
oApp = null;
oNS = null;
}
I found this article very useful: https://learn.microsoft.com/en-us/office/client-developer/outlook/pia/how-to-search-and-obtain-appointments-in-a-time-range
It demonstrates how to get calendar entries in a specified time range. It worked for me. Here is the source code from the article for your convenience :)
using Outlook = Microsoft.Office.Interop.Outlook;
private void DemoAppointmentsInRange()
{
Outlook.Folder calFolder = Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar)
as Outlook.Folder;
DateTime start = DateTime.Now;
DateTime end = start.AddDays(5);
Outlook.Items rangeAppts = GetAppointmentsInRange(calFolder, start, end);
if (rangeAppts != null)
{
foreach (Outlook.AppointmentItem appt in rangeAppts)
{
Debug.WriteLine("Subject: " + appt.Subject
+ " Start: " + appt.Start.ToString("g"));
}
}
}
/// <summary>
/// Get recurring appointments in date range.
/// </summary>
/// <param name="folder"></param>
/// <param name="startTime"></param>
/// <param name="endTime"></param>
/// <returns>Outlook.Items</returns>
private Outlook.Items GetAppointmentsInRange(
Outlook.Folder folder, DateTime startTime, DateTime endTime)
{
string filter = "[Start] >= '"
+ startTime.ToString("g")
+ "' AND [End] <= '"
+ endTime.ToString("g") + "'";
Debug.WriteLine(filter);
try
{
Outlook.Items calItems = folder.Items;
calItems.IncludeRecurrences = true;
calItems.Sort("[Start]", Type.Missing);
Outlook.Items restrictItems = calItems.Restrict(filter);
if (restrictItems.Count > 0)
{
return restrictItems;
}
else
{
return null;
}
}
catch { return null; }
}
Try this:
public List<AdxCalendarItem> GetAllCalendarItems()
{
Outlook.Application OutlookApp = new Outlook.Application();
List<AdxCalendarItem> result = new List<AdxCalendarItem>();
Outlook._NameSpace session = OutlookApp.Session;
if (session != null)
try
{
object stores = session.GetType().InvokeMember("Stores", BindingFlags.GetProperty, null, session, null);
if (stores != null)
try
{
int count = (int)stores.GetType().InvokeMember("Count", BindingFlags.GetProperty, null, stores, null);
for (int i = 1; i <= count; i++)
{
object store = stores.GetType().InvokeMember("Item", BindingFlags.GetProperty, null, stores, new object[] { i });
if (store != null)
try
{
Outlook.MAPIFolder calendar = null;
try
{
calendar = (Outlook.MAPIFolder)store.GetType().InvokeMember("GetDefaultFolder", BindingFlags.GetProperty, null, store, new object[] { Outlook.OlDefaultFolders.olFolderCalendar });
}
catch
{
continue;
}
if (calendar != null)
try
{
Outlook.Folders folders = calendar.Folders;
try
{
Outlook.MAPIFolder subfolder = null;
for (int j = 1; j < folders.Count + 1; j++)
{
subfolder = folders[j];
try
{
// add subfolder items
result.AddRange(GetAppointmentItems(subfolder));
}
finally
{ if (subfolder != null) Marshal.ReleaseComObject(subfolder); }
}
}
finally
{ if (folders != null) Marshal.ReleaseComObject(folders); }
// add root items
result.AddRange(GetAppointmentItems(calendar));
}
finally { Marshal.ReleaseComObject(calendar); }
}
finally { Marshal.ReleaseComObject(store); }
}
}
finally { Marshal.ReleaseComObject(stores); }
}
finally { Marshal.ReleaseComObject(session); }
return result;
}
List<AdxCalendarItem> GetAppointmentItems(Outlook.MAPIFolder calendarFolder)
{
List<AdxCalendarItem> result = new List<AdxCalendarItem>();
Outlook.Items calendarItems = calendarFolder.Items;
try
{
calendarItems.IncludeRecurrences = true;
Outlook.AppointmentItem appointment = null;
for (int j = 1; j < calendarItems.Count + 1; j++)
{
appointment = calendarItems[j] as Outlook.AppointmentItem;
try
{
AdxCalendarItem item = new AdxCalendarItem(
calendarFolder.Name,
appointment.Subject,
appointment.Location,
appointment.Start,
appointment.End,
appointment.Start.Date,
appointment.End.Date,
appointment.AllDayEvent,
appointment.Body);
result.Add(item);
}
finally
{
{ Marshal.ReleaseComObject(appointment); }
}
}
}
finally { Marshal.ReleaseComObject(calendarItems); }
return result;
}
}
public class AdxCalendarItem
{
public string CalendarName;
public string Subject;
public string Location;
public DateTime StartTime;
public DateTime EndTime;
public DateTime StartDate;
public DateTime EndDate;
public bool AllDayEvent;
public string Body;
public AdxCalendarItem(string CalendarName, string Subject, string Location, DateTime StartTime, DateTime EndTime,
DateTime StartDate, DateTime EndDate, bool AllDayEvent, string Body)
{
this.CalendarName = CalendarName;
this.Subject = Subject;
this.Location = Location;
this.StartTime = StartTime;
this.EndTime = EndTime;
this.StartDate = StartDate;
this.EndDate = EndDate;
this.AllDayEvent = AllDayEvent;
this.Body = Body;
}
}
Microsoft.Office.Interop.Outlook.Application oApp = null;
Microsoft.Office.Interop.Outlook.NameSpace mapiNamespace = null;
Microsoft.Office.Interop.Outlook.MAPIFolder CalendarFolder = null;
Microsoft.Office.Interop.Outlook.Items outlookCalendarItems = null;
oApp = new Microsoft.Office.Interop.Outlook.Application();
mapiNamespace = oApp.GetNamespace("MAPI"); ;
CalendarFolder = mapiNamespace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderCalendar);
outlookCalendarItems = CalendarFolder.Items;
outlookCalendarItems.IncludeRecurrences = true;
foreach (Microsoft.Office.Interop.Outlook.AppointmentItem item in outlookCalendarItems)
{
if (item.IsRecurring)
{
Microsoft.Office.Interop.Outlook.RecurrencePattern rp = item.GetRecurrencePattern();
// get all date
DateTime first = new DateTime( item.Start.Hour, item.Start.Minute, 0);
DateTime last = new DateTime();
Microsoft.Office.Interop.Outlook.AppointmentItem recur = null;
for (DateTime cur = first; cur <= last; cur = cur.AddDays(1))
{
try
{
recur = rp.GetOccurrence(cur);
MessageBox.Show(recur.Subject + " -> " + cur.ToLongDateString());
}
catch
{ }
}
}
else
{
MessageBox.Show(item.Subject + " -> " + item.Start.ToLongDateString());
}
}
}
it is working I try it but you need to add reference about
Microsoft outlook
Here's a combination of a few answers to get entries from the past 30 days. Will output to console but you can take the console log output and save to a file or whatever you want from there. Thanks to everyone for posting their code here, was very helpful!
using Microsoft.Office.Interop.Outlook;
void GetAllCalendarItems()
{
Microsoft.Office.Interop.Outlook.Application oApp = null;
Microsoft.Office.Interop.Outlook.NameSpace mapiNamespace = null;
Microsoft.Office.Interop.Outlook.MAPIFolder CalendarFolder = null;
Microsoft.Office.Interop.Outlook.Items outlookCalendarItems = null;
oApp = new Microsoft.Office.Interop.Outlook.Application();
mapiNamespace = oApp.GetNamespace("MAPI"); ;
CalendarFolder = mapiNamespace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderCalendar);
outlookCalendarItems = CalendarFolder.Items;
outlookCalendarItems.IncludeRecurrences = false;
Console.WriteLine("Showing Calendar Items From the last 30 days");
//Set your dates here...
DateTime startTime = DateTime.Now.AddDays(-31);
DateTime endTime = DateTime.Now;
string filter = "[Start] >= '"
+ startTime.ToString("g")
+ "' AND [End] <= '"
+ endTime.ToString("g") + "'";
try
{
outlookCalendarItems.Sort("[Start]", Type.Missing);
foreach (Microsoft.Office.Interop.Outlook.AppointmentItem item in outlookCalendarItems.Restrict(filter))
{
Console.WriteLine(item.Subject + " -> " + item.Start.ToLongDateString());
}
}
catch { }
Console.WriteLine("Finished");
}
GetAllCalendarItems();
calendarFolder =
mapiNamespace.GetDefaultFolder(
Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderCalendar);