Description:
I have a cxScheduler control linked to unbound storage. I want to implement two-way synchronization between Microsoft Outlook and cxScheduler, such that one of two things happens. Either:
- Both Outlook and the cxScheduler control will contain the same set of appointments/events after synchronization (a merge operation). For example, suppose the cxScheduler control contains 2 events (call them A and B) and the Outlook calendar contains 2 appointments (call them B and C). Both items B are same event/appointment, in other words they occur at the same time and date. If I perform this type of synchronization, the end result is that both Outlook and the cxScheduler control will contain 3 items (A, B, and C).
- Both Outlook and the cxScheduler control will contain just the common appointments/events after synchronization (a delete operation). Using the previous example, if this type of synchronization is performed, then both Outlook and the cxScheduler control will contain 1 item (that is, B) after synchronization.
How can I implement this?
Answer:
To implement this functionality we recommend that you create the TcxOutlookSynchronize class descendant and add the two-way synchronization method there:
DelphiTcxOutlook2WaySynchronize = class(TcxOutlookSynchronize)
private
FEventModifyDateField: TcxCustomSchedulerStorageField;
public
property EventModifyDateField: TcxCustomSchedulerStorageField
read FEventModifyDateField write FEventModifyDateField;
procedure TwoWaySynchronize(ADeleteUnsynchronized: Boolean = False);
end;
The EventModifyDateField field is used to store the event's last modification date and time. This field is necessary for correctly updating events/appointments: if the Appointment's LastModificationTime property value is greater that event's value then we should update the event. Otherwise, we should update the corresponding appointment:
Delphi...
if AOutlookAppItem.LastModificationTime > AEvent.GetCustomFieldValueByName(EventModifyDateField.DisplayName) then
UpdateExistingEvent(AEvent, AOutlookAppItem, AStorageEntryIDs)
else
UpdateExistingAppointmentItem(AOutlookAppointmentItem, AEvent);
...
So, for the unbound storage it is necessary to create a custom field and set its value after modifying the event. For the bound storage it is necessary to create this field in the DataSet and define its values using the DataSet's methods.
If ADeleteUnsynchronized is True, the first step to take is to check for the unsynchronized events and appointments. To do this, it is necessary to iterate through both the events and appointments collections and look for the corresponding appointments/events in the other collection. If an event/appointment in one of the collections does not have a corresponding item in the other collection, we should delete this event/appointment:
Delphifor i := 1 to CalendarFolder.Items.Count do //Synchronize appointments
begin
AOutlookAppointmentItem := CalendarFolder.Items(J);
if not IsEventPersists(AOutlookAppointmentItem) then
CalendarFolder.Items(I).Delete
end;
for I := 0 to Storage.EventCount - 1 do //Synchronize events
begin
AEvent := Storage.Events[I];
if not IsAppPersists(AEvent) then
AEvent.Delete
end;
The IsEventPersists and IsAppPersists methods are the custom functions. You can review their implementations in the attached example.
Once we've completed that process, we should iterate through the remaining events and appointments and update their properties using the code as shown.
Please review the attached project which demonstrates how to implement the two-way synchronization logic. We also have a data-aware version of this solution kindly provided by our user Eddie Shipman. Please refer to report Q212666 in the Support Center ("How to implement two-way synchronization with DeleteUnsynchronized option").
I need only cxScheduller to Outlook, how can i do this?
Hello Vinicius,
I've created a separate ticket on your behalf (T478204: How to implement a synchronization between cxScheduler and MS Outlook?). It has been placed in our processing queue and will be answered shortly.