Click here to Skip to main content
15,900,461 members
Articles / Web Development / ASP.NET
Article

.NET class to create and maintain vCalendar information

Rate me:
Please Sign up or sign in to vote.
4.82/5 (27 votes)
6 Feb 2003CPOL 311.5K   1.6K   105   70
.NET class to create and maintain vCalendar information

Sample Image - vCalendar.gif

Introduction

I have been porting the calendar portion of my site to ASP.NET and came to the exporting of event information to a vCalendar file that can be imported into Outlook or other calendar apps that support the vCalendar/iCalendar format. So I created a class to wrap all of the formatting of information.

VB.NET
Public Class vCalendar
    Public Events As vEvents

    Public Overrides Function ToString() As String
        Dim result As New System.Text.StringBuilder()
        result.AppendFormat("BEGIN:VCALENDAR{0}", _<BR>             System.Environment.NewLine)
        'The following two lines seem to be required by <BR>        'Outlook to get the alarm settings
        result.AppendFormat("VERSION:2.0{0}", System.Environment.NewLine)
        result.AppendFormat("METHOD:PUBLISH{0}", _<BR>             System.Environment.NewLine)
        Dim item As vEvent
        For Each item In Events
            result.Append(item.ToString())
        Next
        result.AppendFormat("END:VCALENDAR{0}", _<BR>            System.Environment.NewLine)
        Return result.ToString
    End Function

    Public Sub New(ByVal Value As vEvent)
        Me.Events = New vEvents()
        Me.Events.Add(Value)
    End Sub

    Public Sub New()
        Me.Events = New vEvents()
    End Sub

    Public Class vAlarm
        Public Trigger As TimeSpan        <BR>           'Amount of time before event to display alarm
        Public Action As String         <BR>           'Action to take to notify user of alarm
        Public Description As String  'Description of the alarm

        Public Sub New()
            Trigger = TimeSpan.FromDays(1)
            Action = "DISPLAY"
            Description = "Reminder"
        End Sub

        Public Sub New(ByVal SetTrigger As TimeSpan)
            Trigger = SetTrigger
            Action = "DISPLAY"
            Description = "Reminder"
        End Sub

        Public Sub New(ByVal SetTrigger As TimeSpan, _<BR>              ByVal SetAction As String, ByVal SetDescription As String)
            Trigger = SetTrigger
            Action = SetAction
            Description = SetDescription
        End Sub

        Public Overrides Function ToString() As String
            Dim result As New System.Text.StringBuilder()
            result.AppendFormat("BEGIN:VALARM{0}", _<BR>               System.Environment.NewLine)
            result.AppendFormat("TRIGGER:P{0}DT{1}H{2}M{3}", _<BR>               Trigger.Days, Trigger.Hours, Trigger.Minutes, _<BR>               System.Environment.NewLine)
            result.AppendFormat("ACTION:{0}{1}", Action, _<BR>               System.Environment.NewLine)
            result.AppendFormat("DESCRIPTION:{0}{1}", _<BR>               Description, System.Environment.NewLine)
            result.AppendFormat("END:VALARM{0}", _<BR>               System.Environment.NewLine)
            Return result.ToString
        End Function
    End Class

    Public Class vEvent
        Public UID As String          'Unique identifier for the event
        Public DTStart As Date  'Start date of event.  <BR>                   'Will be automatically converted to GMT
        Public DTEnd As Date         'End date of event.  <BR>                   'Will be automatically converted to GMT
        Public DTStamp As Date        'Timestamp.  <BR>                   'Will be automatically converted to GMT
        Public Summary As String          'Summary/Subject of event
        Public Organizer As String    'Can be mailto: url or just a name
        Public Location As String
        Public Description As String
        Public URL As String
        Public Alarms As vAlarms        'Alarms needed for this event

        Public Overrides Function ToString() As String
            Dim result As New System.Text.StringBuilder()
            result.AppendFormat("BEGIN:VEVENT{0}", _<BR>               System.Environment.NewLine)
            result.AppendFormat("UID:{0}{1}", UID, _<BR>               System.Environment.NewLine)
            result.AppendFormat("SUMMARY:{0}{1}", _<BR>               Summary, System.Environment.NewLine)
            result.AppendFormat("ORGANIZER:{0}{1}", Organizer, _<BR>               System.Environment.NewLine)
            result.AppendFormat("LOCATION:{0}{1}", Location, _<BR>               System.Environment.NewLine)
            result.AppendFormat("DTSTART:{0}{1}", _<BR>               DTStart.ToUniversalTime.ToString("yyyyMMdd\THHmmss\Z"), _<BR>               System.Environment.NewLine)
            result.AppendFormat("DTEND:{0}{1}", _<BR>               DTEnd.ToUniversalTime.ToString("yyyyMMdd\THHmmss\Z"), _<BR>               System.Environment.NewLine)
            result.AppendFormat("DTSTAMP:{0}{1}", _<BR>               Now.ToUniversalTime.ToString("yyyyMMdd\THHmmss\Z"), _<BR>               System.Environment.NewLine)
            result.AppendFormat("DESCRIPTION:{0}{1}", Description, _<BR>               System.Environment.NewLine)
            If URL.Length > 0 Then result.AppendFormat("URL:{0}{1}", _<BR>               URL, System.Environment.NewLine)
            Dim item As vAlarm
            For Each item In Alarms
                result.Append(item.ToString())
            Next
            result.AppendFormat("END:VEVENT{0}", _<BR>                System.Environment.NewLine)
            Return result.ToString
        End Function

        Public Sub New()
            Me.Alarms = New vAlarms()
        End Sub
    End Class

    Public Class vAlarms
        ' The first thing to do when building a CollectionBase <BR>        ' class is to inherit from System.Collections.CollectionBase
        Inherits System.Collections.CollectionBase

        Public Overloads Function Add(ByVal Value As vAlarm) As vAlarm
            ' After you inherit the CollectionBase class, you <BR>            ' can access an intrinsic object
            ' called InnerList that represents your collection. <BR>            ' InnerList is of type ArrayList.
            Me.InnerList.Add(Value)
            Return Value
        End Function

        Public Overloads Function Item(ByVal Index As Integer) As vAlarm
            ' To retrieve an item from the InnerList, <BR>            ' pass the index of that item to the .Item property.
            Return CType(Me.InnerList.Item(Index), vAlarm)
        End Function

        Public Overloads Sub Remove(ByVal Index As Integer)
            ' This Remove expects an index.
            Dim cust As vAlarm

            cust = CType(Me.InnerList.Item(Index), vAlarm)
            If Not cust Is Nothing Then
                Me.InnerList.Remove(cust)
            End If
        End Sub

    End Class

    Public Class vEvents
        ' The first thing to do when building a CollectionBase <BR>        ' class is to inherit from System.Collections.CollectionBase
        Inherits System.Collections.CollectionBase

        Public Overloads Function Add(ByVal Value As vEvent) As vEvent
            ' After you inherit the CollectionBase class, <BR>            ' you can access an intrinsic object
            ' called InnerList that represents your collection. <BR>            ' InnerList is of type ArrayList.
            Me.InnerList.Add(Value)
            Return Value
        End Function

        Public Overloads Function Item(ByVal Index As Integer) As vEvent
            ' To retrieve an item from the InnerList, <BR>            ' pass the index of that item to the .Item property.
            Return CType(Me.InnerList.Item(Index), vEvent)
        End Function

        Public Overloads Sub Remove(ByVal Index As Integer)
            ' This Remove expects an index.
            Dim cust As vEvent

            cust = CType(Me.InnerList.Item(Index), vEvent)
            If Not cust Is Nothing Then
                Me.InnerList.Remove(cust)
            End If
        End Sub
    End Class
