Проверка данных перед их сохранением
Провести в приложении TimeTrack дополнительную проверку данных. Для примера остановимся на форме Projects (Проекты). Двумя ключевыми моментами этой формы являются даты начала и планируемого завершения проекта. Очевидно, что дата начала должна предшествовать дате конца. В предлагаемом практикуме будет показано, как изменить логику программы для проверки совместимости значений перед тем, как их поместить в базу данных. Естественно, для этой цели можно использовать и проверку на уровне таблицы, однако в этом случае данные не будут проверяться до тех пор, пока пользователь не попытается сохранить всю запись.
Чтобы добавить описанную выше проверку корректности, откройте форму Projects в режиме конструктора и перейдите к модулю формы. Введите следующий фрагмент программы:
Private Sub StartDate_Exit(Cancel As Integer)
'Проверка логичности дат
If DatesAreBad Then
MsgBox "Дата начала должна предшествовать дате завершения", _
vbCriticalCancel = True
End If
End Sub
Private Sub EstimatedEndDate_Exit(Cancel As Integer)
'Проверка логичности дат
If DatesAreBad Then
MsgBox "Дата начала должна предшествовать дате завершения", _
vbCriticalCancel = True
End If
End Sub
Private Function DatesAreBad() As Boolean
'Проверка того, что дата начала предшествует дате завершения
On Error GoTo HandleErr
'Все в порядке
DatesAreBad = False
Dim dtSDate As Date
Dim dtEDate As Date
'Проверка на содержание в текстовых полях дат
dtSDate = CDate(StartDate.Value)
dtEDate = CDate(EstimatedEndDate.Value)
'Проверка на существование проблем
If dtEDate - dtSDate < 0 Then
DatesAreBad = True
End If
ExitHere:
Exit Function
HandleErr:
'В случае любой ошибки считаем, что даты некорректны
DatesAreBad = True
Resume ExitHere
End Function
В этом фрагменте программы введена обработка событий Выход (Exit) двух полей – даты начала проекта и даты его завершения. Следует отметить, что изменение значения любого из них может вызвать проблему. Так как проверка проводится в двух полях, то имеет смысл вынести саму логику проверки в отдельную функцию и вызывать ее из процедур обработки событий. В самой этой функции вычисляется разность между датами завершения и начала. Если результатом является положительное число, функция возвращает False, в противном случае – True.
В каждой из процедур обработки событий, если функция DateAreBad возвращает True, то выполняются следующие действия. Вначале выводится сообщение о характере ошибки, а затем значение аргумента Cancel устанавливается в True, что обяжет пользователя ввести в поле допустимое значение.
Создание собственного объекта
В дополнение к использованию объектов из существующих библиотек, язык VBA позволяет создавать собственные классы и объекты. В практическом задании приведен пример создания класса, обобщающего недельный график работы. Для начала выберите в меню пункт Insert→Class Module (Вставить→Модуль класса). Открывшееся окно модуля класса будет выглядеть практически так же, как и окно обычного модуля; в то же время в окне свойств вы увидите отличающийся список параметров. Задайте в окне свойств имя нового Модуля – Time Week.
Теперь введите текст описания создаваемого класса:
Option Compare Database
Option Explicit
' Описываем несколько простых свойств
Public MondayHours As Integer
Public TuesdayHours As Integer
Public WednesdayHours As Integer
Public ThursdayHours as Integer
Public FridayHours As Integer
Public SaturdayHours As Integer
Public SundayHours As Integer
' Описываем свойство, возвращаемое частной переменной
Private strEmployeeName As String
Public Property Let EmployeeName(NewName As String)
strEmployeeName = NewName
End Property
Public Property Get EmployeeName() As String
EmployeeName = strEmployeeName
End Property
' Вычисление трех свойств, доступных только для чтения
Public Property Get TotalHoursO As Integer
TotalHours = MondayHours + TuesdayHours + _
WednesdayHours + ThursdayHours + FridayHours + _
SaturdayHours + SundayHours
End Property
Public Property Get RegularHours() As Integer
If TotalHours < 40 Then
RegularHours = TotalHours
Else
RegularHours = 40
End If
End Property
Public Property Get OvertimeHoursО As Integer
If TotalHours > 40 Then
OvertimeHours = TotalHours - 4 0 Else
OvertimeHours = 0
End If
End Property
' Описываем простой метод
Public Function PrintTimeReport()
Debug.Print "Понедельник "& MondayHours
Debug.Print "Вторник "& TuesdayHours
Debug.Print "Среда "& WednesdayHours
Debug.Print "Четверг "& ThursdayHours
Debug.Print "Пятница "& FridayHours
Debug.Print "Суббота "& SaturdayHours
Debug.Print "Воскресенье "& SundayHours
End Function
В этом тексте программы продемонстрировано два способа описания свойств и одно описание метода. Простейшим способом создания свойства в классе является обычное объявление общей переменной – все такие переменные видимы как свойства класса.
Более сложным способом создания свойства является написание процедуры свойства. Свойство EmployeeName вставлено в класс с помощью процедур property Let и Property Get. Когда некто присваивает свойству значение, вызывается процедура Property Let, которой это значение передается. Когда пользователь пытается прочитать значение свойства, вызывается процедура Property Get, которая его и возвращает. В нашем примере значение свойства EmployeeName хранится во внутренней частной переменной; в данном случае процедура свойства передает это значение общей переменной.
Остальные три свойства (TotalHours, RegularHours и OvertimeHours) внедрены с помощью процедур Propoerty Get – соответствующих процедур Property Let для них не создавалось. Таким образом, эти свойства доступны только для чтения, так как средств для присвоения им значения извне просто не существует.
Процедура PrintTimeReport является методом класса. Любая объявленная в модуле класса общая функция или процедура автоматически становится методом класса.
После сохранения этой программы вы можете использовать класс TimeWeek в своих целях. Вот пример вызова этого класса:
Sub UseTimeWeek()
`Пример использования класса TimeWeek
Dim tw As New TimeWeek
tw.MondayHours = 8
tw.TuesdayHours = 9
tw.WednesdayHours = 8.5
tw.ThursdayHours = 8
tw. FridayHours = 7.5
tw.SaturdayHours = 4
tw.SundayHours = 3.5
Debug.Print "Рабочее время: " & tw.RegularHours
Debug.Print "Сверхурочные: " & tw.OvertimeHours
Debug.Print "Итого: " & tw.TotalHours
Debug.Print " "
tw.PrintTimeReport
End Sub
А вот результат вызова процедуры UseTimeWeek в окне Immediate:
Рабочее время: 40
Сверхурочные: 9
Итого: 49
----------------
Понедельник 8
Вторник 9
Среда 8
Четверг 8
Пятница 8
Суббота 4
Воскресенье 4
По окончании тестирования свойств и методов реализованного класса в окне Immediate необходимо разработать форму для демонстрации свойств и методов реализованного класса.