Итак, на предыдущем уроке мы нашли баги (от слова Bug - жук) в нашей программе, т.е. недочёты (ошибки) . От этих багов нужно избавиться. Посмотрим причину возникновения ошибок. Запустите программу. Ничего не вводя в поля нажмите на кнопку. Visual Basic выдаст окно, в котором скажет: "Type mismatch", т.е. ошибка в типах. В окне доступны 3 кнопки:
End - завершить приложение
Debug - показать место возникновения ошибки, чтобы мы смогли от неё избавиться
Help - вызвать справку о возникшей ошибке.
Нажмите Debug. Visual Basic покажет вам причину возникновения ошибки:
Жёлтым цветом выделена строка - причина ошибки. Если навести курсор мыши на имя переменной, то всплывёт подсказка, в которой Visual Basic сообщит нам её значение. Такая возможноть доступка только в режиме Debug. Текущий режим можно узнать из заголовка окна Visual Basic. Например:
в режиме проектировки интерфейса это строка:
Имя_Проекта - Microsoft Visual Basic [design]
при запущенном приложении:
Имя_Проекта - Microsoft Visual Basic [run]
в режиме Debug:
Имя_Проекта - Microsoft Visual Basic [break]
Наведите мышкой на txtParamA.Text. VB сообщит о том, что значение текстового поля txtParamA.Text = "" (пустым кавычкам, или по другому - пустая строка). Здесь можно догадаться, почему происходит ошибка несовпадения типов. Ведь переменная paramA должна хранить вещественное число, а здесь мы пытаемся присвоить ей строковое значение - "". Если бы paramA имела тип String, или в txtParamA.Text была бы строка - число ("123") - ошибка бы не возникла. А здесь Visual Basic просто не может сам конвертировать строку "" в число типа Double. Мы должны найти возможное решение ошибки. Давайте заглянем в раздел vbhelprus. Найдём там функцию Val. О! Это как раз то, что нужно! Давайте изменим код:
paramA = txtParamA.Text
paramB = txtParamB.Text
paramC = txtParamC.Text
На код:
paramA = Val(txtParamA.Text)
paramB = Val(txtParamB.Text)
paramC = Val(txtParamC.Text)
Теперь ошибок несовпадения типов быть не может, т.к. функция Val при любом параметре возвратит число, а сама функция Val никогда не вызовет ошибки, хотя ... но это уже на совести разработчиков VB
Проанализируем полученный результат. Что изменилось после того, как мы вставили функцию Val? Теперь мы знаем что переменным paramA, paramB и paramC в любом случае присвоится число. Но вот какое число? Ведь если мы введём в поля нули, то и переменные будут содержать нули! Также, если в поля мы введём !буквы!, то переменные также будут содержать нули. Значит нужно сделать проверку на содержание в переменных нулей. Запустите программу и введите в поля нули (или буквы) и нажмите кнопку. Visual Basic выдаст окно:
Нажимаем Debug и вот что видим:
Причина ошибка заключается в невозможности деления на 0, а paramA у нас как раз и равен 0. К тому при нулевых коэффициентах квадратное уравнение решается гораздо проще (например, если c=0, то x вынесем за скобку, ну а дальше всё просто). Избавимся от этого недоразумения. Для этого, вставим после присвоения значения свойства Text переменным ещё одну проверку - проверку на содержание нулей в переменных:
If paramA = 0 Or paramB = 0 Or paramC = 0 Then
MsgBox "Нули в качестве коэффициентов не допускаются!", _
vbCritical
Exit Sub
End If
Символ "_" используется в том случае, когда вы хотите перенести часть выражения на другую строчку. В данном случае мы переносим константу vbCritical.
Здесь мы проверяем переменные на содержание в них нулей. В принципе, можно было бы проверить не переменные, а сами тектовые поля (If Val(txtParamA.Text)=0 Then....). Это уже дело вкуса. Всё равно, результат одинаков.
Второй баг побеждён! Можно запускать программу и решать уравнения