End Class

I plan to add more properties as I discover them, but these are pretty much the only ones that are supported by outlook at this time. I also wanted to get some feedback on my design.

vCalendar specs

Here are some links to for the vCalendar specs (thanks Tommi):

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
http://www.onlinescorekeeper.com/

Comments and Discussions

 
GeneralRe: Not working Pin
mmikey12125-Mar-04 10:29
mmikey12125-Mar-04 10:29 
GeneralRe: Not working Pin
Chris Becker25-Mar-04 10:37
sussChris Becker25-Mar-04 10:37 
GeneralRe: Not working Pin
Anonymous3-Aug-04 8:25
Anonymous3-Aug-04 8:25 
GeneralUpdates to an ASP page Pin
Anonymous7-Nov-03 6:10
Anonymous7-Nov-03 6:10 
GeneralRe: Updates to an ASP page Pin
slolife7-Nov-03 6:37
slolife7-Nov-03 6:37 
GeneralRe: Updates to an ASP page Pin
Anonymous7-Nov-03 9:10
Anonymous7-Nov-03 9:10 
QuestionC# version? Pin
neilio17-Aug-03 9:52
neilio17-Aug-03 9:52 
AnswerRe: C# version? Pin
Chris Becker25-Aug-03 18:34
sussChris Becker25-Aug-03 18:34 
Yep, here ya go:

