Hi Keenan
I have posted about three times in the last few days, but I can't see them
in the newsreader. Please forgive me is a whole lot of duplicates turn up.
WARNING: There is a lot to digest in this message, so please persevere to
the end
If you store the weeks as a string then you will have a devil of a job
detecting clashes, which I would think was of paramount importance for a
timetabling system.
For example, the following two records clearly clash in week 15:
Thu - 08:00AM - 12:00PM - ABC - ABC01 - MR. SMITH - 101 - 14,15,16,19
Thu - 11:00AM - 01:00PM - XYZ - XYZ09 - MRS JONES - 101 - 13,15,17
But how can you write code to detect this condition?
Also, would you not often have a situation where the same class is in the
same room for the same time slot several days of the week - say Mon, Wed,
Fri?
I would remove the day and week from the table and add an ID field, then add
two more tables for BookingDays (ID and DayNumber) and BookingWeeks (ID and
WeekNumber).
Also, assuming each class is always taught by the same teacher, remove the
Course, Module and Teacher into a separate Classes table.
This leaves you with:
Classes:
ClassID (autonumber)
Course
Module
Teacher
Bookings:
BookingID (autonumber)
Room
StartTime
EndTime
ClassID
BookingDays:
BookingID
DayNumber
BookingWeeks:
BookingID
WeekNumber
Days:
DayNumber (1=Monday,2=Tuesday,etc)
DayName
Weeks:
WeekNumber
WeekDate (date of Monday)
Just to clarify, your example class booked for Mon-Wed-Fri in weeks
14,15,16,19 would have the following records:
Classes:
123, ABC, ABC01, MR. SMITH
Bookings:
99, 101, 08:00AM, 12:00PM, 123
BookingDays:
99, 1
99, 3
99, 5
BookingWeeks:
99, 14
99, 15
99, 16
99, 19
This gives you the flexibility to build all sorts of queries - for example,
the following query will list all the starting and ending dates *and* times
and room numbers for every session of a given class:
SELECT Bookings.ClassID,
Bookings.Room,
[WeekDate]+[Days].[DayNumber]-1+[StartTime] AS StartDateTime,
[WeekDate]+[Days].[DayNumber]-1+[EndTime] AS EndDateTime
FROM (((Bookings INNER JOIN BookingDays
ON Bookings.BookingID = BookingDays.BookingID)
INNER JOIN BookingWeeks
ON Bookings.BookingID = BookingWeeks.BookingID)
INNER JOIN Days ON BookingDays.DayNumber = Days.DayNumber)
INNER JOIN Weeks ON BookingWeeks.WeekNumber = Weeks.WeekNumber
WHERE (Bookings.ClassID=123);
Now, the problem is creating a user interface that makes it easy to append
or delete records in your BookingDays and BookingWeeks tables simply by
ticking/unticking checkboxes.
The trick is to create a query that lists ALL the days (or Weeks) with a
calculated yes/no field to indicate if the corresponding BookingDays (or
BookingWeeks) record is present for the given BookingID:
SELECT Days.DayName, Days.DayNumber,
[Days].[DayNumber] In (Select DayNumber from BookingDays
where BookingID=Nz(Forms!frmBookings!BookingID,0)) AS Selected
FROM BookingDays RIGHT JOIN Days
ON BookingDays.DayNumber = Days.DayNumber;
This query will list all the days with their numbers, and a third column
(Selected) will show show True (-1) or False (0) depending on whether a
BookingDays record exists for the given day and the BookingID from the form
frmBookings.
You could use this query as the RecordSource of a popup "Day Selector" form
with a textbox bound to DayName and a checkbox bound to Selected. Both
these controls should be disabled and locked.
Now, the coup de grace...
You place a transparent command button over the checkbox named cmdToggle.
This command button either creates or deletes a record as required, and
requeries the form:
Private Sub cmdToggle_Click()
Dim sSql As String
On Error GoTo ProcErr
If Me.Selected Then
sSql = "Delete from BookingDays " _
& " where BookingID=Forms!frmBookings!BookingID " _
& " and DayNumber=" & Me.DayNumber
Else
sSql = "Insert into BookingDays (BookingID, DayNumber) " _
& "values (Forms!frmBookings!BookingID, " _
& Me.DayNumber & ")"
End If
CurrentDb.Execute sSql, dbFailOnError
Me.Requery
ProcEnd:
On Error Resume Next
Exit Sub
ProcErr:
MsgBox Err.Description, vbExclamation, "Error #" & Err.Number
Resume ProcEnd
End Sub
Finally, you can write two functions to return comma separated lists of days
(or weeks) given the BookingID passed as an argument. These generated
strings cannot be edited, of course, but they can be used to give a simple
display of the days and weeks that a room is booked.
I know there is a lot of information to digest here, particularly if you are
a beginner, but I think it will be worthwhile considering this approach to
avoid insurmountable problems further down the track.