В начало
Статьи
Библиотека
Разное

Вот здесь - новый сайт, заходите немедленно!

kift - Коллекция Интересных Фактов и Теорий

А тут можно поболтать и побухтеть, милости просим:

kift - неизданное

Самоучитель Visual Basic

15. Основы отладки программ.

В этом разделе Вы познакомитесь с понятием отладки и приведете свою программу в рабочий вид. Кроме того, Вы создадите собственную процедуру.

Приготовьтесь к работе, перейдите в окно кода формы frmSheet, в обработчик события txtSheet_Change (как помните, здесь мы закончили работу накануне).

  • Щелкните на вертикальной линейке слева от строки End Sub, чтобы на ней появился красный кружочек:
   

Это – точка останова (BreakPoint), при выполнении кода программа остановится на этой строке и Вы сможете произвести некоторые отладочные действия.

  • Повторным щелчком в том же месте вы можете удалить точку останова.

Запустите программу, откройте окно дневника, нажмите на кнопку « Страничка».

Как видите, программа остановилась при выполнении события Change, хотя мы еще не успели изменить текст!

Дело в том, что событие Change происходит и при загрузке текстового поля (ведь в нем появляется текст, значит – содержимое текстового поля изменяется).

Подобные ситуации могут встречаться в процессе вашей работы, особенно вначале, когда вы еще недостаточно умелы. При этом и помогают средства отладки, самой полезное из которых – точки останова.

  • Если вы наведете курсор на переменную в процедуре, в которой произошла остановка, появится подсказка с информацией о переменной.

  • Продолжить работу программы можно, выполнив команду меню RunContinue (Продолжить), который появится вместо RunStart. Гораздо удобнее, правда, пользоваться «горячей клавишей» [F5] как для запуска так и для продолжения работы.

  • Если вы запустите программу клавишей [F8], то программа будет выполняться «пошагово», выполняя по порядку обработку всех событий. Это также бывает очень удобно при отладке.

Как же нам выйти из ситуации?

Следует, чтобы при первом запуске формы флаг не устанавливался, но устанавливался впоследствии.

Это делается так (исправьте код обработчика события):

Private Sub txtSheet_Change()
Static boolFirst As Boolean
If boolFirst = False Then
boolFirst = True
Exit Sub
End If
boolChange = True
End Sub

Первая строка:

Static boolFirst As Boolean

Слово Static(Статический) используется при объявлении так называемых статических переменных. Эти переменные сохраняют свое значение в промежутках между вызовами процедуры - в отличие от обычных переменных, которые всегда создаются заново при каждом обращении к процедуре.

При создании формы происходит автоматическая инициализация переменных, в т. ч. переменной boolFirst, по умолчанию она получает значение False (старайтесь не полагаться на автоматическую инициализацию, проводимую VB, но здесь у нас нет выхода).

  • В строках

If boolFirst = False Then
boolFirst = True
Exit Sub
End If

сначала происходит проверка значения переменной boolFirst, если ее значение равно False, то ей присваивается значение True и процедура заканчивается.

  • А так как значение boolFirst равно False только сразу после создания формы, то этот блок выполнится лишь один раз.

  • При следующих событиях Change значение boolFirst уже будет равно True (т.к. переменная статическая и ее значение никуда не денется до конца работы программы) и эти строки будут пропускаться.

Теперь в начале обработчика события выгрузки формы-странички проверяйте значение переменной boolChange, и, если она равна True, производите действия для работы с БД. Действия с коллекцией форм-страничек выполняются всегда (т.к. надо удалить страничку с экрана, и, значит, из коллекции страничек).

Private Sub Form_Unload(Cancel As Integer)
Dim varPosition
On Error Resume Next
‘действия при изменении содержимого странички
If boolChange = True Then
With frmDiary.datPrimaryRS.Recordset
varPosition = .AbsolutePosition
.MoveLast
.MoveFirst
Do Until .EOF
If frmDiary.datPrimaryRS.Recordset ("Dates") = Me.Caption Then
frmDiary.datPrimaryRS.Recordset ("Note") = Me.txtSheet.Text
.AbsolutePosition = varPosition
Exit Do
End If
.MoveNext
Loop
End With
End If
‘действия для удаления странички из коллекции
For Each NewSheet In colSheets
 If NewSheet.Caption = Me.Caption Then
 colSheets.Remove Me.Caption
 Exit For
 End If