//$Date: 6/17/03 12:58p $
//$Revision: 1 $

using System;
using OnlineScorekeeper.Helpers;

namespace OnlineScorekeeper.Helpers
{
	public class vCalendar
	{
		//Specs can be found at: http://www.imc.org/pdi/pdiproddev.html
		public vEvents Events;

		public override string ToString()
		{
			System.Text.StringBuilder result = new System.Text.StringBuilder();
			result.AppendFormat("BEGIN:VCALENDAR{0}", System.Environment.NewLine);

			//The following two lines seem to be required by Outlook to get the alarm settings
			result.AppendFormat("VERSION:2.0{0}", System.Environment.NewLine);
			result.AppendFormat("METHOD:PUBLISH{0}", System.Environment.NewLine);

			result.Append(Events.ToString());
			result.AppendFormat("END:VCALENDAR{0}", System.Environment.NewLine);
			return result.ToString();
		}

		public vCalendar(vEvent value)
		{
			this.Events.Add(value);
		}

		public vCalendar()
		{
			//Do nothing
		}

		public class vRecurrence
		{
			//RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTHDAY=12;BYMONTH=11;WKST=SU				//Every year on Nov 12
			//RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=TU;BYMONTH=11;BYSETPOS=2;WKST=SU		//Every 2nd Tue of Nov, yearly
			//RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=SA;BYMONTH=11;BYSETPOS=-1;WKST=SU		//Last Sat of Nov
			//RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=SA;BYMONTH=11;BYSETPOS=1;WKST=SU		//First Sat of Nov, yearly
			//RRULE:FREQ=WEEKLY;INTERVAL=2;BYDAY=SU,MO,TU,WE,TH,FR,SA;WKST=SU			//every 2 weeks on all days
			//RRULE:FREQ=DAILY; INTERVAL=1;UNTIL=20031110T000000Z;WKST=SU				//daily every 1 day until end date
			//RRULE:FREQ=DAILY; COUNT=10;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;WKST=SU			//daily every day for 10 occurrences

			public enum Frequencies
			{
				Daily, Weekly, Monthly, Yearly
			}

			public enum DaysOfWeek
			{
				Su, Mo, Tu, We, Th, Fr, Sa
			}

			public Frequencies Frequency;
			public int Interval = 0;
			public DaysOfWeek WeekStart = DaysOfWeek.Su;
			public DateTime EndDateTime;
			public int Occurences = 0;

			private int m_MonthDay;

			public int MonthDay
			{
				get { return m_MonthDay; }
				set
				{
					if (value >= 1 || value <= 31)
					{
						m_MonthDay = value;
					}
					else
					{
						throw new Exception("MonthDay must be between 1 and 31.");
					}
				}
			}

