Building Lotus Notes/Domino calendar applications
The Lotus Notes calendar is one of the most popular and easy to use components of Lotus Notes. Calendars can be used for many different purposes. Some of the more common uses include:
- conference room reservations
- equipment reservations
- shared business or department calendar
- resource or event planner
- vacation planner
In addition to its end-user features, the Notes calendar can be very useful to application developers. In this article, we provide step-by-step instructions for building a simple calendar application. We assume you're an experienced Lotus Notes/Domino developer, and are familiar with basic Notes calendar features.
There are two primary components that make up a calendar application: a form and a view. The form is used to capture information such as the appointment date, time, and subject. The view simply displays the subject, based on the specified date and time provided in the form. Believe it or not, these two elements are all you need to build a calendar application that can manage recurring events.
Before we start programming, we need to first understand a few rules for building a calendar application and the process used in the management of recurring events.
- The appointment form must have a start date field. This field determines where to display the event on the calendar. The start date is the anchor for the calendar application.
- The appointment form must contain a duration. This field must be numeric and represents the number of sequential days for the event. (The appointment form can also include a start and end time. However, this is an optional value and is not required for actually displaying the event on a calendar.)
- Column1 of the calendar view must contain a date/time value sorted in ascending order. This column should be hidden from the user. (You must sort the first column in ascending order for the calendar view to display correctly.)
- Column2 of the calendar view must contain the duration for the calendar event. This value determines how many sequential days to display the appointment. The duration value can be either a positive or negative value. Positive numbers will display calendar events to the right (or future) of the start date. Negative numbers will display calendar events to the left (or prior) to the start date.
- The style of the view must be set to Calendar. This setting changes the appearance of the view from the traditional look to an actual calendar.
Now letâs delve deeper into the architecture and implementation options for managing recurring calendar events. The complexity of the application will revolve around the process to manage repeating events. As with any software language, there are many ways to design, develop, and implement a solution. The next sections will discuss two possible architectures.
Managing recurring events using single documents
We have already discussed the primary elements of the calendar application, a form and a view. The next step is to talk about options for managing recurring events. This first approach is a simple and efficient method to manage sequential calendar events.
A sequential event is an appointment that continues beyond the initial date. In other words, you can create a single appointment that is displayed on numerous calendar dates. However, all calendar dates must be in sequence, such as April 4 through 7. The "single document" approach creates one document and displays the appointment across the calendar date range (see Figure 1). This approach is simple to implement. If you're looking to build a calendar application or add a calendar to an existing application quickly, this would be a good starting point.
Figure 1. Single document recurring event
The primary advantage to this approach is the simplicity to implement. You can generate a new application (or enhance an existing application by adding a couple of fields and creating a calendar view) with minimal effort. Also, because all calendar dates reference the same (or single) document, users only need to update one document. Changes are reflected across each calendar date. For example, letâs say the author wants to include a conference phone number in the body of the appointment. The author can make one update and the change is immediately available across all calendar dates. Other team members can double-click any of the documents and see the same consistent information.
The disadvantage to this approach is the inability to manage complex recurring events. If youâre looking for the ability to schedule events for the second Friday or third day of each month, then the single document approach will require that the user manually create an entry on each date.
The next section will cover a more robust, comprehensive architecture for repeating events.
Managing recurring events using multiple documents
The "multiple document" approach creates a separate document based on the recurring event parameters specified in the initial appointment. For example, you can create one appointment that generates a separate document for each calendar date (see Figure 2). This architecture offers much greater flexibility in scheduling, but is considerably more complex to implement.
Figure 2. Multiple document recurring event
To implement this second approach requires additional information to be captured in the initial appointment form. This is managed via a separate dialog window that prompts the user to specify the recurring event parameters: weekly, daily, day of the week, skip weekends, monthly, custom dates, and so on. When the initial appointment is saved, all recurring event dates are calculated and a separate document is generated for each calendar date.
Using this second approach provides much greater flexibility and options to manage recurring events. Implementing this architecture allows you to create repeating events:
|By Date||April 4 (one-day event)|
|Daily by date||April 4 through April 7 (sequential)|
|Weekly by day||Monday, Wednesday, and Friday|
|Monthly by date||First of each month|
|Monthly by day||Third Friday of each month|
|Custom dates||A comma delimited list of calendar dates|
|Skip Weekends||Do not create if event falls on Saturday or Sunday|
|Next Business Day||Move event to Monday if computed day is a weekend|
Another advantage is the ability to move and delete events. Since each event is stored as a unique document, users can move, delete or update one calendar event without affecting the other related events.
The disadvantage to this approach is the complex algorithm required to calculate the event dates. This approach also creates a separate document for each event. If the author wants to update the subject or body for all related events, each document will need to be independently updated.
There are additional challenges associated with deleting, or removing, a scheduled appointment. To delete all related appointments, the author will need to delete each one individually, or include a subroutine to automatically remove related events.
Building a simple event calendar
Now let's turn our attention to building a simple example of a single-document calendar application. Letâs start by first launching the Lotus Domino Designer client and creating a blank database (see Figure 3). To do this, open the Domino Designer client and select File - Database - New. Specify an application title and file name. Be sure to select "-Blank-" as the template type.
Figure 3. New Database screen
Itâs a good idea to remove all spaces from the "File name" field. Spaces can cause problems when working with Web applications. For example, replace "Meeting Calendar.nsf" with "MeetingCalendar.nsf."
Creating the Appointment form
The appointment form captures the event start and end dates, duration, author, subject, and details. The duration will automatically be computed. Most of the work associated with calendar applications resides in the appointment form, including management of recurrent events.
To create a form, click the New Form button or select the Create - Design - Form menu options.
Next, add the fields specified in the following table. To create a field, select the Create - Field menu options. Be sure to set the data type, formula, and other properties for each field on the form.
|StartDate||Date/Time, Editable||DEFAULT StartDate:= @If(@IsNewDoc; @Today; @Return(StartDateTime)); StartDate||Set the style to Calendar/Time Control in the field properties dialog.|
|EndDate||Date/Time, Editable||n/a||Set the style to Calendar/Time Control in the field properties dialog.|
|Duration||Number, Computed||@If(StartDate = ""; 0; EndDate = ""; 0; @BusinessDays(StartDate; EndDate))||This formula will automatically compute the duration, based on the start and end dates.|
|Person||Text, Computed when Composed||@Name([CN]; @UserName)||This formula will automatically compute the authorâs name.|
|Body||Rich Text, Editable||n/a||n/a|
The field name, type, and style will be defined in the properties dialog. The field formula will be placed in the Value or Default Value section of the programmerâs pane, located in the lower section of the Designer client. Select View - Programmerâs Pane if the pane is not visible. (See the Domino Designer product documentation for details about how to use the Domino Designer client.)
Defining global objects
The next step is to define global objects associated with the form in the "(Globals)" section. You can define an object once and refer to the object throughout the form. This simplifies the code and makes the application code more efficient.
Set the following in the "Declarations" section found under the "(Global)" heading:
Dim doc As NotesDocument ' Refers to the current calendar document Dim ws As NotesUIWorkspace ' Refers to the current application workspace Dim s As NotesSession ' Refers to the current notes session Dim db As NotesDatabase ' Refers to the current Notes database Dim sDate As NotesDateTime ' Temporary variable for Start Date calculations Dim eDate As NotesDateTime ' Temporary variable for End Date calculations
We suggest that you add "Option Explicit" in the "(Options)" section. This forces you to declare (for example, DIM) all variables and will help you with debugging. If the variable is not defined, the statement is flagged as a syntax error. This makes it much easier to find problems in the code (such as mis-typed variable names).
Your calendar appointment form should now look similar to Figure 4:
Figure 4. Calendar appointment form
Set the window title to Appointment. This title will display at the top of the window whenever this form is opened in the Lotus Notes client. The title helps make the application more user-friendly. The window title is not used anywhere else in the application and can be changed to any value you prefer (for example, Appointment, Meeting, or "Meeting by " + person's name).
After the document is opened, set a default start date in the appointment form:
Sub Queryopen(Source As Notesuidocument, Mode As Integer, Isnewdoc As Variant, Continue As Variant) Set ws = New NotesUIWorkspace Set s = New NotesSession ApptDate = ws.CurrentCalendarDateTime End Sub
Obtain a handle to the document after the appointment is displayed. The doc object will be used in several LotusScript events to set and retrieve information from the appointment record:
Sub Postopen(Source As Notesuidocument) Set doc = source.Document End Sub
Calculate two variables to be utilized in the calendar view: StartDateTime and CalendarDateTime. These variables will contain the array of sequential calendar dates. This code formats the data and sets the values on the appointment form.
Sub Postrecalc(Source As Notesuidocument) Dim mydate As NotesItem Set doc = source.Document Set mydate = doc.GetFirstItem("StartDate") Set sDate = New NotesDateTime(mydate.DateTimeValue.DateOnly) Set doc.StartDateTime = sDate Set eDate = New NotesDateTime("") Set eDate = sDate eDate.AdjustDay(doc.Duration(0) - 1) Set doc.EndDateTime = eDate doc.CalendarDateTime = doc.StartDateTime End Sub
Refresh the current document any time the document is saved. This will ensure that the most current data is displayed to the user any time the form is saved (for instance, when the user selects File - Save).
Sub Querysave(Source As Notesuidocument, Continue As Variant) Source.Refresh End Sub
Setting form properties
Finally, on the form properties dialog, check the "Automatically refresh fields" option in the Options section located on the first tab (see Figure 5). This option will refresh computed fields as you change the data on the appointment form. For example, when the start and end dates are changed, the duration value will automatically update.
Figure 5. Form properties
To complete the form, specify Appointment | Appt as the form name in the Properties dialog. The vertical bar indicates the alias name for the form. Then, save and close the form. (It's good practice to always provide a form name and alias name. All code should then refer to the alias name. This provides greater flexibility to change the form name without impacting existing code and/or view formulas.)
Creating the Calendar view
Most of the application is now complete. The only step remaining is the calendar view to display appointment events. Whenever a database is created, a default view, called "(Untitled)," is automatically generated. Double-click the view to open in Edit mode. Toggle the Properties dialog from Column to View. Set the name to Calendar and alias to Cal.
The next step is to define the columns. Columns are added by single-clicking an existing column header and then selecting the Create - Insert New Column menu options. Then add the following columns.
Column1 is a hidden column and must contain the start date/time value sorted in ascending order. For this project, you will need to select the option to "show multiple values as separate entries." This is the option used to show one document across multiple calendar dates (see Figure 1). In the programmerâs pane, change the display type to Formula and set the column formula to:
REM "Column1 contains the list of start dates as defined in the appointment form"; StartTime := @Time(CalendarDateTime); DateList := @Explode(@TextToTime(@Text(CalendarDateTime) + "-" + @Text(EndDateTime))); @TextToTime(@Text(DateList) + " " + @Text(StartTime))
To set the sort type, select the second tab in the Column properties dialog and click the Ascending radio button option. Also select "Show multiple values as separate entries." To hide the column, select the last tab in the Column properties dialog. Double-click the column1 header to display the Properties dialog. Then select the Hide Column checkbox located on the last tab:
Figure 6. Column properties
Column2 is a hidden column and must contain the event duration in order for the calendar view to display correctly. You will receive an error message if the second column does not contain a valid numeric data value. Set the column formula to:
REM "Column2 contains the duration for each appointment form";
Be sure to hide column2 using the same steps described earlier for column1.
Column3 simply displays the text value for the calendar event. This is the value that will be shown on the actual calendar view. Set the column formula to:
REM "Column3 represents the value displayed on the calendar";
Alternatively, this column could contain the person and subject, or some other combination of data elements and text. You may also want to set the background color for the column to enhance the application usability. This will highlight the entry and help users locate calendar events in the view. To set the background color, select the third tab in the View properties dialog. The Background setting is located in the Entry section.
NOTE: Column titles are not displayed in the calendar view. However, providing a column header name will help you, and other developers, understand the view design and column content.
Setting view objects and properties
The RegionDoubleClick event allows users to double-click a calendar date and automatically launch the new appointment form. After the form is displayed, the start date is populated with the date selected on the calendar. This event also contains a data validation check to see whether or not the selected date is prior to the current date. If the date is in the past, the user receives the prompt, "Date in pastâ¦ Do you want to continue?" If the user select Yes, the "answer" variable is set to 6 (which is a default value automatically set by the Lotus Notes application).
A new appointment form is displayed if either the date is in the future or the user answered Yes to create the record in the past. The following routine is only executed if the user double-clicks a calendar date. (Alternatively, the user can select the New Appointment button, described later in this section, or the Create - Appointment menu options.)
Sub Regiondoubleclick(Source As Notesuiview) Dim doc As NotesDocument Dim workspace As New NotesUIWorkspace Dim uidoc As NotesUIDocument Dim view As NotesView Dim dateTime As New NotesDateTime( "" ) Call dateTime.SetNow 'Display warning if selected date is in the past. If Source.CalendarDateTime < Cdat (dateTime.DateOnly) Then answer% = Messagebox("Date in past... Do you want to continue?", 292, "Continue?") End If 'Create the appointment if date is in the past and user clicked YES, or 'create the appointment if date is in the future. If (answer% = 6) Or (Source.CalendarDateTime >= Cdat (dateTime.DateOnly)) Then Set view = Source.View Set uidoc = workspace.ComposeDocument ( "", "", "Appt" ) Set doc = uidoc.Document doc.StartDate = Source.CalendarDateTime End If End Sub
You may want to consider adding this code to any application that contains a calendar view. Simply change Appt to the appropriate form name. This will make the application more user-friendly and enhance general usability.
Create action buttons for the view
To create the button that allows a user to make new appointments, select Create - Action - Actions. Give the button the title New Appointment and enter the following formula in the programmerâs pane:
REM "Create new calendar events";
To create a button that allows a user to jump to the current calendar date, select Create - Action - Actions. Title the button Today and enter the following formula in the programmerâs pane:
REM "Jump to todayâs calendar date";
Save and close the view.
Congratulations, you have completed the calendar application!
In this article, we have discussed the elements of a simple single-document calendar, and the elements of a recurring event. We have also provided instructions for how to create a simple calendar application. We hope you found this article useful. Let us know what you think, and feel free to suggest other topics for future articles about Lotus Notes and Domino.
- See the Domino Designer product documentation for details about how to use the Domino Designer client.
- The developerWorks: Lotus article series, "Lotus Notes Calendar and Scheduling explained! part 1" and "Lotus Notes Calendar and Scheduling explained! part 2," takes a close look at Notes calendar and scheduling and how its major components work together.