Next NewSheet
End Sub

Как видите, обработчик получился громоздкий. К тому же, он состоит из двух независимых частей. Безусловно, вы можете оставить как есть, но профессионально будет выполнить разбиение процедуры обработчика на две части. Заодно вы познакомитесь с созданием собственных процедур.

Для создания процедур используется специальное средство VB.

Мы уже неоднократно использовали понятие процедуры без определения ее.

  • Процедура – логически завершенная часть программы, выполняющая какое-то действие.

  • Отличие процедуры от функции в том, что она не оповещает вызвавший код о результатах выполнения, то есть – не возвращает значения.

Приготовьтесь к работе. Откройте окно кода формы frmDiary.

  • Выполните команду меню ToolsAddProcedure... (Добавить Процедуру).

Появится окно Add Procedure:

   

Строка Name – для ввода имени процедуры, переключатели группы Type (Тип) определяют тип создаваемого блока: Sub (Процедура), Function (Функция), Property (Свойство), Event (Событие). Переключатели группы Scope (Область Видимости) определяют область видимости процедуры.

В поле Name введите имя будущей процедуры RefreshDB (ОбновитьБД).

  • Переключатель Type оставьте в положении Sub.

  • Переключатель Scope переведите в положение Private (Частная).

Область видимости Private для процедуры означает, что обратиться к этой процедуре можно будет только из модуля, в котором она находится.

Щелкните OK.

Как видите, появилась заготовка процедуры:

Private Sub RefreshDB()

 

End Sub

Конечно, это можно было сделать и вручную. Но свойства Property и события Event удобнее создавать, используя эту возможность VB.

Перенесите часть кода из обработчика события Form_Unload в эту процедуру, чтобы она приняла вид:

Private Sub RefreshDB()
Dim varPosition
With frmDiary.datPrimaryRS.Recordset
varPosition = .AbsolutePosition
.MoveLast
.MoveFirst
Do Until .EOF
If frmDiary.datPrimaryRS.Recordset ("Dates") = Me.Caption Then
frmDiary.datPrimaryRS.Recordset ("Note") = Me.txtSheet.Text
.AbsolutePosition = varPosition
Exit Do
End If
.MoveNext
Loop
End With
End Sub

Соответственно, удалите этот код из обработчика события.

А на месте этого кода в обработчике выгрузки формы просто вызовите созданную процедуру:

Private Sub Form_Unload(Cancel As Integer)
On Error Resume Next
If boolChange = True Then
‘вот оно!
RefreshDB
End If
For Each NewSheet In colSheets
 If NewSheet.Caption = Me.Caption Then
 colSheets.Remove Me.Caption
 Exit For
 End If
Next NewSheet
End Sub

Как видите, код еще более упростился.

Взгляните на участок:

If boolChange = True Then
	RefreshDB
End If

После проверки условия происходит лишь одно действие.

Этот участок можно еще более упростить (сделайте это):

If boolChange = True Then RefreshDB

Сохраните проект и испытайте программу.

У вас может возникнуть вопрос: «Мой компьютер достаточно мощный, и, даже при обязательном сохранении всех страничек я не замечаю разницы в производительности. К чему возиться со всеми этими проверками?»

Отлично. Заменим совсем немного кода и получим практическую пользу из проверки.

Замените строку

If boolChange = True Then RefreshDB

на блок

Dim varAnswer
If boolChange = True Then
varAnswer = MsgBox("Текст странички изменен." _
& vbCrLf & "Сохранить его?", _
vbYesNoCancel Or vbQuestion, _
"Закрытие странички")
 If varAnswer = vbYes Then
 RefreshDB
 ElseIf varAnswer = vbCancel Then
 Cancel = 1
 Exit Sub
		 End If
End If

Если значение флага boolChange равно True, то мы начинаем довольно сложный блок проверки, определяющий, следует ли сохранять сделанные изменения.

