Dynamic Calendar Web Application in ASP.NET 2.0
Introduction
Very often, you will find calendars on various website,
where a date can be labeled as a holiday, a special event, a birthday etc...
However, it would be really cumbersome to update the HTML page each time there is an event on a specific date.
This is where the power of ASP.NET comes into picture.
Linking a database of events and the dates to our page, we can dynamically generate a calendar
which will show the required information on specific dates.
Scenarios
In this tutorial, we will consider a list of events that will be stored
in database to be retrieved and properly label a date if an event falls on that date.
Below is a list of sample data that will be used in the tutorial.
| Event | Date |
| New Year | 1st Jan to 2nd of Jan 2007 |
| Independence Day | 5th Feb 2007 |
| Dad's Birthday | 3rd March 2007 |
| Valentine's Day! | 4th April 2007 |
| Wife's Birthday | 30th May 2007 |
| Camping with friends | 5th June to 10th June 2007 |
| Mum's Birthday | 8th July 2007 |
| Christmas | 25th Dec 2007 |
| Brother's Birthday | 26th Dec 2007 |
Fig 1. List of sample events for the application
Database Design for Calendar web application
An MS Access database named "Events" is created to hold the events.
There will be only 1 table named "Events" that will hold the information.
The fieldnames are self-explanatory, as shown in the figure 2.
For simplicity, we will manually fill in the data and make sure that Date From will not be greater than Date To.

Fig 2. Table definition for holding the events

Fig 3. Populated table containing list of events. Date format (mm/dd/yyyy)
Screen and CSS Design
We will only have one page holding the calendar for year 2007.
The page will only contain a title and a label.
It is the label that will hold the generated calendar as will be shown later.
A nice CSS will also be linked with the page.
Of course you are free to modify the CSS as per your taste.
The important CSS classes that will be used are:
calendarFrame
calendarMonthYear
calendarDay
hasEvent
hasNoEvent
The calendar style that will be displayed will look like as in figure 5.