.
Итоговый код программы:
Private Sub cmdCalculate_Click()
' объявляем переменные
Dim paramA As Double
Dim paramB As Double
Dim paramC As Double
Dim x1 As Double
Dim x2 As Double
Dim D As Double
paramA = Val(txtParamA.Text)
paramB = Val(txtParamB.Text)
paramC = Val(txtParamC.Text)
If paramA = 0 Or paramB = 0 Or paramC = 0 Then
MsgBox "Нули в качестве коэффициентов не допускаются!", _
vbCritical
Exit Sub
End If
D = (paramB * paramB) - (4 * paramA * paramC)
If D > 0 Then
x1 = (paramB + Sqr(D)) / (2 * paramA)
x2 = (paramB - Sqr(D)) / (2 * paramA)
lblD.Caption = "Дискременант: " & D
lblX1.Caption = "Корень №1: " & x1
lblX2.Caption = "Корень №2: " & x2
ElseIf D = 0 Then
x1 = paramB / (2 * paramA)
x2 = x1
lblD.Caption = "Дискременант: " & D
lblX1.Caption = "Корень №1: " & x1
lblX2.Caption = "Корень №2 = Корню №1"
ElseIf D <0>Breakpoint. Замечание: такую точку нельзя ставить на строчке с объявлением переменной.
Поставьте точку как показано на рисунке и запустите программу. Введите следующие данные в качетсве параметров: a = 3, b = -6, c = 2. Нажмите на кнопку "Решить!". Visual Basic остановит выполнение программы точно на той строчке, на которой стоит брикпоинт. Теперь VB в режиме Debug. Вы можете просматривать значения переменных, наводя на них курсор мыши и выполнять программу по шагам. Чтобы выполнить одну команду, нужно нажать F8 или Shift+F8. Отличие этих двух команд заключается в том, что при нажатии F8 на строчке с вызовом процедуры Visual Basic войдёт в эту процедуру и вы сможете продолжить пошаговое выполнение в этой процедуре до строчки End Sub, где VB вернёт вас на то место, где произошёл вызов. Если же нажать Shift+F8, то Visual Basic выполнит процедуру, но не будет заходить в неё для пошаговой трассировки.
Теперь потрассируйте программу. Проследите за тем, как изменяются значения переменных при присвоении им значения. Теперь откройте окно Locals Window. (меню View->Locals Window). В этом окне отображаются значения всех локальных переменных:
Здесь изображены все наши локальные переменные. Их 6 штук. "А вот что такое Me?" - спросите вы. Никак "Millenium"?

Нет, "Me" - это тоже зарезервированное слово Visual Basic. Оно указывает на текущую форму. В своей программе вы можете обращаться к своей форме через Me. Например, если написать
Me.Hide
То с экрана скроется та форма, в коде которой написан этот код. (простите за каламбур).
Также можно заметить значок "+" слева от "Me". При нажатии на него произойдёт раскрытие списка со всеми дочерними объектами формы. Там же будут находится все элементы управления помещённые на форму, а также все глобальные переменные уровня этой формы.
Заметьте, что окно Locals - плавающее , и при двойном щелчке по заголовку окна оно "пристыкуется" в среду VB. При очередном двойном щелчке окно "отстыкуется".
Дотрассируйте (т.е. пройдите пошагово) программу до конца. Закройте её.
Обработка других ошибок
Независимо от того, насколько качественно написано приложение, никогда нельзя полностью исключать возможность возникновения ошибки в программе. Вы наверняка видели, да нет, точно видели такое окошко Windows: "Программа выполнила недопустимую операцию и будет закрыта...". Т.е. возникла исключительная ситуация, и Windows, не зная как можно обойти ошибку, выдаёт "общее" окно для всех таких ошибок. Так вот и в ваших программах тоже может возникнуть такая исключительная ситуация. Причин для этого ооочень много. Например, у пользователя программой сбои с жёстким диском, или глючит операционная система, или вирус удалил нужный вам файл и т.д. и т.п. В общем, в таких ситуациях желательно сообщить пользователю о том, что возникла ошибка и спокойно выйти/продолжить программу. О том как это сделать и будет рассказано далее.
В Visual Basic существуют несколько глобальных объектов. Это Err, Printer, Screen, Clipboard и App. Эти объекты доступны в любом месте программы. В данном случае нас интересует только объект Err. О назначении и использовании других объектов, возможно, расскажу в статьях.
Объект Err содержит в себе 6 свойств и 2 метода. Этот объект содержит информацию о последней произошедшей ошибке. Вот наиболее важные свойства:
Err.Number
Err.LastDllError
Эти свойства содержат номер последней произошедней ошибки. Первое - содержит номер ошибки самого Visual Basic. Второе - номер ошибки при работе с API функциями. Пока нам понадобится только первое свойство.
Visual Basic располагает оператором, с помощью которого можно контролировать ход программы при возникновении ошибок. Это оператор On Error. Он имеет несколько видов:
On Error GoTo МЕТКА
On Error Resume Next
On Error GoTo 0
Первый оператор позволяет указать Visual Basic метку (номер строки) на которую передастся управление программы при возникновении ошибки. Рассмотрим пример использования этого оператора:
Private Sub Command1_Click()
Dim myString As String
On Error GoTo ERRH
myString = "ERROR HANDLING WITH VB IS COOL"
MsgBox Mid(myString, 0, 1) '<--- здесь ошибка (#)
Exit Sub '<--- досрочно выходим, если нет ошибок
ERRH: '<--- метка
MsgBox Error(Err.Number) '<выводим>Break On All Errors. Теперь Visual Basic всегда будет переводить программу в режим Debug при возникновении любой ошибки (естесственно, это не касается логических ошибок, на них не действует ни один оператор

.
Давайте теперь посмотрим на оператор Оператор On Error Resume Next. Его можно использовать тогда, когда вы просто хотите подавить ошибку. Т.е. продолжить программу без всяких предупреждений. Замените в нашем примере On Error GoTo ERRH на On Error Resume Next и посмотрите что прозойдёт. Вы не увидите никаких признаков ошибки. Код просто будет продолжен со следующей строчки. В нашем случае - это Exit Sub.
Оператор On Error GoTo 0 удаляет все ранее установленные обработчики ошибок, т.е. разрешает Visual Basic использовать его собственный обработчик ошибок (При возникновении которой, он закроет приложение. А это иногда совсем не к чему).
За более подробной информацией можно обратиться к справочникам.