В начале этого блока мы объявляем вспомогательную переменную varAnswer. Затем вызывается функция MsgBox.

  • Первый параметр функции MsgBox (англ. MessageBox – Окно Сообщения) – текст, который будет выводиться в окне сообщения. В нашем случае это строка "Текст странички изменен." & vbCrLf & "Сохранить его?". Слово vbCrLf указывает, что в этом месте следует перейти на новую строку.

  • Второй параметр vbYesNoCancel Or vbQuestion состоит из двух: vbYesNoCancel (ДаНетОтменить) и vbQuestion(Вопрос). Слово Or (Или) – логическая операция, стандартно используемая в VB для комбинации нескольких значений параметров в одно. Параметр vbYesNoCancel заставляет функцию выводить соответствующую комбинацию кнопок. Другие варианты: vbOKOnly (ТолькоOK), vbOKCancel (OKОтменить), vbAbortRetryIgnore (ПрерватьПовторитьПропустить), vbYesNo (ДаНет), vbRetryCancel (ПовторитьОтменить). Параметр vbQuestion выводит на окошке сообщения знак вопроса. Другие значения: vbExclamation (Восклица­ние), vbInformation (Информация), vbCritical (Предупреждение).

Не забудьте впоследствии поэкспериментировать с этими значениями, по очереди подставляя их вместо указанных.

  • Третий параметр функции MsgBox – заголовок выводимого окошка.

Возвращаемое функцией MsgBox значение зависит от второго параметра.

  • В нашем случае, при параметре vbYesNoCancel функция сможет вернуть значения vbYes, vbNo и vbCancel.

  • Аналогично и для других параметров – возвращаются значения, «составляющие» параметр.

Понятие «параметр» мы также использовали без пояснения, что же это такое.

  • Параметр – значение, получаемое процедурой или функцией при вызове и определяющее какие-то аспекты ее работы.

Параметры, как частный случай переменной, имеют те же типы, что и переменная. Объявлять типы параметров надо обязательно.

Общий синтаксис параметров:

Sub MySub (par1 As Long, par2 As String)

То есть, список параметров заключается в скобки и идет за именем процедуры. Объявления параметров разделяются запятыми.

При вызове этой процедуры параметры будут переданы ей и могут использоваться в работе самой процедуры. Параметр может изменяться в процессе работы процедуры, а по завершению вызывающий код может определять значения изменившихся параметров – это называется «возврат значений в параметрах».

Далее идет блок проверки значения, возвращенного функцией:

If varAnswer = vbYes Then
	 RefreshDB
ElseIf varAnswer = vbCancel Then
 Cancel = 1
 Exit Sub
End If
  • Если мы подтвердили обновление БД и сохранение изменений (вариант vbYes), происходит вызов функции RefreshDB, которую мы создали раньше. Если на окошке мы выбрали кнопку « Отмена» (вариант vbCancel), то произойдет следующее.

  • Обратите внимание, что у обработчика события Form_Unload есть параметр по имени Cancel (Отмена). Если внутри обработчика этому параметру присвоить значение больше 0, то программа не выгрузит форму. Если же произошел выбор vbNo, то этот блок будет пропущен, форма выгрузится без сохранения изменений.

Заметьте также, что в коде один блок If... Then находится внутри другого. Это называется вложенностью блоков. Позволяется делать так с блоками циклов и проверки условий.

Процедуру вкладывать в другую процедуру нельзя!

Запустите программу.

К сожалению, в программе осталась еще одна неприятная особенность. В поле « Дата» формы дневника вы можете ввести повторяющееся значение даты, и это приведет к ошибке.

Для устранения ее вам придется :

  1. Сохранить позицию указателя в наборе записей.

  2. Преобразовать текст из текстового поля txtFields(0) в формат даты.

  3. В цикле пройти весь набор записей, проверяя, нет ли уже такого же значения.

  4. Если такое значение даты уже есть – обрабатывать внештатную ситуацию, если нет – присваивать значение из текстового поля записи БД.

  5. Восстановить позицию указателя в наборе записей.

Все эти операции мы уже делали. При этом можно использовать обработчик события текстового поля LostFocus(ПотеряФокуса), возникающего при переходе к другому контролу на форме (или к самой форме).

Эти исправления предоставляется сделать Вам самостоятельно, как «выпускной экзамен» нашего курса. Поверьте, в настоящей книге есть информация, требуемая для этого.

Удачи!

Вопросы

  1. Что такое точка останова? Для чего и как она применяется?

  2. Как в процессе отладки узнать текущее значение переменной?

  3. Что значит слово Static в объявлении переменной?

  4. Что такое автоматическая инициализация?

  5. Каким образом возможно создать процедуру?

  6. Для чего Вам может понадобиться создавать процедуры?

  7. Опишите синтаксис функции MsgBox.

Задания

  1. Законспектируйте раздел.

  2. Добавьте комментарии в код.

Hosted by uCoz