Remkomplekty.ru

IT Новости из мира ПК
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Excel vba on error

Excel vba on error

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Файл примера

Скачать

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

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

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

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

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

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

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

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

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

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

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

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

Читать еще:  Cells value vba excel

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Что лучше?

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

VBA On Error

Excel VBA On Error Statement

VBA On Error statement is a type of error handling mechanism which is used to guide the code to do what if it encounters any type of error, generally when a code encounters an error the execution stops but with this statement in the code the execution of the code continues as it has set of instructions to do when it encounters an error.

Anticipating the error in the code makes you a pro in VBA coding. You can’t make the code 100% efficient, even if you are confident about your code one or other way it may throw up an error.

It almost an impossible task to identify and handle every kind of error, but we have different ways of handling an error in VBA. While writing the code you may not anticipate the kind of error code can throw up but if any error comes you will up spending more time in debugging than writing the code itself.

What is an Error?

An error is nothing but a line of code cannot be executed because of the functionality or the wrong code. So try to anticipate the error and handle it.

For example, if you try to delete the sheet which is not there then obviously we cannot execute that line of code.

An error is of three types one is compiled error due to undeclared variables. The second one is data entry error due to wrong entries by the coder, and the third one is run time error due to VBA cannot recognize the line of code. For trying to access or work on worksheet or workbook which is not there.

But we have a statement in vba to handle all these kinds of errors i.e. “On Error” statement.

Types of On Error Statements

The key point of handling errors in VBA is the “On Error” statement. For example On Error “resume next line”, “go to or jump to another line”, etc…

On Error statement has three kinds of statements to it.

  1. GoTo 0 means whenever the run time error occurs excel or VBA should display the error message box saying the kind of error it has encountered. As soon as VBA executes the code it disables all the error handlers in that particular block on the code.
  2. Resume Next means whenever the error occurs this statement instructs the excel to ignore that error and move on to (resume next) next line of code without displaying any error messages. It does not mean it will fix the error rather it just ignores the error.
  3. GoTo [label] means whenever VBA encounters an error go to assigned label. This makes the code to jump to the specific line provided by the coder.

Top 3 Ways to Handle Errors in VBA

#1 – On Error Resume Next

Assume you are dividing the value of 20 by 0 and you have declared the variable to assign the result of the division to it.

Excel vba on error

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

  • On Error GoTo строка — Активизирует подпрограмму обработки ошибок, начало которой определяется обязательным аргументом строка, значением которого может быть любая метка строки или номер строки. Если возвращается ошибка выполнения, управление передается на указанную строку и запускается обработчик ошибок. Аргумент строка должен определять строку в той же процедуре, в которой находится инструкция On Error; в противном случае возникает ошибка компиляции.
  • On Error Resume Next — Указывает, что возникновение ошибки выполнения приводит к передаче управления на инструкцию, непосредственно следующую за инструкцией, при выполнении которой возникла ошибка. Рекомендуется при доступе к объектам использовать эту форму инструкции, а не On Error GoTo.
  • On Error GoTo 0 — Отключает любой активизированный обработчик ошибок в текущей процедуре.
Читать еще:  Vlookup vba excel

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

«Включенным» обработчиком ошибок называют подпрограмму, которая указана в инструкции On Error; «активным» обработчиком ошибок является включенный обработчик ошибок, который обрабатывает текущую ошибку. Если ошибка возникает в самом обработчике ошибок (в промежутке между возникновением ошибки и выполнением инструкции Resume, Exit Sub, Exit Function или Exit Property), то обработчик ошибок, определенный в текущей процедуре, не может обработать ошибку. Управление в этом случае возвращается в вызывающую процедуру; если в вызывающей процедуре включен обработчик ошибок, то обработка ошибки передается ему. Если этот обработчик ошибок является в данный момент активным, т.е. уже обрабатывает ошибку, то управление снова передается назад в вызывающую процедуру и т.д. до тех пор, пока не будет найден включенный, но не активный обработчик ошибок. Если включенный, но неактивный обработчик ошибок найден не будет, ошибка становится фатальной в том месте программы, в котором она впервые возникла. При каждой передаче управления обработчиком ошибок в вызывающую процедуру эта процедура становится текущей. После завершения обработки ошибки обработчиком в любой процедуре возобновляется выполнение текущей процедуры с той ее части, которая указана в инструкции Resume.

Подпрограмма обработки ошибок не может быть процедурой Sub или Function. Эта подпрограмма должна быть частью программы, которая отмечается с помощью метки строки или номера строки.

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

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

При обработке ошибок, возникающих при доступе к другим объектам, рекомендуется использовать конструкцию On Error Resume Next, а не конструкцию On Error GoTo. Проверка объекта Err после каждого взаимодействия с другим объектом позволяет устранить неопределенность в том, при доступе к какому объекту возникла ошибка. Это позволяет всегда точно знать, какой объект поместил значение кода ошибки в свойство Err.Number, а также в каком объекте возникла ошибка (эта информация содержится в свойстве Err.Source).

