Разное

Vba обработка исключений: Обработка ошибок в коде VBA — Макросы и программы VBA — Excel — Каталог статей

Содержание

Обработка ошибок в коде VBA - Макросы и программы VBA - Excel - Каталог статей

Поискав по рунету материал на тему обработки ошибок в VBA, не увидал на первых двух страницах результатов поиска чего-то, что мне понравилось. Может плохо смотрел, но решил написать на эту тему свою статью.

Простите, но - немного словоблудия 🙂

Ошибки в программе

Ошибки времени исполнения программы возникают, когда среда программирования не может выполнить то, что вы хотите. Таких ситуаций может быть много. Например:

  1. Вы обращаетесь к объекту по имени, а объекта с таким именем в коллекции нет

  2. Вы хотите выделить ячеку на одном листе, а этот лист в данный момент не является активным (типичнейшая ошибка новичков в Excel VBA)

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

  4. Вы ссылаетесь на элемент массива, который находится за пределами его границ.

  5. Вы пытаетесь присвоить переменной значение, которое оно не может хранить. Например, переменной типа Long нельзя присвоить строковую константу или переменной типа Integer присвоить знанчение превышающее число 32767.

На любую из этих и сотни других ситуаций среда выполнения реагирует стандартно - прерывает ход выполнения программы на том операторе, где возникла ошибка или, как ещё принято говорить, исключение. На экран выводится информация о возникшей ошибке и предлагаются стандартные варианты для продолжения работы:

  • Continue (продолжить) - этот пункт во время возникновения ошибки всегда не активен. Он активен, когда по ходу выполнения программы вы использовали оператор Stop. Кстати это очень полезный оператор для отладки программы.

  • End (завершить) - завершение исполнения программы

  • Debug (отладка) - переход в режим отладки, в котором можно посмотреть, на каком операторе возникла ошибка, что содержат переменные, можно даже перетащить жёлтую полоску, подсвечивающую текущий оператор, назад, и модифицировать знанчение переменных через окно Immediate window (впрочем это экзотика). В общем случае кнопка Debug позволяет посмотреть, где случилась ошибка и попытаться понять почему так случилось.

Если вы - автор программы, в которой случилась ошибка, то вы, должно быть, в начале будете рады увидеть подобное окно, ибо только так вы сможете отловить основные ошибки, скрытые в вашем коде. Однако, если эту ошибку видит пользователь, то для него это, мягко говоря, безрадостное и малопонятное зрелище. Ещё хуже, если за эту программу вам заплатили деньги. Поэтому в среде худо-бедно профессиональных программистов принято предусматривать обработку ошибок в своих программах.

Почему вообще в коде возникают ошибки?

  1. Много ошибок во время написания кода возникает по невнимательности или не совсем адекватного понимания того, что делаешь. Таких ошибок, как правило, очень много, особенно у начинающих программистов, но эти ошибки довольно легко отловить и исправить, так как, пока вы их не исправите, ничего не работает. Ну, например, вы должны извлечь данные из 5-го столбца, а вы извлекаете из 6-го, а их там банально нет. Ясно, что вы это очень быстро заметите.

  2. Вторая группа ошибок - это ошибки оптимиста. Когда программа написана в целом правильно, но алгоритм не готов к ударам судьбы в виде неожиданных действий со стороны пользователя, ошибок ввода-вывода (вы рассчитывали считать данные из файла, а файла с таким именем не оказалось, либо он заблокирован другим приложением), особенностей конфигурации компьютера (разные версии ОС или офиса, которые в некоторых мелочах отличаются).

  3. Тонкие логические ошибки. Чем сложнее программа, тем больше шансов, что модель задачи в вашей голове, ваша программа и реальность не совсем согласованы между собой. Пока вы не достигните достаточного погружения в задачу вы такие ошибки не найдёте и не исправите. Порой на это уходит много времени. Но это характерно для сложных задач.

  4. Ошибки на стыке вашего приложения и сервисов ОС, приводящие к неожиданным крахам приложения. Такого вообще возникать не должно, но как мы понимаем, и ОС и офис содержат ошибки, да и вы (что более вероятно) можете пользоваться системными вызовами не правильно. Подобные ошибки - сущий кошмар, особенно когда они проявляются лишь на некоторых конфигурациях, при определенных условиях, их трудно поймать и надёжно воспроизвести.

Задачи механизмов обработки ошибок

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

  2. Информирование. Мало обработать ошибку и предотвратить завершение программы. Надо ещё и адекватно проинформировать пользователя о причинах нестандартного поведения программы. Частно причиной ошибок в программе являются некорректные действия пользователя, поэтому важно сообщать ему о них.

  3. Защита данных от повреждения. Программа обязана защищать от непреднамеренных повреждений результаты своей или пользовательской работы. Деструктивные действия должны быть снабжены соответствующими предупредительными диалоговыми окнами. Часто ошибка, не обработанная должным образом может повредить нужные данные.

Файл примера

Скачать

Код без обработки ошибок

Вот простой пример с потолка. Если вызвать Example_00, то она прекрасно отработает без ошибок и вернёт это:

В функцию GetCalories передаётся строка с блюдом, а она должна вернуть его калорийность, сверившись с таблицей в A1:B7.

Давайте поищем слабые места в этом коде. Первое, что должно прийти в голову - если мы ищем, то, что произойдёт, если мы не найдём? А произойдёт, конечно же, ошибка. Её инициирует метод Match.

Ещё одно слабое место этой подпрограммы: функция возвращает вещественный тип Double, и даже, если поиск оказался удачным, то в Cells(intRow, 2) может случайно находиться текстовая строка, а потому, когда вы числовому типу попытаетесь присвоить строковый тип, также произойдёт ошибка. И, если вы второй ошибки сможете избежать за счёт дополнительного оператора if с проверкой через IsNumber(), то избежать первой ошибки таким способом нельзя. Что же делать? А вот тут на сцену выходят операторы обработки ошибок.

Есть 2 подхода к обработке ошибок: автономный подход и выносной. Эти термины я придумал только что, чтобы проще было их обсуждать.

Автономный подход

Смысл автономного подхода в том, чтобы не выносить сор из избы. Если в подпрограмме возникла ошибка, то мы должны предположить, на каком месте она возникнет и поджидать её там с дубиной. С ошибкой, в этом случае, разбираются обычно в операторе, идущем сразу после потенциально опасного места. Давайте смотреть, как это может выглядеть:

Итак, что тут сделано:

  1. Сразу после объявления функции GetCalories_v1 идёт оператор on error resume next, который в случае возникновения в каком-либо месте ошибки, предписывает VBA просто передавать управление на следующий оператор, идущий после ошибочного.

  2. Мы объявили переменные. Необъявленные переменные получают тип Variant и значение по умолчанию Empty. Объявленные переменные числовых типов инициируются нулём, строковые - пустой строкой, то есть я наперёд знаю, что они содержат, а это хорошо для обработки ошибок.

  3. На вызове метода WorksheetFunction.Match у нас возникает ошибка, так как искомого значения в таблице нет. А это, между прочим, был оператор присваивания ( = ). Прежде, чем левой части оператора присваивания (intRow) что-то будет присвоено, необходимо вычислить правую часть оператора присваивания (WorksheetFunction.Match...), а поскольку в процессе этого вычисления возникает ошибка, то переменная intRow остаётся такой, какой была! А, как я уже сказал, VBA автоматически её инициализирует нулём до начала исполнения подпрограммы. Получается, что, если в этом операторе возникнет ошибка, то в intRow будет ноль. Если ошибки во время поиска не возникнет, то ноля там не будет ни при каких раскладах, так как строки на листе нумеруются с единицы.

  4. И вот этот ноль мы и контролируем, добавляя оператор If. Если intRow больше нуля, то WorksheetFunction.Match отработала штатно, а если нет - то работу подпрограммы надо прерывать, но об этом чуть позже.

  5. Далее мы помним, что Cells(intRow, 2) может теоретически вернуть строковое значение, которое вызовет ошибку Type missmatch при присвоении переменной типа Double (GetCalories_v1), поэтому мы вставляем дополнительную проверку промежуточной переменной varTemp тому, что она числовая. И если это так, то присваиваем GetCalories_v1 значение из varTemp.

  6. В случае возникновения любой ошибки внутри GetCalories_v1 она просто вернёт ноль. Почему ноль? Потому что переменная GetCalories_v1 тоже инициализируется нулём и об этом не надо заботиться, а в случае ошибки она останется в неприкосновенности.

  7. Соответственно родительский код (в нашем случае его роль играет процедура Example_01) должен проверить, а не вернёт ли GetCalories_v1 ноль, и быть готовым к этой ситуации.

  8. А вот теперь тонкий момент, который не все понимают. Почему я использовал промежуточные переменные intRow и varTemp? Вроде бы есть очевидный ответ - чтобы не вычислять значение выражений с Match и Cells 2 раза. Отчасти это, конечно, так. Но это, в данном случае, не главная причина. Главная причина в том, что такой код

    вызовет неправильное поведение программы. Если у нас Match вызовет исключение, то VBA передаст управление на СЛЕДУЮЩИЙ оператор, а следующий оператор в данном случае это то, что идёт после Then - присваивание переменной varTemp значения. Таким образом наша проверка на наличие ошибки сработает с точностью до наоборот, передав управление в ту часть кода, которая должна быть защищена от ситуации, когда Match не нашла строку в таблице. Вот почему важно в операторе If не иметь ничего такого, что могло бы вызвать ошибку.

  9. Как видите, в этом подходе мне зачастую даже нет необходимости проверять объект Err, чтобы понять, что произошла ошибка, так как я ориентируюсь на то, что промежуточные переменные остаются неинициализированными, что является показателем наличия ошибки.

Выносной подход

Данный метод основан на том, что, когда возникает ошибка, то VBA передаёт управление на специальный участок кода - обработчик ошибок, который обычно размещают в конце подпрограммы. Это может выглядеть так:

