Share via


Creating Recurring Appointments and Meetings

Topic Last Modified: 2009-02-25

Recurring appointments and meetings occur more than once and follow a pattern in time. For example, a department meeting on the first Tuesday of each month can be defined as a recurring meeting.

In Collaboration Data Objects (CDO), a single Appointment object and one or more RecurrencePattern objects represent a recurring appointment or meeting. The Appointment object defines the first appointment or meeting, and the RecurrencePattern objects define the pattern for additional appointments or meetings. You can also specify modifications to the recurring meeting pattern by using one or more Exception objects.

To create a recurring appointment or meeting

  1. Create an Appointment object.
  2. Set the properties of the first appointment or meeting.
  3. Create a RecurrencePattern object and add it to the Appointment's RecurrencePatterns collection. You do this by using the IRecurrencePatterns.Add method.
  4. Set the properties of the RecurrencePattern object to create the desired recurrence pattern.
  5. For meetings, create one or more Attendee objects and specify the attendees.
  6. For meetings, create a CalendarMessage object by using the IAppointment.CreateRequest method and send the message.
  7. Save the appointment to the organizer's calendar (optional).

This topic contains Microsoft® Visual Basic®, Microsoft Visual C++®, Microsoft C#, and Visual Basic .NET code examples.

Example

Visual Basic

The following example creates a recurring meeting and then invites the specified attendees to the meeting.

' Reference to Microsoft ActiveX Data Objects 2.5 Library
' Reference to Microsoft CDO for Exchange 2000 Library

' Note: It is recommended that all input parameters be validated when they are
' first obtained from the user or user interface.
Sub CreateRecurringMeeting(ObjPer As CDO.Person, _
ObjAppt As CDO.Appointment, _
ObjFreq As CDO.CdoFrequency, _
LngInterval As Long, _
dtmEndDate As Date, _
ObjMbx As IMailbox, _
strAttnMandatory() As String, _
strAttnOptional() As String)

    Dim ObjConfig As New Configuration
    Dim ObjRRule As IRecurrencePattern
    Dim ObjCalMsg As CalendarMessage
    Dim ObjAtten As New Attendee
    Dim StrCalendarURL As String
    Dim ObjConn As New ADODB.Connection

    ObjConn.Provider = "ExOLEDB.DataSource"

    'Set the configuration fields
    ObjConfig.Fields(cdoSendEmailAddress) = ObjPer.Email
    ObjConfig.Fields(CDO.cdoMailboxURL) = ObjMbx.BaseFolder
    ObjConfig.Fields.Update

    With ObjAppt
        .Configuration = ObjConfig

        'Create the RecurrencePattern Object
        Set ObjRRule = .RecurrencePatterns.Add("Add")

        'Define the recurrence pattern
        'Frequency such as cdoWeekly or cdoDaily
        ObjRRule.Frequency = ObjFreq
        'Interval, for example "2"
        ObjRRule.Interval = LngInterval
        'The pattern end date.
        ObjRRule.PatternEndDate = dtmEndDate

        'Add attendees
        Dim i As Long
        For i = LBound(strAttnMandatory) To UBound(strAttnMandatory) - 1
            Set ObjAtten = .Attendees.Add
            ObjAtten.Address = CStr(strAttnMandatory(i))
            ObjAtten.Role = cdoRequiredParticipant
        Next i

        For i = LBound(strAttnOptional) To UBound(strAttnOptional) - 1
            Set ObjAtten = .Attendees.Add
            ObjAtten.Address = CStr(strAttnOptional(i))
            ObjAtten.Role = cdoOptionalParticipant
        Next i

        'Create Meeting Request Message and Send (to attendees).
        Set ObjCalMsg = .CreateRequest

        'Save the appointment to the organizer's calendar
        ObjConn.Open ObjMbx.BaseFolder
        .Datasource.SaveToContainer ObjMbx.Calendar, ObjConn

        ObjCalMsg.Message.Send

' Clean up.
        ObjConn.Close
        Set ObjConn = Nothing
    End With

End Sub

C++

The following example creates a recurring meeting and then invites the specified attendees to the meeting.

/*
 Assume that the following paths are in your
 INCLUDE or Directories path:
 %CommonProgramFiles%\system\ado
 %CommonProgramFiles%\microsoft shared\cdo
*/

#import <msado15.dll> no_namespace
#import <cdoex.dll> no_namespace
#include <iostream.h>
#include <vector>
using namespace std;

// Note: It is recommended that all input parameters be validated when they are
// first obtained from the user or user interface.

void createRecurringMeeting(
                     IAppointmentPtr& iAppt,
                     IMailboxPtr& iMbx,
                     CdoFrequency Frequency,
                     long Interval,
                     DATE endDate,
                     vector<bstr_t>& AttnMand,
                     vector<bstr_t>& AttnOpt
                     )
{

   if(iAppt == NULL || iMbx == NULL)
      _com_issue_error(E_INVALIDARG);

   IConfigurationPtr iConf(__uuidof(Configuration));
   _ConnectionPtr Conn(__uuidof(Connection));
   IRecurrencePatternPtr RRULE;
   ICalendarMessagePtr iCalMsg;
   IAttendeePtr iAttn;
   IPersonPtr  iPer;

    Conn->Provider = "ExOLEDB.DataSource";

   try {
      iPer = iMbx;
   }
   catch(_com_error e ) {
      cerr << "Invalid or unbound Person object reference passed." << endl;
      _com_issue_error(E_INVALIDARG);
   }

   iConf->Fields->Item[cdoSendEmailAddress]->Value = variant_t(iPer->Email);
   iConf->Fields->Item[cdoMailboxURL]->Value = variant_t(iMbx->BaseFolder);
   iConf->Fields->Update();

   iAppt->Configuration = iConf;

    //Create the RecurrencePattern object
    RRULE = iAppt->RecurrencePatterns->Add("Add");

    /*
     Define the recurrence pattern
      Frequency, such as cdoWeekly or cdoDaily
   */
    RRULE->Frequency = Frequency;

    // Interval, for example "2"
    RRULE->Interval = Interval;

    // The pattern end date.
    RRULE->PatternEndDate = endDate;

   typedef vector<bstr_t>::const_iterator CI;
   for(CI p = AttnMand.begin(); p != AttnMand.end(); p++) {
      iAttn = iAppt->Attendees->Add(bstr_t());
      iAttn->Address = _bstr_t(*p);
      iAttn->Role = cdoRequiredParticipant;
      cout << "Added " << bstr_t(*p) << " as required attendee to meeting." << endl;
   }

   for(p = AttnOpt.begin(); p != AttnOpt.end(); p++) {
      iAttn = iAppt->Attendees->Add(bstr_t());
      iAttn->Address = _bstr_t(*p);
      iAttn->Role = cdoOptionalParticipant;
      cout << "Added " << bstr_t(*p) << " as optional attendee to meeting." << endl;
   }

   try {
      iCalMsg = iAppt->CreateRequest();
   }
   catch(_com_error e) {
      cerr << "Error creating the request" << endl;
      throw e;
   }

    //Save the appointment to the organizer's calendar
   try {
      Conn->Open(iMbx->BaseFolder, bstr_t(), bstr_t(), -1);
      iAppt->DataSource->SaveToContainer(
                        iMbx->Calendar,
                        Conn,
                        adModeReadWrite,
                        adCreateNonCollection,
                        adOpenSource,
                        bstr_t(),
                        bstr_t());

      // Close the connection.
      Conn->Close();
      Conn = NULL;
    }
   catch(_com_error e) {
      cerr << "Error saving recurring appointment to user's calendar folder." << endl;
      throw e;
   }

   try {
      iCalMsg->Message->Send();
   }
   catch(_com_error e) {
      cerr << "Error sending calendar message." << endl;
      throw e;
   }

}

C#

The following example creates a recurring meeting and then invites the specified attendees to the meeting.

// Reference to Microsoft ActiveX Data Objects 2.5 Library
// Reference to Microsoft CDO for Exchange 2000 Library
static void CreateRecurringMeeting (CDO.Person ObjPer,
                                    CDO.Appointment ObjAppt,
                                    CDO.CdoFrequency ObjFreq,
                                    long LngInterval,
                                    DateTime dtmEndDate,
                                    CDO.IMailbox ObjMbx,
                                    string[] strAttnMandatory,
                                    string[] strAttnOptional)
{
   try
   {
      // Variables.
      CDO.Configuration ObjConfig = new CDO.Configuration();
      CDO.IRecurrencePattern ObjRRule;
      CDO.CalendarMessage ObjCalMsg;
      CDO.Attendee ObjAtten = new CDO.Attendee();
      ADODB.Connection ObjConn = new ADODB.Connection();

      ObjConn.Provider = "ExOLEDB.DataSource";

      // Set the configuration fields.
      ObjConfig.Fields[CDO.CdoConfiguration.cdoSendEmailAddress].Value = ObjPer.Email;
      ObjConfig.Fields[CDO.CdoConfiguration.cdoMailboxURL].Value = ObjMbx.BaseFolder;
      ObjConfig.Fields.Update();

      ObjAppt.Configuration = ObjConfig;

      // Create the RecurrencePattern object.
      ObjRRule = ObjAppt.RecurrencePatterns.Add("Add");

      // Set the recurrence pattern frequency,
      // such as cdoWeekly or cdoDaily.
      ObjRRule.Frequency = ObjFreq;

      // Set the recurrence pattern interval,
      // such as "2".
      ObjRRule.Interval = (int)LngInterval;

      // Set the recurrence pattern end date.
      ObjRRule.PatternEndDate = dtmEndDate;

      // Add mandatory attendees.
      long i;
      for (i = 0; i < strAttnMandatory.Length; ++i)
      {
         ObjAtten = ObjAppt.Attendees.Add("");
         ObjAtten.Address = Convert.ToString(strAttnMandatory[i]);
         ObjAtten.Role = CDO.CdoAttendeeRoleValues.cdoRequiredParticipant;
      }

      // Add optional attendees.
      for (i = 0; i < strAttnMandatory.Length; ++i)
      {
         ObjAtten = ObjAppt.Attendees.Add("");
         ObjAtten.Address = Convert.ToString(strAttnOptional[i]);
         ObjAtten.Role = CDO.CdoAttendeeRoleValues.cdoOptionalParticipant;
      }

      // Create the meeting request message.
      ObjCalMsg = ObjAppt.CreateRequest();

      // Save the appointment to the organizer's calendar.
      ObjConn.Open(ObjMbx.BaseFolder, "", "", -1);

      ObjAppt.DataSource.SaveToContainer(ObjMbx.Calendar, ObjConn,
      ADODB.ConnectModeEnum.adModeReadWrite,
      ADODB.RecordCreateOptionsEnum.adCreateNonCollection,
      ADODB.RecordOpenOptionsEnum.adOpenSource, "", "");

      // Send the meeting request message to the attendees.
      ObjCalMsg.Message.Send();

      // Close the connection.
      ObjConn.Close();

      Console.WriteLine("Meeting sent.");
   }

   catch (Exception err)
   {
      Console.WriteLine(err.ToString());
   }
}

Visual Basic .NET

The following example creates a recurring meeting and then invites the specified attendees to the meeting.

' Reference to Microsoft ActiveX Data Objects 2.5 Library
' Reference to Microsoft CDO for Exchange 2000 Library
Sub CreateRecurringMeeting(ByVal ObjPer As CDO.Person, _
                           ByVal ObjAppt As CDO.Appointment, _
                           ByVal ObjFreq As CDO.CdoFrequency, _
                           ByVal LngInterval As Long, _
                           ByVal dtmEndDate As Date, _
                           ByVal ObjMbx As CDO.IMailbox, _
                           ByVal strAttnMandatory() As Object, _
                           ByVal strAttnOptional() As Object)
   Try
      ' Variables.
      Dim ObjConfig As New CDO.Configuration()
      Dim ObjRRule As CDO.IRecurrencePattern
      Dim ObjCalMsg As CDO.CalendarMessage
      Dim ObjAtten As New CDO.Attendee()
      Dim ObjConn As New ADODB.Connection()

      ObjConn.Provider = "ExOLEDB.DataSource"

      ' Set the configuration fields.
      ObjConfig.Fields(CDO.CdoConfiguration.cdoSendEmailAddress).Value = ObjPer.Email
      ObjConfig.Fields(CDO.CdoConfiguration.cdoMailboxURL).Value = ObjMbx.BaseFolder
      ObjConfig.Fields.Update()

      With ObjAppt
         .Configuration = ObjConfig

         ' Create the RecurrencePattern object.
         ObjRRule = .RecurrencePatterns.Add("Add")

         ' Set the recurrence pattern frequency,
         ' such as cdoWeekly or cdoDaily.
         ObjRRule.Frequency = ObjFreq

         ' Set the recurrence pattern interval,
         ' such as "2"
         ObjRRule.Interval = LngInterval

         ' Set the recurrence pattern end date.
         ObjRRule.PatternEndDate = dtmEndDate

         ' Add mandatory attendees.
         Dim i As Long
         For i = LBound(strAttnMandatory) To UBound(strAttnMandatory)
            ObjAtten = .Attendees.Add
            ObjAtten.Address = CStr(strAttnMandatory(i))
            ObjAtten.Role = CDO.CdoAttendeeRoleValues.cdoRequiredParticipant
         Next i

         ' Add optional attendees.
         For i = LBound(strAttnOptional) To UBound(strAttnOptional)
            ObjAtten = .Attendees.Add
            ObjAtten.Address = CStr(strAttnOptional(i))
            ObjAtten.Role = CDO.CdoAttendeeRoleValues.cdoOptionalParticipant
         Next i

         ' Create the meeting request message.
         ObjCalMsg = .CreateRequest

         ' Save the appointment to the organizer's calendar.
         ObjConn.Open(ObjMbx.BaseFolder)
         .DataSource.SaveToContainer(ObjMbx.Calendar, ObjConn)

         ' Send the meeting request message to the attendees.
         ObjCalMsg.Message.Send()

         ' Close the connection.
         ObjConn.Close()

         Console.WriteLine("Meeting sent.")

      End With

   Catch err As Exception
      Console.WriteLine(err.ToString())
   End Try

End Sub

When you use CDO to configure a recurrence pattern object, the recurrence pattern may not appear as expected in Outlook. For example, assume that you use CDO to create a "daily" meeting type with a recurrence of "weekdays." When an Outlook user views the meeting series, the recurrence pattern appears as a "weekly" meeting type together with the individual weekdays that are selected.

This is expected behavior. A daily meeting type with a recurrence of weekdays is functionally equal to a weekly meeting that has each weekday selected.