Конструкция On Error GoTo 0 отключает обработку ошибок в текущей процедуре. Эта конструкция не задает переход на строку 0 для обработки ошибок, даже если в процедуре имеется строка с номером 0. Если инструкция On Error GoTo 0 не выполнялась, то обработчик автоматически отключается при выходе из процедуры.

Для того, чтобы предотвратить выполнение программы обработки ошибок в тех случаях, когда ошибка не возникла, следует помещать соответствующую инструкцию Exit Sub, Exit Function или Exit Property сразу после подпрограммы обработки ошибки, как в следующем примере:

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

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

Системные ошибки при вызовах библиотек динамической компоновки (DLL) не приводят к возникновению исключений и не перехватываются средствами Visual Basic. При вызове функций из библиотек DLL необходимо проверять, успешно ли возвращается каждое значение (согласно спецификациям API), и в случае неудачи проверять значение свойства LastDLLError объекта Err.

Правильная обработка ошибок в VBA (Excel)

Я работаю с VBA уже довольно давно, но я все еще не уверен в обработке ошибок.

хорошая статья одна из CPearson.com

однако мне все еще интересно, был ли способ, которым я раньше делал ошибки, / совершенно неправильным: блок 1

предложение if, потому что если это правда, оно будет выполнено, и если это не удастся, Goto перейдет в Else-part, так как Ubound массива никогда не должно быть нуля или меньше, без ошибки, этот метод работал довольно хорошо до сих пор.

если я правильно понял, это должно быть так: Блок 2

или даже такой: Блок 3

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

блок 4

источник следующего кода: CPearson.com

Должно ли это быть как в блоке 3 ?

Спасибо, что прочитали мой вопрос Приветствия skofgar

5 ответов

Я определенно не буду использовать Block1. Кажется неправильным, что блок ошибок в операторе IF не связан с ошибками.

блоки 2,3 & 4, я думаю, вариации на тему. Я предпочитаю использовать блоки 3 & 4 над 2 только из-за нелюбви к оператору GOTO; я обычно использую метод Block4. Это один из примеров кода, который я использую, чтобы проверить, добавлена ли библиотека Microsoft ActiveX Data Objects 2.8 и если не добавить или использовать более раннюю версию, если 2.8 не доступный.

у вас есть один действительно замечательный ответ от ray023, но ваш комментарий, что это, вероятно, перебор, подходит. Для «более светлой» версии.

блок 1 это, ИМХО, плохая практика. Как уже указывалось osknows, смешивание обработки ошибок с кодом нормального пути не является хорошим. Во-первых, если a новая ошибка возникает, когда есть условие ошибки в действительности вы будете не получите возможность справиться с этим (если вы звоните из обычной это также имеет обработчик ошибок, где выполнение будет «пузыриться»).

Блок 2 похоже на имитацию блока Try / Catch. Это должно быть хорошо, но это не путь VBA. Блок 3 является вариацией на блоке 2.

блок 4 — это голая версия пути VBA. Я бы сильно посоветуйте использовать его или что-то в этом роде, потому что это то, что ожидает любой другой программист VBA, наследующий код. Позвольте представить небольшое расширение, однако:

обратите внимание, что второй Resume . Это трюк, которому я научился недавно: это будет никогда выполнить в обычной обработке, так как Resume оператор отправит выполнение в другое место. Однако это может быть находкой для отладки. При получении уведомления об ошибке выберите отладка (или нажмите Ctl-Break, затем выберите отладка при получении сообщения «выполнение было прервано»). Следующий (выделенный) оператор будет либо MsgBox или следующий оператор. Используйте «Set Next Statement» (Ctl-F9), чтобы выделить голый Resume , нажмите клавишу F8. Это покажет вам ровно где произошла ошибка.

Читать еще:  Excel vba value

Что касается вашего возражения против этого формата «прыжки вокруг», а) это то, что программисты VBA ожидают, как указано ранее, & B) ваши подпрограммы должны быть достаточно коротким, чтобы не далеко прыгать.

две основные цели для обработки ошибок:

  1. ошибки ловушки вы можете прогнозировать, но не управлять пользователем от выполнения (например, сохранение файла в thumb drive когда thumb диски был удален)
  2. непредвиденные ошибки, пользователя с формой это сообщает им, в чем проблема есть. Таким образом, они могут передать это сообщение для вас, и вы, возможно, сможете чтобы дать им работу, пока вы работайте над исправлением.

Итак, как бы вы сделали это?

прежде всего, создайте форму ошибки для отображения при возникновении непредвиденной ошибки.

это может выглядеть примерно так (FYI: мой называется frmErrors):

обратите внимание на следующие надписи:

  • lblHeadline
  • lblSource
  • lblProblem
  • lblResponse

кроме того, стандартная команда кнопки:

нет ничего впечатляющего в коде для этой формы:

в основном, вы хотите знать, какую кнопку пользователь нажал, когда форма закрывается.

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

у вас могут быть ошибки, которые будут настроены только для вашего приложения. Это, как правило, будет краткий список ошибок специально только для вашего приложения. Если у вас еще нет модуля констант, создайте модуль, который будет содержать перечисление пользовательских ошибок. (Примечание: Office ‘ 97 не поддерживает перечисления.). Перечисление должно выглядеть примерно так:

создайте модуль, который выдаст ваши пользовательские ошибки.

теперь вы хорошо оснащены, чтобы ловить ошибки в вашей программе. Вы sub (или функция), должны выглядеть примерно так:

копия / вставка кода выше может не работать прямо из ворот, но определенно должна дать вам суть.

кстати, если вам когда-нибудь понадобится, чтобы я сделал логотип вашей компании, посмотрите на меня http://www.MySuperCrappyLogoLabels99.com

Я держу вещи простыми:
На уровне модуля я определяю две переменные и устанавливаю одну в имя самого модуля.

в каждой под / функции модуля я определяю локальную переменную

Я установил ThisRoutineName в имя sub или функции

затем я отправляю все ошибки в ERR_RTN: когда они происходят, но сначала я устанавливаю sLocalErrorMsg, чтобы определить, что такое ошибка, и обеспечить некоторую отладку информация.

в нижней части каждой под / функции я направляю логический поток следующим образом

затем у меня есть отдельный модуль, который я помещаю во все проекты под названием «mod_Error_Handler».

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

Блок 2 не работает, потому что он не сбрасывает обработчик ошибок, потенциально вызывая бесконечный цикл. Для правильной работы обработки ошибок в VBA вам нужно Resume инструкция для очистки обработчика ошибок. The Resume также активирует предыдущий обработчик ошибок. Блок 2 терпит неудачу, потому что новая ошибка возвращается к предыдущему обработчику ошибок, вызывая бесконечный цикл.

Блок 3 терпит неудачу, потому что нет Resume оператор, поэтому любая попытка обработки ошибок после этого будет неудача.

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

но вот еще один способ обработки ошибки в VBA. Он обрабатывает ошибку inline как Try/Catch in VB.net есть несколько подводных камней, но правильно управляемый он работает довольно мило.

ключ к этой работе-использовать Resume заявление сразу за другим On Error заявление. The Resume это в обработчике ошибок и отвлекает код EndTry1 метки. Вы должны немедленно установить другой On Error оператор, чтобы избежать проблем, как предыдущий обработчик ошибок будет «возобновить». То есть он будет активен и готов к обработке очередной ошибки. Это может привести к повторению ошибки и вводу бесконечного цикла.

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

How to dou

3. «ОСНОВЫ VBA: Условные операторы»

Table of Contents:

Когда вам нужно иметь дело с ошибками в Excel VBA, вы можете использовать оператор OnError. Однако есть несколько вещей, которые вам нужно знать в первую очередь. Вы можете использовать оператор On Error тремя способами.

Возобновление после ошибки

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

Чтобы восстановить ошибку, вы должны использовать оператор Resume. Это очищает условие ошибки и позволяет продолжить выполнение в определенном месте. Вы можете использовать оператор Resume тремя способами.

В следующем примере используется оператор Resume после возникновения ошибки:

Эта процедура имеет другую метку: TryAgain.Если возникает ошибка, выполнение продолжается на ярлыке BadEntry, и в коде отображается сообщение ниже. Если пользователь отвечает, нажав «Да», оператор Resume запустится, и выполнение вернется к метке TryAgain. Если пользователь нажимает «Нет», процедура заканчивается.

Если возникает ошибка, пользователь может решить, следует ли повторить попытку.

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

Оператор Resume очищает условие ошибки перед продолжением. Чтобы увидеть это, попробуйте подставить следующий оператор для второго оператора в предыдущем примере:

Код работает неправильно, если вы используете GoTo, а не Resume. Чтобы продемонстрировать, введите отрицательное число. Вы получите сообщение об ошибке. Нажмите «Да», чтобы повторить попытку, а затем введите другой отрицательный номер. Эта вторая ошибка не попадает в ловушку, потому что исходное условие ошибки не было очищено.

Обработка ошибок в двух словах

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

Он начинается сразу после метки, указанной в инструкции On Error.

Он должен быть достигнут вашим макросом только в случае возникновения ошибки. Это означает, что вы должны использовать инструкцию, такую ​​как Exit Sub или Exit Function, непосредственно перед меткой.

Для этого может потребоваться оператор Resume. Если вы решите не прерывать процедуру при возникновении ошибки, вы должны выполнить оператор Resume перед возвратом к основному коду.

Знание того, когда игнорировать ошибки

В некоторых случаях вполне нормально игнорировать ошибки. Именно тогда вступает в действие оператор On Error Resume Next.

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

В этом случае вы можете просто пропустить любую ячейку, содержащую значение, которое невозможно преобразовать в квадратный корень. Вы можете создавать всевозможные возможности проверки ошибок, используя структуры If-Then, но вы можете разработать лучшее (и более простое) решение, просто игнорируя возникающие ошибки.

Следующая процедура выполняет это с помощью оператора On Error Resume Next:

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

Ссылка на основную публикацию
ВсеИнструменты
Adblock
detector
×
×