2

Using Delphi to read Outlook appointments via COM... Code is working fine, with the exception of Recurring appointments. Everything I read says that I need to using RecurrencePattern and GetOccurrence and determine where the next appointment should be, and then try to get it, and see if it fails... This seems like a really "kludged" way of doing it.

Has anyone already written something like this? Apparently, there is some code on experts-exchange, but I don't have a subscription there... Can't find anything else.

IDEALLY (and I will take what I can get), I would like a routine that says.. this appointment has 6 occurrences, and here is an array of all the TDateTimes of each occurrence.

Note that all of this code works fine. I just need help filling out the BOTTOM section of code to build recurrance patterns.

CODE FRAGMENTS --- Not all code is shown---... as per request...

Access Outlook...

try
    Outlook := GetActiveOleObject('outlook.application');
    Form1.SB1.SimpleText := 'Outlook already started';
  except
    try
      Outlook := CreateOleObject('outlook.application');
      Created := True;
      Form1.SB1.SimpleText := 'Outlook not running.  Starting Outlook API';
    except
      // Unable to access or start OUTLOOK
      MessageDlg(
        'Unable to start or access Outlook.  Possibilities include: permission problems, server down, or VPN not enabled.  Exiting...', mtError, [mbOK], 0);
      exit;
    end;
  end;

... Get the Calendar of my recipient...

// Now get the calendar entry
    Calendar := Namespace.GetSharedDefaultFolder(Recip, 9);

Now set the filter to restrict appoints to be within a date range, and include recurrences.

 // If here, everything is good so far...
  // user name, email, and Calendar is accessible

  MyItems := Calendar.Items;
  MyItems.Sort('[Start]', False);

  MyItems.IncludeRecurrences := True;

  // Set the filter dates... SECONDS can NOT be shown...
  FilterStartDate := FormatDateTime('mmmm dd, yyyy', StartDate);
  FilterStartDate := FilterStartDate + ' 12:00 AM';

  FilterEndDate := FormatDateTime('mmmm dd, yyyy', EndDate);
  FilterEndDate := FilterEndDate + ' 11:59 PM';

  RestrictDateFilter := ('[Start]>' + CHR(34) + FilterStartDate + CHR(34) + 'and ' + '[Start]<' + CHR(34)
      + FilterEndDate + CHR(34));

  DebugIt('RestrictFilter:', RestrictDateFilter);
  Application.ProcessMessages;

  ItemCollection := MyItems.Restrict(RestrictDateFilter);
  ItemCollection.Sort('[Start]', False);

Read my first appointment

// Try to read the first appoint, or error message if no appointments
  try
    Appointment := ItemCollection.GetFirst;
  except
    DebugIt('No appointments found', '');
    MessageDlg('Unable to retrieve any appointments in this time frame.', mtError, [mbOK], 0);
    exit;
  end;

While looping through all the appointments...

if Appointment.IsRecurring = True then
      begin

        // Recurring Appointment, in a Valid RANGE
        DebugIt('Repeating appointment starting on ' + DateToStr(Appointment.Start), '');

        // If yearly repeating, we want to ignore
        RP := Appointment.GetRecurrencePattern;
        DebugIt('Determining appointment recurrence pattern', '');

        if ((RP.RecurrenceType = olRecursYearly) or (RP.RecurrenceType = olRecursYearNth)) then
        begin
          // ignore these appointments
        end
        else
        begin
        // HERE IS WHERE I NEED HELP
            // How do I determine all of the appointments based on the recurrences?  
        end;

      end;

Thanks GS

user1009073
  • 3,160
  • 7
  • 40
  • 82
  • 2
    Post a sample of your code, to give at least a little context. Mention interfaces you are using (ISomething or ISomethingElse). – Warren P Dec 19 '11 at 18:11
  • 1
    You don't really need an Experts-Exchange membership. If you can find the page you want on Google, click the link and scroll to the bottom of the page. When E-E gets a link from Google, it shows the whole page, including the answers. (If it didn't do that, the answers wouldn't be searchable, and E-E would be even less useful than it already is.) – Rob Kennedy Dec 19 '11 at 18:50
  • Odd. I tried that from a link in StackOverflow, and I didn't get the answer. When I search from Google, I get the answer... once I see the answer, it isn't what I had hoped for... – user1009073 Dec 19 '11 at 18:56
  • +1 for posting some context with code samples. – Warren P Dec 19 '11 at 21:43

1 Answers1

2

Figured out an answer.... Here is a routine I wrote which will go from MinDate to MaxDate, and test to see if the appointment exists on that date. This was the only way that I could get recurrences to work...

procedure IdentifyOutlookRecurrences(Appt: Variant; EmailID: Integer; MinDateAllowed, MaxDateAllowed: TDateTime);
var
  recurStart, recurEnd: TDateTime;
  RP: Variant;
  dt: TDate;
  PatternEndDate: TDate;
  TestAppt: Variant;
  year, month, day, hour, minute, second, ms: Word;
  CheckDateTime: TDateTime;
  OccurrenceEndDate: TDateTime;
  OccurrenceNumber: Integer;

begin

  if Appt.IsRecurring then
  begin
    RP := Appt.GetRecurrencePattern;
    DebugIt('Recurring Appt:', Appt.Subject);

    // Get the date range for our occurrences
    recurStart := RP.PatternStartDate;
    recurEnd := RP.PatternEndDate;
    DebugIt('Recur Start:End', DateToStr(recurStart) + ':' + DateToStr(recurEnd));
    DebugIt('RecurPattern Start Time', DateTimeToStr(RP.StartTime));

    // Identify the end point for looping...
    if recurEnd < MaxDateAllowed then
      PatternEndDate := recurEnd
    else
      PatternEndDate := MaxDateAllowed;

    // Get the minimum date allowed...
    dt := trunc(MinDateAllowed);

    DecodeDate(dt, year, month, day);
    DecodeTime(RP.StartTime, hour, minute, second, ms);

    OccurrenceNumber := 0;

    repeat

      DecodeDate(dt, year, month, day);
      CheckDateTime := EncodeDateTime(year, month, day, hour, minute, second, 0);
      DebugIt('Check for recurrance', DateTimeToStr(CheckDateTime));
      // Now check it the appointment exists.
      try
        TestAppt := RP.GetOccurrence(CheckDateTime);
        OccurrenceEndDate := CheckDateTime + (RP.Duration / 1440);
        DebugIt('Appt Recurrence *** IS *** found', DateTimeToStr(CheckDateTime));
        // Now write it to the database
        InsertApptIntoDB(Appt, EmailID, OccurrenceNumber, CheckDateTime, OccurrenceEndDate);
        Inc(OccurrenceNumber);
      except
        DebugIt('Appt Recurrence *** NOT *** found', DateTimeToStr(CheckDateTime));
      end;

      // Increment our date
      dt := dt + 1;
    until dt > PatternEndDate;
  end;
end;

DebugIt is just a logging routine I use...

user1009073
  • 3,160
  • 7
  • 40
  • 82