Обратите внимание, что:

  1. Оператор on error теперь в случае ошибки предписывает передавать управление на метку ErrorHandler, которая объявлена в конце кода процедуры GetCalories_v2

  2. В коде мы никак не заботимся о каких-либо проверках. Возникла ошибка? Иди на метку - там разберутся.

  3. Если ошибки не случилось, то, чтобы программа не стала исполнять строчки, предназначенные для обработки ошибок, перед меткой ErrorHandler обычно ставят оператор Exit Sub или Exit Function (в зависимости от типа подпрограммы).

  4. Принципиальный момент - наличие оператора On Error Resume Next сразу после метки ErrorHandler. Дело в том, что после того, как вы перешли на метку ErrorHandler, очень опасно иметь действующим оператор On Error GoTo ErrorHandler, так как, если у вас в обработчике ошибки случится любая ошибка, то управление будет передано опять на метку и, как нетрудно понять, образуется бесконечный цикл. Поэтому сразу после метки мы возможность возникновения цикла ликвидируем оператором On Error Resume Next.

Что лучше?

Какой метод лучше применять зависит от ваших предпочтений и конкретных ситуаций. Грамотную обработку ошибок можно сделать и так и эдак. Вот несколько соображений по преимуществам и недостакам данных подходов:

Автономный подход
Преимущества Недостатки
Есть возможность точно идентифицировать каждую конкретную проблему (если вы её предусмотрели), возникающую во время исполнения, что позволит вам дать самые точные инстркции пользователю для предотвращения появления исключения в будущем.
Достаточно трудоёмок, так как подразумевает наличие большого количества проверок в коде. Каждое потенциально опасное действие должно быть снабжено соответствующим оператором If, в котором контролируется значение переменной или код ошибки.
Надо хорошо представлять себе ситуации, где могут возникнуть ошибки, в противном случае ряд ошибок вы просто не заметите на этапе отладки.
Необходимо больше кода, а также требуется опыт и фантазия.
Необходимо больше промежуточных переменных
Выносной подход
Преимущества Недостатки
Ни одна ошибка не проскочит незамеченной. Не смотря на то, что вы перехватите все ошибки, отреагировать на них правильно затруднительно, так как вы, по большому счёту, не знаете, на каком операторе произошла ошибка и почему.
Удобнее организовывать централизованный сбор логов по ошибкам в приложении. Однозначно, фаворит для больших проектов.

Средства VBA для обработки ошибок

Кратко пробежимся по операторам, функциям и объектам VBA, которые предназначены для обработки ошибок времени исполнения программы.

Операторы

On Error { GoTo label | Resume Next | GoTo 0 }

Оператор on error управляет тем, на какой участок вашего кода будет передано управление в случае возникновения ошибки. Данный оператор можно вставить в любое место вашей программы или подпрограммы. Есть 3 варианта:

  1. On error goto label - после того, как этот оператор выполнен, ошибка, возникшая на других операторах программы приведёт к переходу на метку label.

  2. On error resume next - после такого оператора, VBA будет игнорировать возникшую ошибку и передавать управление на следующий оператор, стоящий за тем, в котором возникла ошибка.

  3. On error goto 0 - это режим по-умолчанию. В случае возникновения ошибки данный режим приведёт к появлению на экране стандартного обработчик ошибок VBA с кнопками End и Debug.

Resume { label | Next | [0] }

Данный оператор возобновляет выполнение программы. Применяется в выносном методе обработки ошибок.

  1. resume label- возобновление с метки label

  2. resume next - возобновление со следующего оператора

  3. resume или resume 0 - возобновление с оператора, вызвавшего ошибку. Это имеет смысл, если вы устранили ошибку в своём обработчике. На мой взгляд, на практике такое применяется крайне редко.

Goto label

Переход на метку. Может пригодиться, однако, использование меток в коде для чего-то большего, чем обработка ошибок, считается страшным моветоном.

Exit { Do | For | Function | Sub }

Досрочный выход из циклов (Do или For) и досрочный выход из подпрограмм (функции или процедуры). Могут пригодиться при обработке ошибок, но вообще это операторы и без того чрезвычайно полезны.

Объект Err

  1. Err - глобальный объект (его не надо объявлять, а можно сразу пользоваться), который содержит информацию о последней ошибке, случившейся в вашей программе. Проверяя Err сразу после возникновения исключения или после ситуации, которая могла привести к исключению, вы можете понять, что имело место на самом деле.

  2. Свойство Err.Number - содержит числовой код ошибки, по которому их различают в программе. Поскольку Number - свойство по умолчанию, то вы можете его опускать, то есть Err и Err.Number - это эквиваленты. Значение ноль говорит о том, что ошибки не произошло.

  3. Err.Description - содержит англоязычное краткое описание ошибки

  4. Err.Source - возвращает имя модуля, в котором возникла ошибка

  5. Err.Clear - сбрасывает последнюю ошибку. Err сбрасывается также при выполнении оператором Resume, Exit (любого типа кроме Do и For) и On Error.

  6. Err.Raise - искусственно вызывает исключение указанного в переданном параметре типа. Можно использовать для тестирования вашей подсистемы обработки ошибок.

P.S.

Лично я привык в своих программах использовать автономный подход и, возможно, поэтому я не совсем осознаю все преимущества выносного подхода. Буду рад прочесть в комментариях ваше мнение на этот счёт. Тема обработки ошибок данной статьёй, конечно, быть исчерпана не может, но она послужит вам хорошей стартовой точкой в этом важном деле.


Читайте также:


VBA Excel. Метод Application.InputBox (синтаксис, параметры)

Использование метода Application.InputBox в VBA Excel, его синтаксис и параметры. Значения, возвращаемые диалогом Application.InputBox. Примеры использования.

Метод Application.InputBox предназначен в VBA Excel для вывода диалогового окна с более расширенными возможностями, чем диалоговое окно, отображаемое функцией InputBox. Главным преимуществом метода Application.InputBox является возможность автоматической записи в поле ввода диапазона ячеек (в том числе одной ячейки) путем его выделения на рабочем листе книги Excel и возвращения различных данных, связанных с ним, а также проверка соответствия возвращаемого значения заданному типу данных.

Синтаксис метода

Application. InputBox ( Prompt , Title , Default , Left , Top , HelpFile , HelpContextID , Type )

Обязательным параметром метода Application.InputBox является Prompt, если значения остальных параметров явно не указаны, используются их значения по умолчанию.

Обратите внимание на то, что

  • оператор InputBox вызывает функцию InputBox, а
  • оператор Application.InputBox вызывает метод InputBox.

Чтобы не было путаницы, метод InputBox пишут как метод Application.InputBox, в том числе и в справке разработчика.

Параметры метода

Параметр Описание Значение по умолчанию
Prompt Обязательный параметр. Выражение типа String, отображаемое в диалоговом окне в виде сообщения, приглашающего ввести данные в поле. Разделить на строки сообщение можно с помощью константы vbNewLine. Нет
Title Необязательный параметр.  Выражение типа Variant, отображаемое в заголовке диалогового окна. Слово «Ввод»
Default Необязательный параметр. Выражение типа Variant, отображаемое в поле ввода при открытии диалога.  Пустая строка
Left Необязательный параметр. Выражение типа Variant, определяющее в пунктах расстояние от левого края экрана до левого края диалогового окна (координата X).* Горизонтальное выравнивание по центру**
Top Необязательный параметр. Выражение типа Variant, определяющее в пунктах расстояние от верхнего края экрана до верхнего края диалогового окна (координата Y).* Приблизительно равно 1/3 высоты экрана***
HelpFile Необязательный параметр. Выражение типа Variant, указывающее имя файла справки для этого поля ввода. Нет****
HelpContextID Необязательный параметр. Выражение типа Variant, указывающее идентификатор контекста в справочном разделе файла справки. Нет****
Type Необязательный параметр. Выражение типа Variant, указывающее тип возвращаемых данных. 2 (текст)

* Параметры Left и Top учитываются при отображении диалогового окна методом Application.InputBox в Excel 2003, а в последующих версиях Excel 2007-2016 уже не работают.
**При первом запуске горизонтальное выравнивание устанавливается по центру, при последующих – форма отобразиться в том месте, где ее последний раз закрыли.
***При первом запуске вертикальное расположение приблизительно равно 1/3 высоты экрана, при последующих – форма отобразиться в том месте, где ее последний раз закрыли.
**** Если будут указаны параметры HelpFile и HelpContextID, в диалоговом окне появится кнопка справки.

Возвращаемые значения

Диалоговое окно, созданное методом Application. InputBox, возвращает значение типа Variant и проверяет соответствие возвращаемого значения типу данных, заданному параметром Type. Напомню, что тип значений Variant является универсальным контейнером для значений других типов, а в нашем случае для возвращаемых в зависимости от значения параметра Type.

Аргументы параметра Type и соответствующие им типы возвращаемых значений:

Type Возвращаемое значение
0 Формула
1 Число
2 Текст (string)
4 Логическое значение (True или False)
8 Ссылки на ячейки в виде объекта Range
16 Значение ошибки (например, #н/д)
64 Массив значений

Примеры

В отличие от других встроенных диалоговых окон VBA Excel, Application. InputBox при запуске процедуры непосредственно из редактора, открывается прямо в редакторе, и, чтобы выбрать диапазон ячеек на рабочем листе, нужно по вкладке браузера перейти в книгу Excel. Поэтому для тестирования диалога Application.InputBox удобнее создать кнопку, перетащив ее на вкладке «Разработчик» из «Элементов управления формы» (не из «Элементов ActiveX») и в окошке «Назначить макрос объекту» выбрать имя тестируемой процедуры. Чтобы можно было выбрать процедуру сразу при создании кнопки, она должна быть уже вставлена в стандартный программный модуль. Можно назначить процедуру кнопке позже, кликнув по ней правой кнопкой мыши и выбрав в контекстном меню «Назначить макрос…».

Пример 1 – параметры по умолчанию

Тестируем метод Application.InputBox с необязательными параметрами по умолчанию. Аргумент параметра Type по умолчанию равен 2.

Sub Test1()

Dim a As Variant

a = Application. InputBox("Выберите ячейку:")

MsgBox a

End Sub

Скопируйте код и вставьте в стандартный модуль, для удобства создайте на рабочем листе кнопку из панели «Элементы управления формы» и назначьте ей макрос «Test1». На рабочем листе заполните некоторые ячейки разными данными, нажимайте кнопку, выбирайте ячейки и смотрите возвращаемые значения.

Клик по кнопке «OK» диалога Application.InputBox в этом примере возвращает содержимое выбранной ячейки (или левой верхней ячейки выбранного диапазона), преобразованное в текстовый формат. У дат в текстовый формат преобразуется их числовое представление.

Клик по кнопке «Отмена» или по закрывающему крестику возвращает строку «False».

Пример 2 – возвращение объекта Range

В этом примере тестируем метод Application.InputBox с обязательным параметром Prompt, разделенным на две строки, параметром Title и значением параметра Type равным 8. Так как в данном случае диалог в качестве значения возвращает объект Range, он присваивается переменной с помощью оператора Set. Для этого примера создайте новую кнопку из панели «Элементы управления формы» и назначьте ей макрос «Test2».

Sub Test2()

Dim a As Variant

Set a = Application.InputBox("Пожалуйста," _

& vbNewLine & "выберите диапазон:", _

"Наш диалог", , , , , , 8)

MsgBox a.Cells(1)

MsgBox a.Address

End Sub

В первом информационном окне MsgBox выводится значение первой ячейки выбранного диапазона, во втором – адрес диапазона.

Напомню, что обращаться к ячейке в переменной диапазона «a» можно не только по порядковому номеру (индексу) самой ячейки, но и по индексу строки и столбца, на пересечении которых она находится. Например, оба выражения

указывают на первую ячейку диапазона. А в объектной переменной «a» с присвоенным диапазоном размерностью 3х3 оба выражения

указывают на центральную ячейку диапазона.

При использовании метода Application.InputBox происходит проверка введенных данных: попробуйте понажимать кнопку «OK» с пустым полем ввода и с любым введенным текстом (кроме абсолютного адреса). Реакция в этих случаях разная, но понятная.

Есть и отрицательные моменты: при использовании в диалоге Application.InputBox параметра Type со значением равным 8, нажатие кнопок «Отмена» и закрывающего крестика вызывают ошибку Type mismatch (Несоответствие типов). Попробуйте нажать кнопку «Отмена» или закрыть форму диалога.

Решить эту проблему можно, добавив обработчик ошибок. Скопируйте в стандартный модуль код следующей процедуры, создайте еще одну кнопку и назначьте ей макрос «Test3».

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

Sub Test3()

Dim a As Variant

'При возникновении ошибки

'перейти к метке "Inform"

On Error GoTo Inform

Set a = Application. InputBox("Пожалуйста," _

& vbNewLine & "Выберите диапазон:", _

"Наш диалог", , , , , , 8)

MsgBox a.Cells(1)

MsgBox a.Address

'Выйти из процедуры,

'если не произошла ошибка

Exit Sub

'Метка

Inform:

'Вывести информационное окно с

'сообщением об ошибке

MsgBox "Диалог закрыт или нажата кнопка " _

& Chr(34) & "Отмена" & Chr(34) & "!"

End Sub

Попробуйте теперь нажать кнопку «Отмена» или закрыть форму диалога крестиком.

Пример 3 – возвращение массива

Скопируйте в стандартный модуль код процедуры ниже, создайте четвертую кнопку и назначьте ей макрос «Test4». В этой процедуре указан только аргумент параметра Type равным 64, остальные необязательные параметры оставлены по умолчанию.

Sub Test4()

Dim a As Variant

a = Application. InputBox("Выберите диапазон:", , , , , , , 64)

MsgBox a(3, 3)

End Sub

Откройте диалоговую форму, нажав четвертую кнопку, и выберите диапазон размерностью не менее 3х3. Нажмите «OK»: информационное сообщение выведет значение соответствующего элемента массива «a», в нашем случае – «a(3, 3)». Если вы выберите диапазон по одному из измерений меньше 3, тогда строка «MsgBox a(3, 3)» вызовет ошибку, так как указанный элемент выходит за границы массива. Эта же строка по этой же причине вызовет ошибку при нажатии кнопки «Отмена» и при закрытии диалога крестиком. Если закомментировать строку «MsgBox a(3, 3)», то закрываться диалог будет без ошибок и при нажатии кнопки «Отмена», и при закрытии диалога крестиком.

Чтобы не попасть за границу массива используйте функцию UBound для определения наибольшего доступного индекса по каждому из двух измерений, например, вот так:

Sub Test5()

Dim a As Variant

a = Application. InputBox("Выберите диапазон:", , , , , , , 64)

MsgBox "Максимальный индекс 1 измерения = " & UBound(a, 1) & _

vbNewLine & "Максимальный индекс 2 измерения = " & UBound(a, 2)

End Sub

только присваивайте значения выражений «UBound(a, 1)» и «UBound(a, 2)» числовым переменным. А этот код используйте для ознакомления с работой функции UBound и ее тестирования.

В этой процедуре ошибка выдается при выборе одной ячейки или диапазона в одной строке, очевидно, Excel воспринимает его как одномерный массив. Хотя при выборе диапазона в одном столбце, по крайней мере в Excel 2016, все проходит гладко и вторая строка информационного сообщения отображается как «Максимальный индекс 2 измерения = 1».

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

Пример 4 – возвращение формулы

Возвращение формулы рассмотрим на следующем примере:

Sub Test6()

Dim a As Variant

a = Application.InputBox("Создайте формулу:", , , , , , , 0)

Cells(1, 1) = a

End Sub

На активном листе Excel заполните некоторые ячейки числами и запустите процедуру на выполнение. После отображения диалога Application.InputBox выбирайте по одной ячейке с числами, вставляя между ними математические операторы. После нажатия на кнопку «OK» формула запишется в первую ячейку активного рабочего листа «Cells(1, 1)» (в текст формулы ее не выбирайте, чтобы не возникла циклическая ссылка). При нажатии на кнопку «Отмена» и при закрытии диалога крестиком в эту ячейку запишется слово «Ложь».

Можно записывать не только математические формулы, но и объединять содержимое ячеек с помощью оператора «&» и многое другое. Только не понятно, для чего это вообще нужно, как, впрочем, и возврат логических, числовых значений и значений ошибки. Вы можете протестировать их возврат с помощью процедуры «Test6», заменив в ней параметр Type метода Application.InputBox соответствующим для возвращения логических, числовых значений и значений ошибки.

Обработка исключений в Visual Basic.NET

Обработка исключений

Последнее обновление: 30.10.2015

В процессе выполнения программы нередко возникают такие ситуации, которые трудно или даже невозможно предусмотреть во время создания программы. Например, при передаче файла по сети может неожиданно оборваться сетевое подключение. Такие ситуации называются исключениями. Чтобы программа неожиданно не зависла в таких ситуациях, программисту нужно вводить в нее обработку исключений. Для обработки исключений в языке VB.NET имеется конструкция Try...Catch..Finally. Ее использование выглядит следующим образом:


Sub Main()

	Dim a(3) As Integer

	Try
		a(5) = 3
    Catch ex As Exception
        Console. WriteLine(ex.Message)
    Finally
        Console.WriteLine("Finally block")
    End Try
        
    Console.ReadLine()
End Sub

В данном случае у нас как раз и возникает исключение, так как в массиве a только 4 элемента, а мы пытаемся присвоить значение шестому элементу. При использовании блока Try...Catch..Finally сначала выполняются все инструкции между операторами Try и Catch. И если вдруг в каком-то месте кода возникает исключение, то обычный порядок выполнения кода останавливается и программа переходит к выражению Catch. Это выражение имеет следующий синтаксис: Catch имя_переменной As тип_исключения. В данном случае у нас объявляется переменная ex, которая имеет тип Exception. При чем если возникшее исключение не является исключением типа, указанного в выражении Catch, то оно не обрабатывается, а программа просто зависает или выбрасывает сообщение об ошибке. Так как тип Exception является базовым типом для всех исключений, то в выражении Catch ex As Exception абсолютно все исключения.

В нашем случае мы просто выводим сообщение об исключении на экран с помощью свойства Message, определенное в классе Exception. Далее в любом случае выполняется блок после оператора Finally. Но этот блок необязательный, и его можно при обработке исключений опускать.

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

Разработка собственных исключений

Мы можем создать свои собственные классы исключений, которые будут обрабатывать нежелательные ситуации. Для примера возьмем класс Algorithm, который мы сделали в одной из глав предыдущей части:


Public Class Algorithm

    Public Shared Function Factorial(x As Integer) As Integer
        If (x = 1) Then
            Return 1
        Else
            Return x * Factorial(x - 1)
        End If
    End Function

    Public Shared Function Fibbonachi(x As Integer) As Integer
        If x = 0 Then
            Return 1
        ElseIf x = 1 Then
            Return 1
        Else
            Return Fibbonachi(x - 1) + Fibbonachi(x - 2)
        End If
    End Function

End Class

Факториал и последовательность Фиббоначи определены только для положительных чисел, поэтому если мы передадим в функцию отрицательное число, возникнет исключительная ситуация. Чтобы ее обработать и создадим класс NegativeNumberException:


Public Class NegativeNumberException
    Inherits Exception
    Sub New()
        MyBase.New("В качестве параметра передано отрицательное число")
    End Sub
End Class

В этом классе по сути мы только передаем сообщение в конструктор базового класса. Теперь вызовем обработку исключения в методе Factorial с помощью ключевого слова Throw:


Public Shared Function Factorial(x As Integer) As Integer
    If x < 0 Then Throw New NegativeNumberException()
    If (x = 1) Then
        Return 1
    Else
        Return x * Factorial(x - 1)
    End If
End Function

И теперь, если мы передадим в этот метод отрицательные значения, в блоке Try...Catch будет обрабатываться исключение NegativeNumberException:


Try
    Console.WriteLine(Algorithm.Factorial(-1))
Catch ex As Exception
    Console. WriteLine(ex.Message)
End Try

VB.Net - Обработка исключений - CoderLessons.com

Исключением является проблема, возникающая при выполнении программы. Исключением является ответ на исключительное обстоятельство, которое возникает во время работы программы, например, попытка деления на ноль.

Исключения предоставляют способ передачи управления из одной части программы в другую. Обработка исключений в VB.Net основана на четырех ключевых словах — Try , Catch , Наконец и Throw .

  • Try — блок Try определяет блок кода, для которого будут активированы определенные исключения. За ним следует один или несколько блоков Catch.

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

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

  • Бросок — программа выдает исключение при обнаружении проблемы. Это делается с помощью ключевого слова Throw.

Try — блок Try определяет блок кода, для которого будут активированы определенные исключения. За ним следует один или несколько блоков Catch.

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

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

Бросок — программа выдает исключение при обнаружении проблемы. Это делается с помощью ключевого слова Throw.

Синтаксис

Предполагая, что блок вызовет исключение, метод перехватывает исключение, используя комбинацию ключевых слов Try и Catch. Блок Try / Catch размещается вокруг кода, который может генерировать исключение. Код в блоке Try / Catch называется защищенным кодом, и синтаксис использования Try / Catch выглядит следующим образом:

Try
   [ tryStatements ]
   [ Exit Try ]
[ Catch [ exception [ As type ] ] [ When expression ]
   [ catchStatements ]
   [ Exit Try ] ]
[ Catch ... ]
[ Finally
   [ finallyStatements ] ]
End Try

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

Классы исключений в .Net Framework

В .Net Framework исключения представлены классами. Классы исключений в .Net Framework в основном прямо или косвенно являются производными от класса System.Exception . Некоторыми из классов исключений, полученных из класса System. Exception, являются классы System.ApplicationException и System.SystemException .

Класс System.ApplicationException поддерживает исключения, генерируемые прикладными программами. Таким образом, исключения, определенные программистами, должны быть производными от этого класса.

Класс System.SystemException является базовым классом для всех предопределенных системных исключений.

В следующей таблице представлены некоторые предопределенные классы исключений, полученные из класса Sytem.SystemException.

Исключительный класс Описание
System.IO.IOException Обрабатывает ошибки ввода / вывода.
System.IndexOutOfRangeException Обрабатывает ошибки, сгенерированные, когда метод ссылается на индекс массива вне диапазона.
System.ArrayTypeMismatchException Обрабатывает ошибки, возникающие, когда тип не соответствует типу массива.
System.NullReferenceException Обрабатывает ошибки, сгенерированные в результате определения нулевого объекта.
System.DivideByZeroException Обрабатывает ошибки, возникающие при делении дивиденда на ноль.
System.InvalidCastException Обрабатывает ошибки, сгенерированные во время приведения типов.
System.OutOfMemoryException Обрабатывает ошибки, возникающие из-за недостатка свободной памяти.
System.StackOverflowException Обрабатывает ошибки, вызванные переполнением стека.

Обработка исключений

VB.Net предоставляет структурированное решение проблем обработки исключений в виде блоков try и catch. Используя эти блоки, основные программные операторы отделены от операторов обработки ошибок.

Эти блоки обработки ошибок реализованы с использованием ключевых слов Try , Catch и finally. Ниже приведен пример создания исключения при делении на ноль:

Live Demo

Module exceptionProg
   Sub division(ByVal num1 As Integer, ByVal num2 As Integer)
      Dim result As Integer
      Try
         result = num1 \ num2
      Catch e As DivideByZeroException
         Console.WriteLine("Exception caught: {0}", e)
      Finally
         Console.WriteLine("Result: {0}", result)
      End Try
   End Sub
   Sub Main()
      division(25, 0)
      Console.ReadKey()
  End Sub
End Module

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Exception caught: System.DivideByZeroException: Attempted to divide by zero. 
at ...
Result: 0

Создание пользовательских исключений

Вы также можете определить свое собственное исключение. Определяемые пользователем классы исключений являются производными от класса ApplicationException . Следующий пример демонстрирует это —

Live Demo

Module exceptionProg
   Public Class TempIsZeroException : Inherits ApplicationException
      Public Sub New(ByVal message As String)
         MyBase. New(message)
      End Sub
   End Class
   Public Class Temperature
      Dim temperature As Integer = 0
      Sub showTemp()
         If (temperature = 0) Then
            Throw (New TempIsZeroException("Zero Temperature found"))
         Else
            Console.WriteLine("Temperature: {0}", temperature)
         End If
      End Sub
   End Class
   Sub Main()
      Dim temp As Temperature = New Temperature()
      Try
         temp.showTemp()
      Catch e As TempIsZeroException
         Console.WriteLine("TempIsZeroException: {0}", e.Message)
      End Try
      Console.ReadKey()
   End Sub
End Module

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

TempIsZeroException: Zero Temperature found

Бросать предметы

Вы можете выбросить объект, если он прямо или косвенно является производным от класса System.Exception.

Вы можете использовать оператор throw в блоке catch, чтобы выбросить текущий объект как —

Throw [ expression ]

Следующая программа демонстрирует это —

Module exceptionProg
   Sub Main()
      Try
         Throw New ApplicationException("A custom exception _ is being thrown here. ..")
      Catch e As Exception
         Console.WriteLine(e.Message)
      Finally
         Console.WriteLine("Now inside the Finally Block")
      End Try
      Console.ReadKey()
   End Sub
End Module

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Ускоряем работу VBA в Excel / Хабр


Предисловие

Так уж сложилось, что на сегодняшний день много кому приходится работать(писать макросы) на VBA в Excel. Некоторые макросы содержат сотни строк кода, которые приходится выполнять каждый день (неделю, месяц, квартал и так далее) и, при этом, они занимают изрядное количество времени. Вроде бы и и процесс автоматизирован и человеческого вмешательства не нужно, но время, занимаемое выполнением макроса, может охватывать десятки минут, а то и несколько часов. Время, как говориться, — деньги и в этом посте я постараюсь значительно ускорить время выполнения Вашего макроса и, возможно, это положительно скажется на ваших делах, а в итоге и деньгах.

Перед началом работы

Перед тем, как перейти прямо к сути, я хотел бы обратить внимание на пост: Несколько советов по работе с VBA в Excel. В частности, в блоке “Ускорение работы макросов” есть полезные примеры кода, которые стоит использовать вместе с моими советами по ускорению работы, для достижения максимального результата.
Ускоряем работу макроса

Итак, к сути… Для того что бы реально ускорить работу VBA в Ecxel нужно понимать, что обращение к ячейке на листе — занимает значительно время. Если Вы хотите записать в ячейку одно значение, то это не займет значительного времени, но если Вам потребуется записать(прочитать, обратиться) к тысячам ячеек, то это потребует гораздо большего времени. Что же делать в таких случаях? На помощь приходят массивы. Массивы хранятся в памяти, а операции в памяти VBA выполняет в сотни, а то и в тысячи раз быстрее. Поэтому, если у Вас в данных тысячи, сотни тысяч значений, то время выполнения макроса может занимать от нескольких минут до нескольких часов, а если эти данные перенести в массив, то выполнение макроса может сократиться до нескольких секунд (минут).

Я наведу пример кода и в комментариях объясню что к чему, так будет яснее. К тому же, могут пригодиться некоторые строки кода, не относящееся прямо к процессу ускорения.

Пример

Предположим, что у нас есть данные на “Лист1” (“Sheet1”). Данные содержаться в 50 колонках (колонки содержат названия) и 10 000 строк. К примеру, нам нужно в последнюю колонку внести значение, которое равно значению во второй колонке, деленное на значение в третьей колонке (начиная со 2-й строки, так как первая содержит заглавие). Потом мы возьмем первые 10 колонок и скопируем их на “Лист2” (“Sheet2”), для дальнейшей обработки (для других потребностей). Пусть пример и банальный, но, как мне кажется, он может отобразить всю суть данного поста.
'Для явной инициализации переменных, включаем эту опцию
'Это поможет избежать многих ошибок
Option Explicit

Sub Test()

'К листам будем обращаться через переменные
Dim Sheet1_WS, Sheet2_WS As Worksheet
'Переменная для прохождения срок на листе (в массиве)
Dim i As Long

'Массив, в котором будут храниться наши данные
Dim R_data As Variant
'Переменные последней строки и колонки
Dim FinalRow, FinalColumn As Long

'Можно инициализировать лист не по названию, а по порядковому номеру
'Set Sheet1_WS = Application. ThisWorkbook.Worksheet("Sheet1")
Set Sheet1_WS = Application.ThisWorkbook.Sheets(1)
Set Sheet2_WS = Application.ThisWorkbook.Sheets(2)

'Поиск последней не пустой строки в первой колонке
'Нужно, что бы данные не были отфильтрованы, иначе последняя строка будет последней строкой в фильтре
'Также в последней строке, в первой колонке, не должно быть пустой ячейки. Конечно, если в этой строке вообще есть данные. Иначе последней строкой будет последняя не пустая ячейка.
FinalRow = Sheet1_WS.Cells(Rows.Count, 1).End(xlUp).Row '=10 000

'Поиск последней не пустой колонки в первой строке
FinalColumn = Sheet1_WS.Cells(1, Columns.Count).End(xlToLeft).Column '=50

'Присваиваем массиву диапазон данных на Листе 1
R_data = Sheet1_WS.Range(Sheet1_WS.Cells(1, 1), Sheet1_WS.Cells(FinalRow, FinalColumn))

For i = 2 To FinalRow
    'Выполняем нужные нам операции с данными.
    'Проверяем, что бы не было деления на ноль.
    'Предполагается, что в колонке 2 и 3 стоят числовые данные
    'Иначе потребуется обработка ошибок
    If R_data(i, 3) <> 0 Then
        R_data(i, FinalColumn) = R_data(i, 2) / R_data(i, 3)
    End If
Next i

'Копируем данные из массива обратно на Лист1
'Перед этим очищаем данные на листе (если есть форматирование или формулы, то лучше Sheet1_WS. Cells.ClearContents)
Sheet1_WS.Cells.Delete
Sheet1_WS.Range(Sheet1_WS.Cells(1, 1), Sheet1_WS.Cells(FinalRow, FinalColumn)) = R_data

'Копируем данные на Лист2, копируем первые 10 колонок.
Sheet2_WS.Range(Sheet2_WS.Cells(1, 1), Sheet2_WS.Cells(FinalRow, 10)) = R_data

'Закрываем книгу и сохраняем её
Workbooks(Application.ThisWorkbook.Name).Close SaveChanges:=True

End Sub

В данном примере массив заполняется указанным диапазоном. Если у нас будет явно заданный двумерный массив, то скопировать его значение на лист можно таким образом:

Dim R_new() As Variant
............................................
' Явно указываем размер массива

ReDim R_new(1 To FinalRow, 1 To 50) As Variant
...........................................
Sheet1_WS.Range(Sheet1_WS.Cells(1, 1), Sheet1_WS.Cells(FinalRow, 50)) = R_new()
Заключение

Большинство операций над данными можно выполнять в массиве, при этом, отображать на лист только результат. Иногда целесообразным бывает показать результат на лист, потом выполнить некоторые действия (например, сортировку) и снова загрузить данные в массив.

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

В дальнейшем я планирую написать советы (примеры) по быстрому поиску данных на листе, но это уже будет другой пост. Если будут вопросы, комментарии, пожалуйста, пишите.

Спасибо за внимание. Удачных разработок.

Как ускорить и оптимизировать код VBA

Хитрости » 20 Январь 2016       Дмитрий       43454 просмотров


Рано или поздно у пишущих на Visual Basic for Applications возникает проблема - код хоть и облегчает жизнь и делает все автоматически, но очень долго. В этой статье я решил собрать несколько простых рекомендаций, которые помогут ускорить работу кода VBA, при этом в некоторых случаях весьма внушительно - в десятки, а то и больше, раз. Основной упор в статье сделан на начинающих, поэтому в начале статьи приводятся самые простые методы оптимизации. Более "глубокие" решения по оптимизации кода приведены в конце статьи, т.к. для применения данных решений необходим достаточный опыт работы в VB и сходу такие методы оптимизации кому-то могут быть непонятны.

  1. Если в коде есть много всяких Activate и Select, тем более в циклах - следует немедленно от них избавиться. Как это сделать я писал в статье: Select и Activate - зачем нужны и нужны ли?
  2. Обязательно на время выполнения кода отключить:
    • автоматический пересчет формул. Чтобы формулы не пересчитывались при каждой манипуляции на листе во время выполнения кода - это может дико тормозить код, если формул много:
      Application.Calculation = xlCalculationManual

      Application.Calculation = xlCalculationManual

    • обновление экрана, чтобы действия по изменению значений ячеек и пр. не мелькали. Зачем это надо? Т. к. все эти действия обращаются к графическому процессору и заставляют его трудиться для перерисовки экрана - это может значительно тормозить код:
      Application.ScreenUpdating = False

      Application.ScreenUpdating = False

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

Элементы обработки ошибок времени выполнения

  • Читать 12 минут

В этой статье

Ошибки и обработка ошибок

При программировании приложения необходимо учитывать, что происходит при возникновении ошибки. Ошибка может возникнуть в вашем приложении по одной из двух причин. Во-первых, какое-то условие во время работы приложения приводит к сбою действительного кода.Например, если ваш код пытается открыть таблицу, которую удалил пользователь, возникает ошибка. Во-вторых, ваш код может содержать неправильную логику, которая не позволяет ему делать то, что вы планировали. Например, ошибка возникает, если ваш код пытается разделить значение на ноль.

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

При добавлении обработки ошибок в процедуру вы должны учитывать, как процедура будет направлять выполнение при возникновении ошибки. Первым шагом в маршрутизации выполнения обработчику ошибок является включение обработчика ошибок путем включения в процедуру некоторой формы оператора On Error . Оператор On Error направляет выполнение в случае ошибки.Если нет оператора On Error , Visual Basic просто останавливает выполнение и отображает сообщение об ошибке при возникновении ошибки.

Когда ошибка возникает в процедуре с включенным обработчиком ошибок, Visual Basic не отображает обычное сообщение об ошибке. Вместо этого он направляет выполнение обработчику ошибок, если он существует. Когда выполнение переходит к включенному обработчику ошибок, этот обработчик ошибок становится активным. В активном обработчике ошибок вы можете определить тип возникшей ошибки и устранить ее выбранным вами способом.Access предоставляет три объекта, которые содержат информацию о произошедших ошибках: объект ошибки ADO , объект ошибки Visual Basic и объект ошибки DAO .

Выполнение маршрутизации при возникновении ошибки

Обработчик ошибок определяет, что происходит в процедуре при возникновении ошибки. Например, вы можете захотеть, чтобы процедура завершилась при возникновении определенной ошибки, или вы можете захотеть исправить условие, вызвавшее ошибку, и возобновить выполнение.Операторы On Error и Resume определяют, как выполняется выполнение в случае ошибки.

Сообщение об ошибке

Оператор On Error включает или отключает процедуру обработки ошибок. Если подпрограмма обработки ошибок включена, выполнение переходит к подпрограмме обработки ошибок при возникновении ошибки.

Существует три формы оператора On Error : On Error GoTo label , On Error GoTo 0 и On Error Resume Next .Оператор On Error GoTo label включает процедуру обработки ошибок, начиная со строки, в которой находится оператор. Вы должны включить процедуру обработки ошибок перед первой строкой, в которой может произойти ошибка. Когда обработчик ошибок активен и возникает ошибка, выполнение переходит к строке, указанной в аргументе label .

Строка, указанная в аргументе label , должна быть началом процедуры обработки ошибок.Например, следующая процедура указывает, что при возникновении ошибки выполнение переходит к строке с меткой:

  Функция MayCauseAnError ()
    'Включить обработчик ошибок.
    При ошибке Перейти к Error_MayCauseAnError
    . 'Включите сюда код, который может вызвать ошибку.
    .
    .
 
Error_MayCauseAnError:
    . 'Включите сюда код для обработки ошибки.
    .
    .
Конечная функция
  

Оператор On Error GoTo 0 отключает обработку ошибок внутри процедуры.Он не указывает строку 0 как начало кода обработки ошибок, даже если процедура содержит строку с номером 0. Если в вашем коде нет оператора On Error GoTo 0 , обработчик ошибок автоматически отключается, когда процедура отработал полностью. Оператор On Error GoTo 0 сбрасывает свойства объекта Err , имея тот же эффект, что и метод Clear объекта Err .

Оператор On Error Resume Resume Next игнорирует строку, вызывающую ошибку, и направляет выполнение на строку, следующую за строкой, вызвавшей ошибку.Исполнение не прерывается. Вы можете использовать оператор On Error Resume Next , если хотите проверить свойства объекта Err сразу после строки, в которой, как вы ожидаете, произойдет ошибка, и обработать ошибку внутри процедуры, а не в обработчике ошибок. .

Резюме

Оператор Resume направляет выполнение обратно в тело процедуры из подпрограммы обработки ошибок. Вы можете включить оператор Resume в подпрограмму обработки ошибок, если хотите, чтобы выполнение продолжалось в определенной точке процедуры.Однако в заявлении Resume нет необходимости; вы также можете завершить процедуру после процедуры обработки ошибок.

Существует три формы заявления Resume . Оператор Resume или Resume 0 возвращает выполнение к строке, в которой произошла ошибка. Оператор Resume Next возвращает выполнение в строку, следующую сразу за строкой, в которой произошла ошибка. Оператор Resume label возвращает выполнение в строку, указанную аргументом label .Аргумент label должен указывать либо метку строки, либо номер строки.

Обычно вы используете оператор Resume или Resume 0 , когда пользователь должен внести исправление. Например, если вы запрашиваете у пользователя имя таблицы для открытия, а пользователь вводит имя таблицы, которая не существует, вы можете снова запросить пользователя и возобновить выполнение с помощью оператора, вызвавшего ошибку.

Вы используете оператор Resume Next , когда ваш код исправляет ошибку в обработчике ошибок, и вы хотите продолжить выполнение без повторного запуска строки, вызвавшей ошибку. Вы используете оператор Resume label , если хотите продолжить выполнение в другой точке процедуры, указанной аргументом label . Например, вы можете захотеть возобновить выполнение процедуры выхода, как описано в следующем разделе.

Выход из процедуры

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

Например, вы можете добавить процедуру выхода к примеру в предыдущем разделе. Если ошибки не происходит, процедура выхода запускается после тела процедуры. Если возникает ошибка, выполнение переходит к подпрограмме выхода после того, как был выполнен код подпрограммы обработки ошибок. Программа выхода содержит оператор Exit .

  Функция MayCauseAnError ()
    'Включить обработчик ошибок. При ошибке Перейти к Error_MayCauseAnError
    . 'Включите сюда код, который может вызвать ошибку.
    .
    .
 
Exit_MayCauseAnError:
    Функция выхода
 
Error_MayCauseAnError:
    . 'Включите код для обработки ошибки.
    .
    .
    'Продолжить выполнение с процедурой выхода для выхода из функции.
    Возобновить Exit_MayCauseAnError
Конечная функция
  

Обработка ошибок во вложенных процедурах

Когда ошибка возникает во вложенной процедуре, у которой нет включенного обработчика ошибок, Visual Basic выполняет обратный поиск в списке вызовов в поисках включенного обработчика ошибок в другой процедуре, а не просто останавливает выполнение.Это дает вашему коду возможность исправить ошибку в другой процедуре. Например, предположим, что процедура A вызывает процедуру B, а процедура B вызывает процедуру C. Если в процедуре C возникает ошибка и нет включенного обработчика ошибок, Visual Basic проверяет процедуру B, а затем процедуру A на наличие включенного обработчика ошибок. Если он существует, выполнение переходит к этому обработчику ошибок. В противном случае выполнение останавливается и отображается сообщение об ошибке.

Visual Basic также выполняет обратный поиск в списке вызовов включенного обработчика ошибок, когда ошибка возникает в активном обработчике ошибок.Вы можете заставить Visual Basic выполнять поиск в обратном направлении по списку вызовов, вызывая ошибку в активном обработчике ошибок с помощью метода Raise объекта Err . Это полезно для обработки ошибок, которых вы не ожидаете в обработчике ошибок. Если возникает непредвиденная ошибка, и вы повторно создаете эту ошибку в обработчике ошибок, то выполнение передает резервную копию списка вызовов, чтобы найти другой обработчик ошибок, который может быть настроен для обработки ошибки.

Например, предположим, что процедура C имеет активированный обработчик ошибок, но обработчик ошибок не исправляет возникшую ошибку.Как только обработчик ошибок проверит все ожидаемые вами ошибки, он может восстановить исходную ошибку. Затем выполнение передает обратно список вызовов обработчику ошибок в процедуре B, если таковой существует, предоставляя этому обработчику ошибок возможность исправить ошибку. Если в процедуре B нет обработчика ошибок или если он не может исправить ошибку и повторно создать ее, то выполнение переходит к обработчику ошибок в процедуре A, если он существует.

Чтобы проиллюстрировать эту концепцию другим способом, предположим, что у вас есть вложенная процедура, которая включает в себя обработку ошибок несоответствия типа, ошибки, которую вы ожидали.В какой-то момент в процедуре C возникает ошибка деления на ноль, которую вы не ожидали. Если вы включили оператор для восстановления исходной ошибки, выполнение передает резервную копию списка вызовов другому включенному обработчику ошибок. , если таковой существует. Если вы исправили ошибку деления на ноль в другой процедуре в списке вызовов, то ошибка будет исправлена. Если ваш код не генерирует ошибку повторно, процедура продолжает выполняться без исправления ошибки деления на ноль. Это, в свою очередь, может вызвать другие ошибки в наборе вложенных процедур.

Таким образом, Visual Basic выполняет поиск включенного обработчика ошибок в резервной копии списка вызовов, если:

  • Ошибка возникает в процедуре, которая не включает включенный обработчик ошибок.

  • Ошибка в активном обработчике ошибок. Если вы используете метод Raise объекта Err , чтобы вызвать ошибку, вы можете заставить Visual Basic выполнить обратный поиск по списку вызовов для включенного обработчика ошибок.

Получение информации об ошибке

После того, как выполнение перешло к подпрограмме обработки ошибок, ваш код должен определить, какая ошибка произошла, и устранить ее. Visual Basic и Access предоставляют несколько языковых элементов, которые можно использовать для получения информации о конкретной ошибке. Каждый подходит для разных типов ошибок. Поскольку ошибки могут возникать в разных частях вашего приложения, вам необходимо определить, какие из них использовать в своем коде, исходя из ожидаемых ошибок.

Элементы языка, доступные для обработки ошибок, включают:

  • Err объект

  • ADO Ошибка объекта и ошибки Коллекция

  • DAO Ошибка объекта и ошибки Коллекция

  • AccessError Метод

  • Ошибка , событие

Err объект

Объект Err предоставляется Visual Basic.Когда возникает ошибка Visual Basic, информация об этой ошибке сохраняется в объекте Err . Объект Err поддерживает информацию только об одной ошибке за раз. Когда возникает новая ошибка, объект Err обновляется, чтобы вместо этого включать информацию об этой ошибке.

Чтобы получить информацию о конкретной ошибке, вы можете использовать свойства и методы объекта Err :

  • Свойство Number является свойством по умолчанию для объекта Err ; он возвращает идентификационный номер возникшей ошибки.
  • Свойство Description объекта Err возвращает описательную строку, связанную с ошибкой Visual Basic.
  • Метод Clear очищает текущую информацию об ошибке из объекта Err .
  • Метод Raise генерирует определенную ошибку и заполняет свойства объекта Err информацией об этой ошибке.

В следующем примере показано, как использовать объект Err в процедуре, которая может вызвать ошибку несоответствия типа:

  Функция MayCauseAnError ()
    'Объявите константу для представления вероятной ошибки.Константа conTypeMismatch как целое число = 13
 
    При ошибке Перейти к Error_MayCauseAnError
        . 'Включите сюда код, который может вызвать ошибку.
        .
        .
 
Exit_MayCauseAnError:
    Функция выхода
 
Error_MayCauseAnError:
    'Проверить свойства объекта Err.
    Если Err = conTypeMismatch Тогда
        .  'Включите код для обработки ошибки.
        .
        .
    Еще
        'Восстановить исходную ошибку.
        Dim intErrNum As Integer
        intErrNum = Err
        Err.Очистить
        Err.Raise intErrNum
    Конец, если
    'Продолжить выполнение с процедурой выхода для выхода из функции.
    Возобновить Exit_MayCauseAnError
Конечная функция
  

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

Объект Err предоставляет всю необходимую информацию об ошибках Visual Basic.Однако он не дает вам полной информации об ошибках Access или ошибках ядра СУБД Access. Доступ и объекты доступа к данным (DAO) предоставляют дополнительные языковые элементы, чтобы помочь вам с этими ошибками.

Объект ошибки и коллекция ошибок

Объект Error и коллекция Errors предоставляются ADO и DAO. Ошибка Объект представляет ошибку ADO или DAO. Одна операция ADO или DAO может вызвать несколько ошибок, особенно если вы выполняете операции DAO ODBC.Каждая ошибка, возникающая во время определенной операции доступа к данным, имеет связанный объект Error . Все объекты Error , связанные с конкретной операцией ADO или DAO, хранятся в коллекции Errors , причем ошибка самого низкого уровня является первым объектом в коллекции, а ошибка самого высокого уровня - последним объектом в коллекции.

Когда возникает ошибка ADO или DAO, объект Visual Basic Err содержит номер ошибки для первого объекта в коллекции Errors .Чтобы определить, возникли ли дополнительные ошибки ADO или DAO, проверьте коллекцию Errors . Значения свойств ADO Number или DAO Number и свойств ADO Description или DAO Description первого объекта Error в коллекции Errors должны соответствовать значениям Number и Описание свойств объекта Visual Basic Err .

Метод AccessError

Вы можете использовать метод Raise объекта Err , чтобы сгенерировать ошибку Visual Basic, которая на самом деле не произошла, и определить описательную строку, связанную с этой ошибкой.Однако вы не можете использовать метод Raise для генерации ошибки доступа, ошибки ADO или ошибки DAO. Чтобы определить описательную строку, связанную с ошибкой доступа, ошибкой ADO или ошибкой DAO, которая на самом деле не произошла, используйте метод AccessError .

Событие ошибки

Событие Error можно использовать для перехвата ошибок, возникающих в форме или отчете Access. Например, если пользователь пытается ввести текст в поле с типом данных «Дата / время», возникает событие «Ошибка».Если вы добавляете процедуру обработки события «Ошибка» в форму «Сотрудники», а затем пытаетесь ввести текстовое значение в поле HireDate, запускается процедура обработки события «Ошибка».

Процедура обработки события Error принимает целочисленный аргумент DataErr. Когда выполняется процедура обработки события Error, аргумент DataErr содержит номер возникшей ошибки доступа. Проверка значения аргумента DataErr в процедуре обработки события - единственный способ определить номер возникшей ошибки. Объект Err не заполняется сведениями об ошибке после возникновения события Error.Вы можете использовать значение аргумента DataErr вместе с методом AccessError , чтобы определить номер ошибки и ее описательную строку.

Примечание

Оператор Error и функция Error предназначены только для обратной совместимости. При написании нового кода используйте объекты Err и Error , функцию AccessError и событие Error для получения информации об ошибке.

Об авторах

Ссылка предоставлена ​​ сообществом UtterAccess.

UtterAccess - это ведущая вики-страница и справочный форум Microsoft Access.

См. Также

Поддержка и отзывы

Есть вопросы или отзывы об Office VBA или этой документации? См. Раздел Поддержка и отзывы Office VBA, чтобы узнать, как получить поддержку и оставить отзыв.

Microsoft Visual Basic: обработка исключений

Практичный Обучение: поиск исключений

  1. Чтобы ввести исключения, откройте код формы и измените события кнопок следующим образом:
     Public Class Form1
    
        .. . Без изменений 
    
        Частная подпрограмма BtnProcessClick (отправитель ByVal как объект,
                                     ByVal e как System.EventArgs)
                                     Обрабатывает BtnProcess.Click
             . . . Без изменений 
    
            'Запросить количество каждой категории товаров
            'Количество рубашек
            Пытаться
                NumberOfShirts = CInt (TxtQtyShirts. Text)
            Поймать
    
            Конец попытки
    
            'Количество штанов
            Пытаться
                NumberOfPants = CInt (TxtQtyPants.Текст)
            Поймать
    
            Конец попытки
    
            'Количество платьев
            Пытаться
                NumberOfOther = CInt (TxtQtyOther.Text)
            Поймать
    
            Конец попытки
    
            'Цена за единицу товара
            Пытаться
                PriceOneShirt = CDbl (TxtUnitPriceShirts.Text)
            Поймать
    
            Конец попытки
    
            Пытаться
                PriceAPairOfPants = CDbl (TxtUnitPricePants.Text)
            Поймать
    
            Конец попытки
    
            Пытаться
                PriceOther = CDbl (TxtUnitPriceOther.Text)
            Поймать
    
            Конец попытки
    
             .. . Без изменений 
        Конец подписки
    
        Частная подписка BtnTaxClick (отправитель ByVal как объект,
                                 ByVal e как System.EventArgs)
                                 Обрабатывает BtnTax.Click
            'Получить налоговую ставку
            Пытаться
                TaxRate = CDbl (TxtTaxRate. Text) / 100
            Поймать
    
            Конец попытки
            'Рассчитайте сумму налога по постоянной ставке
            TaxAmount = TotalOrder * TaxRate
            'Добавьте сумму налога к общему заказу
            SalesTotal = TotalOrder + TaxAmount
    
            TxtTaxAmount.Текст = TaxAmount.ToString ()
            TxtNetPrice.Text = SalesTotal.ToString ()
        Конец подписки
    
        Частная подпрограмма BtnDifferenceClick (отправитель ByVal как объект,
                                        ByVal e как System.EventArgs)
                                        Обрабатывает BtnDifference.Click
            Dim AmountTended As Double = 0,0
            Разница затемнения как двойная = 0,0
    
            'Запросить деньги за заказ
            Пытаться
                AmountTended = CDbl (TxtAmountTended.Text)
            Поймать
    
            Конец попытки
    
            'Рассчитайте разницу, причитающуюся клиенту
            'или что покупатель все еще должен магазину
            Разница = AmountTended - SalesTotal
    
            TxtDifference.Текст = CStr (Разница)
        Конец подписки
    Конец класса 
  2. Запустить заявку. На этот раз введите недопустимые значения в текстовые поля количества и другие текстовые поля, в которых пользователь должен введите значения

  3. Нажмите Процесс

  4. Вернуться в среду программирования

Как уже было сказано, если при обработке возникает ошибка программа из раздела Try , компилятор передает обработку к следующему разделу Catch .Затем вы можете использовать раздел улова для работы с с ошибкой. Как минимум, вы можете отобразить сообщение, информирующее пользователя. Для этого вы можете создать окно сообщения в разделе Catch . Вот это пример:

 Система импорта.
Импортирует System.Windows.Forms

Модульное упражнение

    Начинающий общественный класс
        Наследует форму

        Частный LblNumber как метка
        Частный TxtNumber как текстовое поле
        Друг WithEvents BtnCalculate As Button
        Private LblResult As Label
        Частный TxtResult как TextBox

        Компоненты Dim As System. ComponentModel.Container

        Публичная подписка Новое ()
            InitializeComponent ()
        Конец подписки

        Открытый Sub InitializeComponent ()
            Text = "Исключительное поведение"

            LblNumber = Новый ярлык
            LblNumber.Location = Новая точка (17, 23)
            LblNumber.Text = "Число:"
            LblNumber.AutoSize = True

            TxtNumber = Новое текстовое поле
            TxtNumber.Location = Новая точка (78, 20)
            TxtNumber.Size = Новый размер (83, 20)

            BtnCalculate = Новая кнопка
            BtnCalculate.Местоположение = Новая точка (78, 45)
            BtnCalculate.Text = "Рассчитать"
            BtnCalculate.Size = Новый размер (83, 23)

            LblResult = Новый ярлык
            LblResult.Location = Новая точка (17, 75)
            LblResult.Text = "Результат:"
            LblResult.AutoSize = True

            TxtResult = Новое текстовое поле
            TxtResult.Location = Новая точка (76, 72)
            TxtResult. Size = Новый размер (83, 20)

            Controls.Add (LblNumber)
            Controls.Add (TxtNumber)
            Элементы управления.Добавить (BtnCalculate)
            Controls.Add (LblResult)
            Controls.Add (TxtResult)

        Конец подписки

        Частная подпрограмма CalculateClicked (отправитель ByVal как объект,
                                     ByVal и как EventArgs)
                                     Обрабатывает BtnCalculate.Click
            Тусклый номер как двойной
            Тусклый результат как двойной

            Пытаться
                Число = CDbl (TxtNumber.Text)
                Результат = Число * 12,48
                TxtResult.Текст = CStr (Результат)
            Поймать
                MsgBox («Произошло что-то плохое»)
            Конец попытки
        Конец подписки
    Конец класса

    Функция Main () как целое число

        Dim frmStart As Starter = Новый стартер

        Application.Run (frmStart)

        Возврат 0
    Конечная функция

Концевой модуль 

Конечно, ваше сообщение может быть не особенно четким но на этот раз программа не выйдет из строя.

Практичный Обучение: отображение пользовательских сообщений

  1. Чтобы отображать настраиваемые сообщения для пользователя, измените код следующим образом:
     Public Class Form1
    
         .. . Без изменений 
    
        Частная подпрограмма BtnProcessClick (отправитель ByVal как объект,
                                     ByVal e как System.EventArgs)
                                     Обрабатывает BtnProcess.Click
             . . . Без изменений 
    
            'Запросить количество каждой категории товаров
            'Количество рубашек
            Пытаться
                NumberOfShirts = CInt (TxtQtyShirts.Text)
            Поймать
                MsgBox ("Введенное вами значение числа" &
                       "рубашки не является допустимым числом."&
                       vbCrLf & "Пожалуйста, введите натуральное число, например" &
                       «как 2 или 24 или даже 248»)
            Конец попытки
    
            'Количество штанов
            Пытаться
                NumberOfPants = CInt (TxtQtyPants. Text)
            Поймать
                MsgBox ("Введенное вами значение числа" &
                       "пара или брюки не является допустимым числом". &
                       vbCrLf & "Пожалуйста, введите натуральное число, например" &
                       «как 2 или 24 или даже 248»)
            Конец попытки
    
            'Количество других предметов
            Пытаться
                NumberOfOther = CInt (TxtQtyOther.Текст)
            Поймать
                MsgBox ("Введенное вами значение числа" &
                       «другие элементы не являются допустимым числом». &
                       vbCrLf & "Пожалуйста, введите натуральное число, например" &
                       «как 2 или 24 или даже 248»)
            Конец попытки
    
            'Цена за единицу товара
            Пытаться
                PriceOneShirt = CDbl (TxtUnitPriceShirts.Text)
            Поймать
                MsgBox ("Введенное вами значение цены за единицу" &
                       «рубашка не является узнаваемой валютой» &
                       "количество."& vbCrLf &
                       «Только натуральные или десятичные числа» &
                       "разрешены.  Проконсультируйтесь с руководством" &
                       «знать действующие цены».)
            Конец попытки
    
            Пытаться
                PriceAPairOfPants = CDbl (TxtUnitPricePants.Text)
            Поймать
                MsgBox ("Введенное вами значение цены за единицу" &
                       "пара штанов неузнаваема" &
                       «сумма валюты». & vbCrLf &
                       "Только натуральное или десятичное" &
                       "числа разрешены.Вы можете обратиться к "&
                       "руководство, чтобы узнать о" &
                       «допустимые цены».)
            Конец попытки
    
            Пытаться
                PriceOther = CDbl (TxtUnitPriceOther.Text)
            Поймать
                MsgBox ("Введенное вами значение единицы" &
                       «цена других товаров не является допустимой суммой». &
                       vbCrLf & "Вы должны вводить только естественный или" &
                       "десятичное число. Для получения дополнительной информации" &
                       "пожалуйста, обратитесь к руководству, чтобы получить" &
                       "правильные цены. ")
            Конец попытки
    
             . . . Без изменений 
        Конец подписки
    
        Частная подписка BtnTaxClick (отправитель ByVal как объект,
                                 ByVal e как System.EventArgs)
                                 Обрабатывает BtnTax.Click
            'Получить налоговую ставку
            Пытаться
                TaxRate = CDbl (TxtTaxRate.Text) / 100
            Поймать
                MsgBox ("Введенное вами значение не является" &
                       «признана действующей налоговой ставкой». &
                       vbCrLf & "Действительная ставка налога - это значение" &
                       "от 0 до 100.00 "&
                       vbCrLf & "Пожалуйста, попробуйте еще раз.")
            Конец попытки
            'Рассчитайте сумму налога по постоянной ставке
            TaxAmount = TotalOrder * TaxRate
            'Добавьте сумму налога к общему заказу
            SalesTotal = TotalOrder + TaxAmount
    
            TxtTaxAmount.Text = TaxAmount.ToString ()
            TxtNetPrice.Text = SalesTotal.ToString ()
        Конец подписки
    
        Частная подпрограмма BtnDifferenceClick (отправитель ByVal как объект,
                                        ByVal e как System. EventArgs)
                                        Обрабатывает BtnDifference.Нажмите
            Dim AmountTended As Double = 0,0
            Разница затемнения как двойная = 0,0
    
            'Запросить деньги за заказ
            Пытаться
                AmountTended = CDbl (TxtAmountTended.Text)
            Поймать
                MsgBox ("Введенное вами значение суммы" &
                       "тендер" недействителен. Только натуральный или "&
                       «разрешены десятичные числа». &
                       "Пожалуйста, попробуйте еще раз.")
            Конец попытки
    
            'Рассчитайте разницу, причитающуюся клиенту
            'или что покупатель все еще должен магазину
            Разница = AmountTended - SalesTotal
    
            TxtDifference.Текст = CStr (Разница)
        Конец подписки
    Конец класса 
  2. Протестируйте приложение с допустимыми и недопустимыми значениями. Вот пример:

  3. Закройте форму и вернитесь в среду программирования

Исключения в . NET Framework

Большинство библиотек, таких как Borland VCL и Microsoft MFC поставляются со своими собственными классами для обработки исключений.Даже библиотека Win32 предоставляет свой тип механизма для выявления ошибок. Для поддержки исключения .NET Framework предоставляет специальный класс под названием Exception . Как только компилятор обнаруживает ошибку, класс Exception позволяет вам чтобы определить тип ошибки и предпринять соответствующие действия.

Обычно Исключение в основном служит общим класс исключений. Он используется как улов, за которым не следует параметр. Предвидение различных типов проблем, которые могут возникнуть в программа Microsoft произвела различные классы из Exception , чтобы сделать этот вопрос дружелюбнее.В результате почти любой тип исключения, который вы можете У встречи уже есть класс, чтобы справиться с ней. Поэтому, когда ваш программа сталкивается с исключением, вы легко можете определить тип ошибки.

Существует так много классов исключений, которые мы не можем изучить или просмотрите их все. Решение, которое мы будем использовать, - представить или просмотреть класс, когда мы встречаем его тип ошибки.

При обработке исключений ошибки обрабатываются в Поймайте статью . Чтобы использовать его, с правой стороны Catch введите a имя параметра, за которым следует оператор As, за которым следует тип исключение, с которым вы хотите иметь дело.По умолчанию исключение первого типа Исключение . Исходя из этого, типичная формула для реализации исключения обработка:

 Частная подпрограмма CalculateClicked (отправитель ByVal как объект,
                                     ByVal и как EventArgs)
                                     Обрабатывает BtnCalculate.Click
            Тусклый номер как двойной
            Тусклый результат как двойной

            Пытаться

                'Здесь можно обработать обычный ход программы

            Поймать ex как исключение

                'Сделайте здесь исключение

            Конец попытки

Концевой переводник 

Как уже говорилось, когда в возникает исключение Попробуйте раздел , компиляция кода перенесена на Catch раздел.Если вы объявляете исключение как тип Exception , это класс определит ошибку.

Одно из свойств класса Exception : позвонил по номеру , сообщение . Это свойство содержит строку, описывающую тип возникшей ошибки. Затем вы можете использовать это исключение . Сообщение для отображения сообщения об ошибке, если хотите. Вот пример:

 Частная подпрограмма CalculateClicked (отправитель ByVal как объект,
                                     ByVal и как EventArgs)
                                     Обрабатывает BtnCalculate.Нажмите
            Тусклый номер как двойной
            Тусклый результат как двойной

            Пытаться
                Число = CDbl (TxtNumber.Text)
                Результат = Число * 12,48
                TxtResult.Text = CStr (Результат)
            Поймать ex как исключение
                MsgBox (например, сообщение)
            Конец попытки
Концевой переводник 

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

 Частная подпрограмма CalculateClicked (отправитель ByVal как объект,
                                     ByVal и как EventArgs)
                                     Обрабатывает BtnCalculate.Нажмите
            Тусклый номер как двойной
            Тусклый результат как двойной

            Пытаться
                Число = CDbl (TxtNumber.Text)
                Результат = Число * 12,48
                TxtResult.Text = CStr (Результат)
            Поймать ex как исключение
                MsgBox ("Операция не может быть выполнена, потому что" &
                             "введенный вами номер недействителен")
            Конец попытки
Концевой переводник 

Вы также можете комбинировать исключение . Сообщение сообщение и ваше собственное сообщение:

 Частная подпрограмма CalculateClicked (отправитель ByVal как объект,
                                     ByVal и как EventArgs)
                                     Обрабатывает BtnCalculate.Нажмите
            Тусклый номер как двойной
            Тусклый результат как двойной

            Пытаться
                Число = CDbl (TxtNumber.Text)
                Результат = Число * 12,48
                TxtResult.Text = CStr (Результат)
            Поймать ex как исключение
                MsgBox (например, сообщение и
                       vbCrLf & "Операция не может быть выполнена, потому что" &
                       "введенный вами номер недействителен")
            Конец попытки
Концевой переводник 

Обработка ошибок в Excel VBA

Ниже мы рассмотрим две программы в Excel VBA .Одна программа просто игнорирует ошибки . Другая программа продолжает выполнение в указанной строке после обнаружения ошибки.

ситуация:

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

Квадратный корень 1

Добавьте следующие строки кода к командной кнопке «Квадратный корень 1».

1. Сначала мы объявляем два объекта Range.Мы называем объекты Range rng и cell.

Dim rng As Range, cell as Range

2. Инициализируем объект Range rng с выбранным диапазоном.

Установить rng = Выбор

3. Мы хотим вычислить квадратный корень из каждой ячейки в случайно выбранном диапазоне (этот диапазон может быть любого размера). В Excel VBA для этого можно использовать цикл For Each Next. Добавьте следующие строки кода:

Для каждой ячейки In rng

Следующая ячейка

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

4. Добавьте в цикл следующую строку кода.

При ошибке возобновить следующий

5. Затем мы вычисляем квадратный корень из значения. В Excel VBA мы можем использовать для этого функцию Sqr. Добавьте в цикл следующую строку кода.

cell.Value = Sqr (cell.Value)

6. Закройте редактор Visual Basic и протестируйте программу.

Результат:

Заключение: Excel VBA проигнорировал ячейки, содержащие недопустимые значения, такие как отрицательные числа и текст.Без использования оператора «On Error Resume Next» вы получите две ошибки. Будьте осторожны и используйте оператор «On Error Resume Next» только в том случае, если вы уверены, что игнорировать ошибки можно.

Квадратный корень 2

Добавьте следующие строки кода к командной кнопке «Квадратный корень 2».

1. Та же программа, что и квадратный корень 1, но вместо «При ошибке возобновить следующий» на:

При ошибке Перейти к недопустимому значению:

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

2. За пределами цикла For Each Next сначала добавьте следующую строку кода:

Выходной переводник

Без этой строки будет выполнен остальной код (код ошибки), даже если ошибки нет!

3. Excel VBA продолжает выполнение со строки, начинающейся с InvalidValue: при обнаружении ошибки (не забудьте двоеточие). Добавьте следующую строку кода:

InvalidValue:

4.Пока мы сохраняем простой код ошибки. Мы отображаем MsgBox с некоторым текстом и адресом ячейки, в которой произошла ошибка.

MsgBox «не может вычислить квадратный корень из ячейки» и ячейки. Адрес

5. Добавьте следующую строку, чтобы указать Excel VBA возобновить выполнение после выполнения кода ошибки.

Продолжить следующую

6. Закройте редактор Visual Basic и протестируйте программу.

Результат:

VB Core II Условные операторы Обработка исключений Циклы Отладка массивов.

Презентация на тему: «Условные операторы VB Core II Обработка исключений Отладка массивов циклов» - Стенограмма презентации:

1 VB Core II Условные операторы Обработка исключений Циклы Отладка массивов

2 Операторы if If c> 5 Then x = 1 y = 3 End If If c> 5 Then x = 1: y = 3 If c> 5 Then x = 1 y = 3 Else z = 7 End If If If c> 5 Then x = 1 y = 3 Иначе Если c = 4 Тогда z = 7 Иначе x = 9 Конец Если

3 Упражнение - решатель квадратного уравнения Создайте форму с - 3 текстовыми полями для ввода значений для a b и c (и меток в качестве подсказок) 2 метки, где будут отображаться корни Кнопка с надписью «Решить» Код кнопки (функция квадратного корня - sqr)

4 выберите Dim Number Number = 8 'Инициализировать переменную.Выберите номер дела 'Оценка номера. Случай от 1 до 5 'Число от 1 до 5 включительно. x = 4 Случай 6, 7, 8 'Число от 6 до 8. x = 5 Случай от 9 до 10' Число 9 или 10. x = 6 Case Else 'Другие значения. x = 7 Конец выбора

5 Исключение обработки ошибок и исключений = проблемное событие во время выполнения, обычно связанное с вводом-выводом, например, файл не найден, соединение с сервером потеряно, недопустимый ввод пользователя, а не ошибка программирования. VB вызывает ошибки исключения (в отличие от Java) VB не вызывает принудительную обработку исключений

6 Обработчики ошибок - пример - недопустимые числа Private Sub Command1_Click () Dim num1 As Integer Dim num2 As Integer Dim result As Integer On Error GoTo myErrorHandler num1 = Text1.Текст num2 = Text2.Text result = num1 + num2 Label1.Caption = result Exit Sub myErrorHandler: If Err.Number = 13 Then MsgBox ("Пожалуйста, введите действительное число") Else MsgBox (Err.Description) End If Resume Next End Sub Упражнение Попробуйте это в программе калькулятора. Затем выполните деление на ноль (11)


7 Для следующих циклов Dim x как Integer, total As Integer total = 0 Для x = от 1 до 5 всего = всего + x Далее Dim x как Integer, total As Integer total = 0 Для x = от 1 до 5 Шаг 2 всего = всего + x следующий

8 Отладка - отладка.print Debug.print x, y, z Непосредственное окно - CTRL G Упражнение - напишите цикл for next для сложения нечетных чисел от 1 до 9 включительно. Используйте debug.print, чтобы проверить его работу

9 Другие циклы Dim c как целое число c = 1 Do while c <5 c = c + 1 цикл Dim c как целое число c = 1 Do до c> 4 c = c + 1 цикл Dim c как целое число c = 1 Do c = c + 1 цикл пока c <5 Dim c как целое число, x как целое число c = 1 x = 2 Do c = c + 1 цикл до тех пор, пока c> 4 и x <> 3

10 Массивы (фиксированный размер) Dim x (100) как целое число Dim i как целое число Для i = 0 до 100 x (i) = 99 Далее Dim x (от 1 до 3, от 1 до 3) как целое число Dim i как целое, j как целое Для i = от 1 до 3 Для j = от 1 до 3 x (i, j) = 99 Далее

11 Динамические массивы Dim x () As Integer ReDim x (5) Dim i, j As Integer For i = 1 To 5 x (i) = 99 Next ReDim Preserve x (10) For i = 6 To 10 x (i) = 100 следующий

.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *