Table of Contents

Recurrence

A recurring item repeats on a schedule — a weekly stand-up, a daily backup window, a monthly review — without storing a separate item for every occurrence. The planner models recurrence with the iCalendar RRULE standard: set an item's Recurrency property to an RRULE string and the planner expands the occurrences across the visible range. This guide covers writing RRULEs in code, letting users edit them through the recurrence editor, and persisting them with the database adapter.

RRULE basics

TTMSFNCPlannerItem.Recurrency holds a standard iCalendar recurrence rule. A few common patterns:

RRULE Meaning
FREQ=DAILY;COUNT=10 Every day, ten occurrences.
FREQ=WEEKLY;BYDAY=TU,TH Every Tuesday and Thursday.
FREQ=WEEKLY;INTERVAL=2;BYDAY=MO Every other Monday.
FREQ=MONTHLY;BYMONTHDAY=1 The first of every month.

The item's Recurrent property reports whether an item is an occurrence of a recurring series. Set Recurrency and the planner renders each occurrence within the timeline window automatically:

procedure TForm1.AddRecurringItems;
var
  weekly, daily: TTMSFNCPlannerItem;
begin
  Planner1.BeginUpdate;
  try
    // A weekly stand-up every Tuesday and Thursday.
    weekly := Planner1.AddOrUpdateItem(EncodeDateTime(2026, 6, 23, 9, 0, 0, 0),
                                       EncodeDateTime(2026, 6, 23, 9, 30, 0, 0),
                                       'Stand-up', '');
    weekly.Recurrency := 'FREQ=WEEKLY;BYDAY=TU,TH';

    // A daily backup window for ten occurrences.
    daily := Planner1.AddOrUpdateItem(EncodeDateTime(2026, 6, 22, 23, 0, 0, 0),
                                      EncodeDateTime(2026, 6, 22, 23, 30, 0, 0),
                                      'Backup', '');
    daily.Recurrency := 'FREQ=DAILY;COUNT=10';
  finally
    Planner1.EndUpdate;
  end;

  // Give the end user a recurrence UI in the item editor dialog.
  Planner1.ItemEditor := PlannerItemEditorRecurrency1;
  Planner1.Interaction.UpdateMode := pumDialog;
end;

The recurrence editor

TTMSFNCPlannerItemEditorRecurrency is a ready-made item editor that adds a recurrence panel to the item dialog, so end users build RRULEs without typing them. Assign it to Planner1.ItemEditor and set Interaction.UpdateMode := pumDialog (both shown above) so editing an item opens the dialog with the recurrence controls.

Putting it together

When items come from a dataset, map the RRULE field through the database adapter: set Adapter.Item.Recurrency to the field name that stores the rule. The adapter then loads and saves Recurrency with every other field, so recurring series survive between sessions. This example combines recurrence with persistence — it maps the RRULE field, then adds a recurring item whose rule round-trips to the database:

procedure TForm1.PersistRecurringItems;
var
  it: TTMSFNCPlannerItem;
begin
  // Map the RRULE column alongside the other item fields.
  PlannerDatabaseAdapter1.Item.DataSource := DataSource1;
  PlannerDatabaseAdapter1.Item.DBKey := 'Id';
  PlannerDatabaseAdapter1.Item.StartTime := 'StartTime';
  PlannerDatabaseAdapter1.Item.EndTime := 'EndTime';
  PlannerDatabaseAdapter1.Item.Title := 'Title';
  PlannerDatabaseAdapter1.Item.Recurrency := 'Recurrency';

  Planner1.Adapter := PlannerDatabaseAdapter1;
  PlannerDatabaseAdapter1.Active := True;

  // The new item's RRULE is saved through the mapped Recurrency field.
  it := Planner1.AddOrUpdateItem(Today + EncodeTime(9, 0, 0, 0),
                                 Today + EncodeTime(9, 30, 0, 0),
                                 'Stand-up', '');
  it.Recurrency := 'FREQ=WEEKLY;BYDAY=MO,WE,FR';
end;

Pitfalls

  • Recurrency is the rule, not the occurrences. Set the RRULE on the master item; the planner expands occurrences for display. Do not add an item per occurrence yourself.
  • Editor plus dialog mode. The recurrence editor only appears when ItemEditor is assigned and UpdateMode is pumDialog; in pumInplace mode the inplace editor has no recurrence panel.
  • Map the field to persist rules. Without an Adapter.Item.Recurrency mapping, recurring items load as single items.

See also