The ExICalendar library implements the ICalendar data format, according with Internet Calendaring and Scheduling Core Object Specification, RFC 5545. The iCalendar data format represents exchanging calendaring and scheduling information such as events, to-dos, journal entries, and free/busy information, independent of any particular calendar service or protocol.
While running a sample you might encounter the following exception:
An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in exe
Additional information: Retrieving the COM class factory for component with CLSID failed due to the following error: 80040154.
The most probably you have installed the /COM x86 version ( 32-bit ) of
the component on a Windows x64 machine, so in order to prevent this error
do any of the following:
In VS - project properties - in the Build tab - platform target X86
( AnyCPU to X86 )
Install the x64 version of the component as well, as the
application runs as 64-bit on a Windows 64 machine
The idea of adding recurring events to eXCalendar consists in:
Handle the DateChanged event of the eXCalendar component
Collects the occurrences of the recurrence expression between
FirstVisibleDate, LastVisibleDate properties of the eXCalendar
component, using the RecurRange method of the eXICalendar library
For each occurrence found, add a new events using the Add method of
the Events collection of eXCalendar component
The following VB sample adds recurring events to eXCalendar :
Private Sub Calendar1_DateChanged()
DoEvents
With Calendar1
.BeginUpdate
Dim o As Variant
For Each o In CreateObject("Exontrol.ICalendar").RecurRange("DTSTART=20151201;FREQ=WEEKLY;BYDAY=FR", .FirstVisibleDate, .LastVisibleDate)
.Events.Add(o).Marker = True
Next
.EndUpdate
End With
End Sub
Private Sub Form_Load()
With Calendar1
.FirstDay = Monday
.AlignmentDay = CenterAlignment
.GridLineColor = RGB(128, 128, 128)
Calendar1_DateChanged
End With
End Sub
and you should get:
The same sample in C++, should look such as:
void C...Dlg::DateChangedCalendar1()
{
DoEvents();
EXCALENDARLib::ICalendarPtr spCalendar1 = GetDlgItem(IDC_CALENDAR1)->GetControlUnknown();
if ( spCalendar1 != NULL )
{
EXCALENDARLib::IEventsPtr spEvents = spCalendar1->Events;
spCalendar1->BeginUpdate();
EXICALENDARLib::IICalendarPtr spICal = ::CreateObject(L"Exontrol.ICalendar");
if ( spICal != NULL )
{
_variant_t vtRecurRange = spICal->GetRecurRange(L"DTSTART=20151201;FREQ=WEEKLY;BYDAY=FR",spCalendar1->FirstVisibleDate,spCalendar1->LastVisibleDate);
if ( V_VT( &vtRecurRange ) == ( VT_ARRAY | VT_DATE ) )
{
SAFEARRAY* pArray = V_ARRAY( &vtRecurRange );
DATE* pData = NULL;
if ( SUCCEEDED( SafeArrayAccessData( pArray, (LPVOID*)&pData ) ) )
{
long lowerBound = 0, upperBound = 0;
SafeArrayGetLBound(pArray, 1 , &lowerBound);
SafeArrayGetUBound(pArray, 1, &upperBound);
long nCount = upperBound - lowerBound + 1;
SafeArrayUnaccessData( pArray );
for ( long i = 0; i < nCount; i++, pData++ ) // iterate through returned values
spEvents->Add( *pData )->Marker = VARIANT_TRUE;
}
}
}
spCalendar1->EndUpdate();
}
}
BOOL C...Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
...
EXCALENDARLib::ICalendarPtr spCalendar1 = GetDlgItem(IDC_CALENDAR1)->GetControlUnknown();
if ( spCalendar1 != NULL )
{
spCalendar1->PutAlignmentDay(EXCALENDARLib::CenterAlignment);
spCalendar1->PutFirstDay(EXCALENDARLib::Monday);
spCalendar1->PutGridLineColor(RGB(128,128,128));
DateChangedCalendar1();
}
return TRUE; // return TRUE unless you set the focus to a control
}
where the definitions for CreateObject, DoEvents is:
The idea of adding recurring tasks to eXG2antt/eXGantt consists in:
Handle the DateChanged event of the eXG2antt component
Collects the occurrences of the recurrence expression between first
visible date and last visible date, using the RecurRange method of the eXICalendar library
For each occurrence found, add a new task using the AddBar method of
the Items collection of eXG2antt component
The following VB sample adds recurring events to eXG2antt :
Function Max(ByVal a As Double, ByVal b As Double) As Double
Max = IIf(a < b, b, a)
End Function
Private Sub Form_Load()
With G2antt1
.BeginUpdate
.Columns.Add "Tasks"
.Items.AddItem "Every Friday, starting from 2015, Dec 1st"
With .Chart
.LevelCount = 2
.PaneWidth(0) = 224
.Bars("Task").Pattern = exPatternSolid
.FirstVisibleDate = #11/23/2015#
End With
.EndUpdate
End With
End Sub
Private Sub G2antt1_DateChange()
With G2antt1
.BeginUpdate
Dim o As Variant
For Each o In CreateObject("Exontrol.ICalendar").RecurRange("DTSTART=20151201;FREQ=WEEKLY;BYDAY=FR", .Chart.FirstVisibleDate, Max(.Chart.FirstVisibleDate + (1 + .Chart.PaneWidth(False) + .Chart.PaneWidth(True)) / .Chart.UnitWidth, .Chart.DateFromPoint(1, -1)))
.Items.AddBar .Items.FirstVisibleItem, "Task", o, o + 1, o
Next
.EndUpdate
End With
End Sub
and you should get:
A few notes:
The DateFromPoint(1, -1) property
determines the last visible date.
The Max(.Chart.FirstVisibleDate
+ (1 + .Chart.PaneWidth(False) + .Chart.PaneWidth(True)) / .Chart.UnitWidth,
.Chart.DateFromPoint(1, -1))), determines the maximum between
the last visible date if no columns section is displayed and the
currently last visible date
The initial FirstVisibleDate
should be called after filling the columns/items, so during the DateChange
event, the FirstVisibleItem property is
NOT zero, so adding bars is possible
running the trial version of the eXICalendar library (
Please check the Version property of the component, if contains DEMO )
RuntimeKey property has not been called, or using
invalid key, if running the registered version.
If you are running the registered version, you have to
call the RuntimeKey property right after creating the component like in
the following sample:
Set iCal = CreateObject("Exontrol.ICalendar.1")
With iCal
.RuntimeKey = "..."
Debug.Print( .RecurAllAsString("DTSTART=19970805;FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1",255) )
End With
where the "..."
is your runtime license key that
was provided in the email you have received by the time you purchased the
component. In case you have miss it, please contact us to request your
runtime license key.
The Load / LoadFile / LoadFileU methods loads iCalendar format into the
component. The Root / Content property gives access to the root / content
Component of the loaded format. Each component can have other components,
so the Count property of the Components collection counts the number of
Component objects in the collection, not including the inner components.
A) The following getComponentsCount function returns the number of
components in the control ( all/recursively Component objects ):
Function getComponentsCount(ByVal c As EXICALENDARLib.Component) As Long
Dim nCount As Long, i As EXICALENDARLib.Component
nCount = c.Components.Count
For Each i In c.Components
nCount = nCount + getComponentsCount(i)
Next
getComponentsCount = nCount
End Function
and you can call it using a code like: getComponentsCount(iCal.Content)
B) The following method shows how you can count the number of
Components begin found while loading the iCalendar format:
Dim nComponents As Long
Dim WithEvents iCal As EXICALENDARLib.ICalendar
Private Sub Form_Load()
Set iCal = New EXICALENDARLib.ICalendar
nComponents = 0
End Sub
Private Sub iCal_StartLoad()
nComponents = 0
End Sub
Private Sub iCal_AddComponent(ByVal NewComponent As EXICALENDARLib.IComponent)
nComponents = nComponents + 1
End Sub
Private Sub iCal_EndLoad()
Debug.Print (nComponents)
End Sub
where the nComponents member is increased each time the AddComponent
event occurs.