Fig 5. Sample calendar showing the month March 2007.
Coding the Calendar Generator
A year consists of 12 months.
The months will be layout in a table of 4 rows x 3 columns.
Each month will consist of a maximum of 6 rows x 7 columns.
The columns will represent the days, starting with Sunday to Saturday.
A maximum of 6 rows can be obtained when the 1st of a 31-day month falls on a Saturday.
To generate calendar for the year 2207, the following code is used:
If
Not IsPostBack Then
' Generates report for current year
lblCalendar.Text = "<table width='600px'>"
' number of months in horizontal direction
Dim horizontalRepeat As
Integer = 3
Dim
month As Integer
For month = 1 To
12
If (month Mod
horizontalRepeat = 1) Then
lblCalendar.Text += "<tr valign='top'>"
End
If
lblCalendar.Text += "<td>" +
generateCalendar(month, 2007) + "</td>"
If
(month Mod horizontalRepeat = 0)
Then
lblCalendar.Text += "</tr>"
End
If
Next
lblCalendar.Text += "</table>"
End
If
The calendar is being dynamically constructed,
starting with the big table 4 rows x 3 columns. We skip to the next row when
"month Mod horizontalRepeat = 1", that is, when month value is 1, 4, 7 and 10.
We should not forget to close every HTML tag!
The method generateCalendar (month, 2007) returns a string containing an HTML table
that represents a specific month and put in between <td></td> tags.
The method below shows how a month is filled with dates and on which day the dates fall.
' generates the calendar as per the booking status
Dim
wholeCalendar(5, 6) As
Integer
Dim
weeks As Integer
= 0
Dim
day As String =
""
Dim
tmpDate As DateTime
Dim
myDate As Integer
For
myDate = 1 To 31
Try
tmpDate = New DateTime(year, month, myDate)
If (day = "Saturday")
Then
weeks += 1
End If
day = tmpDate.DayOfWeek.ToString()
If (day = "Sunday")
Then
wholeCalendar(weeks, 0) = myDate
ElseIf (day =
"Monday") Then
wholeCalendar(weeks, 1) = myDate
ElseIf (day =
"Tuesday") Then
wholeCalendar(weeks, 2) = myDate
ElseIf (day =
"Wednesday") Then
wholeCalendar(weeks, 3) = myDate
ElseIf (day =
"Thursday") Then
wholeCalendar(weeks, 4) = myDate
ElseIf (day =
"Friday") Then
wholeCalendar(weeks, 5) = myDate
ElseIf (day =
"Saturday") Then
wholeCalendar(weeks, 6) = myDate
End If
Catch ex As
Exception
Exit For
End Try
Next
The code snippet shows the beauty of the try ... catch block.
It completely eliminates the test whether February has to contain 28 or 29 days or whether a month should contain 30 or 31 days.
First, an array 6 x 7 of integer (0...5, 0...6) is created to hold the date 1 to 31.
We start with the first row of the array,
which in other terms represent the first week (week initially set to 0).
Having the year, month and date, an object of DateTime is created.
If there is an error, for example, 30th February,
we know that the last day of the month has been passed (Refer to figure 5).
If the current day is Saturday, the next day will be on the next row, i.e.
Sunday (start of the next week).
We get the day name from the method tmpDate.DayOfWeek.toString()
which will return a value from Monday to Sunday.
We then set the date in the corresponding cell.
Sunday is in column 0; Monday is in column 1 and so on.
After filling the array with numbers, HTML code has to be generated for the current month.
The following code snippet does the job.
' Generates the HTML calendar
Dim
htmlCalendar As String
= ""
Dim
objEventsDAO As New
EventsDAO()
Dim
dt As DataTable
Dim
i As Integer, j
As Integer
htmlCalendar += "<table class='calendarFrame'
cellspacing=0>"
htmlCalendar += "<tr class='calendarMonthYear'
style='text-align: center;'><td colspan='7'>" + getMonthName(month) +
" " + year.ToString() +
"</td></tr>"
htmlCalendar += "<tr class='calendarDay'
style='text-align: center;'> <td>Sun</td> <td>Mon</td> <td>Tue</td>
<td>Wed</td> <td>Thu</td> <td>Fri</td> <td>Sat</td> </tr>"
For
i = 0 To 5
htmlCalendar += "<tr>"
For
j = 0 To 6
If wholeCalendar(i, j) > 0
Then
dt = objEventsDAO.GetEvent(wholeCalendar(i, j), month, year)
If (dt.Rows.Count > 0)
Then
Dim toolTip
As String = dt.Rows(0)("Event").ToString()
htmlCalendar += "<td class='hasEvent'
title=""" + toolTip + """>" +
wholeCalendar(i, j).ToString() + "</td>"
Else
htmlCalendar += "<td class='hasNoEvent'>"
+ wholeCalendar(i, j).ToString() + "</td>"
End If
Else
htmlCalendar += "<td class='hasNoEvent'> </td>"
End
If
Next
htmlCalendar += "</tr>"
Next
htmlCalendar += "</table>"
' Close database connection
objEventsDAO.CloseConnection()
A class called EventsDAO is created containing methods to check whether on a particular
date there is an event or not.
Please refer to the attached code for getting the code.
The SQL commands are simple and self explanatory.
The string htmlCalendar holds the HTML code for the month table,
with the proper CSS class and table title for the current month and year.
Then using the array that was previously filled:
If current array cell contains a zero value,
a space; is placed in between <td></td> tags having the CSS class hasNoEvent.
If current array cell value is associated with an event, wholeCalendar(i, j).ToString()
is placed in between <td></td> tags with the CSS class hasEvent.
Also, when the mouse pointer is moved on the date,
a tooltip is shown containing the event description by adding the attribute Title to the <td> element.
If current array cell value is not associated with an event,
the value wholeCalendar(i,j).ToString() is placed in between <td></td> tags with the CSS class hasNoEvent.
Here is a sample look at the output fro the first 6 months, as seen in a browser.

Fig 6. Sample output of calendar for year 2007
There we are! You can try the sample Calendar web application,
attached for seeing the result.
Improvements / Enhancements
The tutorial is a kick start to get your creativity going. A few suggestions to improve the calendar:
Try accommodating different CSS class to different kind of events.
For example, public holidays can have red background circle.
Note that you should change the MS Access table as well.
Try changing the "year" parameter when generating the
calendar to see different results. E.g. generateCalendar(month, 2010) or generateCalendar(month, 2006)
|