			public override string ToString()
			{
				System.Text.StringBuilder result = new System.Text.StringBuilder();
				result.Append("RRULE:");
				result.AppendFormat("FREQ={0};", Frequency.ToString().ToUpper());
				if (Interval > 0)
					result.AppendFormat("INTERVAL={0};", Interval);
				if (EndDateTime > DateTime.MinValue)
					result.AppendFormat("UNTIL={0};", EndDateTime.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"));
				if (Occurences > 0)
					result.AppendFormat("COUNT={0};", Occurences);
				result.AppendFormat("WKST={0}", WeekStart.ToString().ToUpper());
				return (result.ToString());
			}
		}

		public class vAlarm
		{
			public TimeSpan Trigger;	//Amount of time before event to display alarm
			public string Action;		//Action to take to notify user of alarm
			public string Description;	//Description of the alarm

			public vAlarm()
			{
				Trigger = TimeSpan.FromDays(1);
				Action = "DISPLAY";
				Description = "Reminder";
			}

			public vAlarm(TimeSpan setTrigger)
			{
				Trigger = setTrigger;
				Action = "DISPLAY";
				Description = "Reminder";
			}

			public vAlarm(TimeSpan setTrigger, string setAction, string setDescription)
			{
				Trigger = setTrigger;
				Action = setAction;
				Description = setDescription;
			}

			public override string ToString()
			{
				System.Text.StringBuilder result = new System.Text.StringBuilder();
				result.AppendFormat("BEGIN:VALARM{0}", System.Environment.NewLine);
				result.AppendFormat("TRIGGER:P{0}DT{1}H{2}M{3}", Trigger.Days, Trigger.Hours, Trigger.Minutes, System.Environment.NewLine);
				result.AppendFormat("ACTION:{0}{1}", Action, System.Environment.NewLine);
				result.AppendFormat("DESCRIPTION:{0}{1}", Description, System.Environment.NewLine);
				result.AppendFormat("END:VALARM{0}", System.Environment.NewLine);
				return result.ToString();
			}
		}

		public class vEvent
		{
			public string UID;						//Unique identifier for the event
			public DateTime DTStart;				//Start date of event.  Will be automatically converted to GMT
			public DateTime DTEnd;					//End date of event.  Will be automatically converted to GMT
			public DateTime DTStamp;				//Timestamp.  Will be automatically converted to GMT
			public string Summary;					//Summary/voidject of event
			public string Organizer;				//Can be mailto:, url, or just a name
			public string Location;					//Location of event
			public string Description;				//Description of event
			public string url;						//URL for event info
			public vAlarms Alarms = new vAlarms();	//Alarms for this event
			public vRecurrence Recurrence;
			public bool isPrivate = false;

			public override string ToString()
			{
				System.Text.StringBuilder result = new System.Text.StringBuilder();
				result.AppendFormat("BEGIN:VEVENT{0}", System.Environment.NewLine);
				result.AppendFormat("UID:{0}{1}", UID, System.Environment.NewLine);
				result.AppendFormat("SUMMARY:{0}{1}", Summary, System.Environment.NewLine);
				result.AppendFormat("ORGANIZER:{0}{1}", Organizer, System.Environment.NewLine);
				result.AppendFormat("LOCATION:{0}{1}", Location, System.Environment.NewLine);
				result.AppendFormat("DTSTART:{0}{1}", DTStart.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"), System.Environment.NewLine);
				result.AppendFormat("DTEND:{0}{1}", DTEnd.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"), System.Environment.NewLine);
				if (Recurrence != null) result.Append(Recurrence.ToString());
				result.AppendFormat("DTSTAMP:{0}{1}", DateTime.Now.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"), System.Environment.NewLine);
				result.AppendFormat("DESCRIPTION:{0}{1}", Description, System.Environment.NewLine);
				if (!Strings.IsBlank(url)) result.AppendFormat("URL:{0}{1}", url, System.Environment.NewLine);
				result.Append(Alarms.ToString());
				if (isPrivate)
					result.AppendFormat("CLASS:{0}{1}", "PRIVATE", System.Environment.NewLine);
				else
					result.AppendFormat("CLASS:{0}{1}", "PUBLIC", System.Environment.NewLine);

				result.AppendFormat("END:VEVENT{0}", System.Environment.NewLine);
				return result.ToString();
			}
		}

		public class vAlarms : System.Collections.CollectionBase
		{

			public vAlarm Add(vAlarm value)
			{
				// After you inherit the CollectionBase class, you can access an intrinsic object
				// called InnerList that represents your collection. InnerList is of type ArrayList.
				this.InnerList.Add(value);
				return (value);
			}

			public vAlarm Item(int index)
			{
				// To retrieve an item from the InnerList, pass the index of that item to the .Item property.
				return (vAlarm) this.InnerList[index];
			}

			public void Remove(int index)
			{
				// This Remove expects an index.
				vAlarm cust = (vAlarm) this.InnerList[index];
				if (cust != null)
					this.InnerList.Remove(cust);
			}

			public override string ToString()
			{
				System.Text.StringBuilder result = new System.Text.StringBuilder();
				foreach(vAlarm item in this.InnerList)
				{
					result.Append(item.ToString());
				}
				return (result.ToString());
			}
		}

		public class vEvents : System.Collections.CollectionBase
		{

			public vEvent Add(vEvent value)
			{
				// After you inherit the CollectionBase class, you can access an intrinsic object
				// called InnerList that represents your collection. InnerList is of type ArrayList.
				this.InnerList.Add(value);
				return value;
			}

			public vEvent Item(int index)
			{
				// To retrieve an item from the InnerList, pass the index of that item to the .Item property.
				return (vEvent) this.InnerList[index];
			}

			public void Remove(int index)
			{
				// This Remove expects an index.
				vEvent cust = (vEvent) this.InnerList[index];
				if (cust != null)
					this.InnerList.Remove(cust);
			}

			public override string ToString()
			{
				System.Text.StringBuilder result = new System.Text.StringBuilder();
				foreach(vEvent item in this.InnerList)
				{
					result.Append(item.ToString());
				}
				return (result.ToString());
			}
		}
	}
}

GeneralGeneral Support Pin
CliffWoodger12-Aug-03 23:26
CliffWoodger12-Aug-03 23:26 
GeneralRe: General Support Pin
Chris Becker13-Aug-03 6:42
sussChris Becker13-Aug-03 6:42 
QuestionGreat - How to use it? Pin
sides_dale17-Jun-03 4:13
sides_dale17-Jun-03 4:13 
AnswerRe: Great - How to use it? Pin
slolife17-Jun-03 6:53
slolife17-Jun-03 6:53 
GeneralRe: Great - How to use it? Pin
sides_dale17-Jun-03 7:55
sides_dale17-Jun-03 7:55 
GeneralRe: Great - How to use it? Pin
fabrirs1-Feb-04 16:02
fabrirs1-Feb-04 16:02 
GeneralRe: Great - How to use it? Pin
sides_dale1-Feb-04 16:37
sides_dale1-Feb-04 16:37 
GeneralRe: Great - How to use it? Pin
fabrirs1-Feb-04 18:39
fabrirs1-Feb-04 18:39 
GeneralRe: Great - How to use it? Pin
fabrirs1-Feb-04 19:04
fabrirs1-Feb-04 19:04 
GeneralNice - how about an vCard class Pin
davidM10-Feb-03 6:20
davidM10-Feb-03 6:20 
GeneralRe: Nice - how about an vCard class Pin
Jeffry van de Vuurst23-Mar-03 8:00
Jeffry van de Vuurst23-Mar-03 8:00 
GeneralRe: Nice - how about an vCard class Pin
slolife11-Apr-03 15:27
slolife11-Apr-03 15:27 
GeneralVB.NET Pin
Jon Sagara7-Feb-03 18:32
Jon Sagara7-Feb-03 18:32 
GeneralRe: VB.NET Pin
Sgt. Bilko7-Feb-03 21:33
sussSgt. Bilko7-Feb-03 21:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.