Меню

Vba продолжить если ошибка

Обработка ошибок в VBA Excel с помощью оператора On Error. Синтаксис выражений с оператором On Error. Пример кода с простым обработчиком ошибок.

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

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

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

Синтаксис выражений с On Error

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

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

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

Простой обработчик ошибок

Шаблон простейшего обработчика ошибок:

Sub Primer()

On Error GoTo Stroka

    ‘Блок операторов процедуры

Exit Sub

Stroka:

    MsgBox «Произошла ошибка: « & Err.Description

End Sub

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

Оператор Exit Sub обеспечивает выход из процедуры, если блок операторов выполнен без ошибок. Для вывода описания ошибки используется свойство Description объекта Err.

Примеры обработки ошибок

Пример 1
Деление на ноль:

Sub Primer1()

On Error GoTo Инструкция

    Dim a As Double

    a = 45 / 0

Exit Sub

Instr:

    MsgBox «Произошла ошибка: « & Err.Description

End Sub

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

Пример 2
Выход за границы диапазона:

Sub Primer2()

On Error GoTo Instr

    Dim myRange As Range

    Set myRange = Range(«A1:D4»).Offset(2)

Exit Sub

Instr:

    MsgBox «Произошла ошибка: « & Err.Description

End Sub

Результат выполнения кода VBA Excel с оператором On Error GoTo:

Пример использования выражений On Error Resume Next и On Error GoTo 0 смотрите в статье: Отбор уникальных значений с помощью Collection.

In this Article

  • VBA Errors Cheat Sheet
    • Errors
  • VBA Error Handling
  • VBA On Error Statement
    • On Error GoTo 0
    • On Error Resume Next
    • Err.Number, Err.Clear, and Catching Errors
      • Error Handling with Err.Number
    • On Error GoTo Line
      • On Error Exit Sub
      • Err.Clear, On Error GoTo -1,  and Resetting Err.Number
      • VBA On Error MsgBox
  • VBA IsError
  • If Error VBA
  • VBA Error Types
    • Runtime Errors
    • Syntax Errors
    • Compile Errors
    • Debug > Compile
    • OverFlow Error
  • Other VBA Error Terms
    • VBA Catch Error
    • VBA Ignore Error
    • VBA Throw Error / Err.Raise
    • VBA Error Trapping
    • VBA Error Message
    • VBA Error Handling in a Loop
  • VBA Error Handling in Access

VBA Errors Cheat Sheet

Errors

On Error – Stop code and display error

On Error Goto 0

On Error – Skip error and continue running

On Error Resume Next

On Error – Go to a line of code [Label]

On Error Goto [Label]

Clears (Resets) Error

On Error GoTo1

Show Error number

MsgBox Err.Number

Show Description of error

MsgBox Err.Description

Function to generate own error

Err.Raise

See more VBA “Cheat Sheets” and free PDF Downloads

VBA Error Handling

VBA Error Handling refers to the process of anticipating, detecting, and resolving VBA Runtime Errors. The VBA Error Handling process occurs when writing code, before any errors actually occur.

VBA Runtime Errors are errors that occur during code execution. Examples of runtime errors include:

  • Referencing a non-existent workbook, worksheet, or other object (Run-time Error 1004)
  • Invalid data ex. referencing an Excel cell containing an error (Type Mismatch – Run-time Error 13)
  • Attempting to divide by zero

VBA On Error Statement

Most VBA error handling is done with the On Error Statement. The On Error statement tells VBA what to do if it encounters an error. There are three On Error Statements:

  • On Error GoTo 0
  • On Error Resume Next
  • On Error GoTo Line

On Error GoTo 0

On Error GoTo 0 is VBA’s default setting. You can restore this default setting by adding the following line of code:

On Error GoTo 0

When an error occurs with On Error GoTo 0, VBA will stop executing code and display its standard error message box.

vba runtime error 13

Often you will add an On Error GoTo 0 after adding On Error Resume Next error handling (next section):

Sub ErrorGoTo0()

On Error Resume Next
    ActiveSheet.Shapes("Start_Button").Delete
On Error GoTo 0

'Run More Code

End Sub

On Error Resume Next

On Error Resume Next tells VBA to skip any lines of code containing errors and proceed to the next line.

On Error Resume Next

Note: On Error Resume Next does not fix an error, or otherwise resolve it. It simply tells VBA to proceed as if the line of code containing the error did not exist. Improper use of On Error Resume Next can result in unintended consequences.

A great time to use On Error Resume Next is when working with objects that may or may not exist. For example, you want to write some code that will delete a shape, but if you run the code when the shape is already deleted, VBA will throw an error. Instead you can use On Error Resume Next to tell VBA to delete the shape if it exists.

On Error Resume Next
    ActiveSheet.Shapes("Start_Button").Delete
On Error GoTo 0

Notice we added On Error GoTo 0 after the line of code containing the potential error. This resets the error handling.

In the next section we’ll show you how to test if an error occurred using Err.Number, giving you more advanced error handling options.

VBA Coding Made Easy

Stop searching for VBA code online. Learn more about AutoMacro — A VBA Code Builder that allows beginners to code procedures from scratch with minimal coding knowledge and with many time-saving features for all users!

automacro

Learn More

Err.Number, Err.Clear, and Catching Errors

Instead of simply skipping over a line containing an error, we can catch the error by using On Error Resume Next and Err.Number.

Err.Number returns an error number corresponding with the type of error detected. If there is no error, Err.Number = 0.

For example, this procedure will return “11” because the error that occurs is Run-time error ’11’.

Sub ErrorNumber_ex()

On Error Resume Next
ActiveCell.Value = 2 / 0
MsgBox Err.Number

End Sub

vba run-time error 11 err.number

Error Handling with Err.Number

The true power of Err.Number lies in the ability to detect if an error occurred (Err.Number <> 0).  In the example below, we’ve created a function that will test if a sheet exists by using Err.Number.

Sub TestWS()
    MsgBox DoesWSExist("test")
End Sub

Function DoesWSExist(wsName As String) As Boolean
    Dim ws As Worksheet
    
    On Error Resume Next
    Set ws = Sheets(wsName)
    
    'If Error WS Does not exist
    If Err.Number <> 0 Then
        DoesWSExist = False
    Else
        DoesWSExist = True
    End If

    On Error GoTo -1
End Function

Note: We’ve added a On Error GoTo -1 to the end which resets Err.Number to 0 (see two sections down).

With On Error Resume Next and Err.Number, you can replicate the “Try” & “Catch” functionality of other programming languages.

On Error GoTo Line

On Error GoTo Line tells VBA to “go to” a labeled line of code when an error is encountered.  You declare the Go To statement like this (where errHandler is the line label to go to):

On Error GoTo errHandler

and create a line label like this:

errHandler:

Note: This is the same label that you’d use with a regular VBA GoTo Statement.

Below we will demonstrate using On Error GoTo Line to Exit a procedure.

On Error Exit Sub

You can use On Error GoTo Line to exit a sub when an error occurs.

You can do this by placing the error handler line label at the end of your procedure:

Sub ErrGoToEnd()

On Error GoTo endProc

'Some Code
    
endProc:
End Sub

or by using the Exit Sub command:

Sub ErrGoToEnd()

On Error GoTo endProc

'Some Code
GoTo skipExit
    
endProc:
Exit Sub

skipExit:

'Some More Code

End Sub

Err.Clear, On Error GoTo -1,  and Resetting Err.Number

After an error is handled, you should generally clear the error to prevent future issues with error handling.

After an error occurs, both Err.Clear and On Error GoTo -1 can be used to reset Err.Number to 0. But there is one very important difference: Err.Clear does not reset the actual error itself, it only resets the Err.Number.

What does that mean?  Using Err.Clear, you will not be able to change the error handling setting. To see the difference, test out this code and replace On Error GoTo -1 with Err.Clear:

Sub ErrExamples()

    On Error GoTo errHandler:
        
    '"Application-defined" error
    Error (13)
    
Exit Sub
errHandler:
    ' Clear Error
    On Error GoTo -1
    
    On Error GoTo errHandler2:
    
    '"Type mismatch" error
    Error (1034)
    
Exit Sub
errHandler2:
    Debug.Print Err.Description
End Sub

Typically, I recommend always using On Error GoTo -1, unless you have a good reason to use Err.Clear instead.

VBA On Error MsgBox

You might also want to display a Message Box on error.  This example will display different message boxes depending on where the error occurs:

Sub ErrorMessageEx()
 
Dim errMsg As String
On Error GoTo errHandler

    'Stage 1
    errMsg = "An error occured during the Copy & Paste stage."
    'Err.Raise (11)
    
    'Stage 2
    errMsg = "An error occured during the Data Validation stage."
    'Err.Raise (11)
     
    'Stage 3
    errMsg = "An error occured during the P&L-Building and Copy-Over stage."
    Err.Raise (11)
     
    'Stage 4
    errMsg = "An error occured while attempting to log the Import on the Setup Page"
    'Err.Raise (11)

    GoTo endProc
    
errHandler:
    MsgBox errMsg
   
endProc:
End Sub

Here you would replace Err.Raise(11) with your actual code.

VBA IsError

Another way to handle errors is to test for them with the VBA ISERROR Function. The ISERROR Function tests an expression for errors, returning TRUE or FALSE if an error occurs.

Sub IsErrorEx()
    MsgBox IsError(Range("a7").Value)
End Sub

VBA Programming | Code Generator does work for you!

If Error VBA

You can also handle errors in VBA with the Excel IFERROR Function.  The IFERROR Function must be accessed by using the WorksheetFunction Class:

Sub IfErrorEx()

Dim n As Long
n = WorksheetFunction.IfError(Range("a10").Value, 0)

MsgBox n
End Sub

This will output the value of Range A10, if the value is an error, it will output 0 instead.

VBA Error Types

Runtime Errors

As stated above:

VBA Runtime Errors are errors that occur during code execution. Examples of runtime errors include:

  • Referencing a non-existent workbook, worksheet, or other object
  • Invalid data ex. referencing an Excel cell containing an error
  • Attempting to divide by zero

vba runtime error 13

You can “error handle” runtime errors using the methods discussed above.

Syntax Errors

VBA Syntax Errors are errors with code writing. Examples of syntax errors include:

  • Mispelling
  • Missing or incorrect punctuation

The VBA Editor identifies many syntax errors with red highlighting:

vba syntax error example

The VBA Editor also has an option to “Auto Syntax Check”:

vba syntax error option

When this is checked, the VBA Editor will generate a message box alerting you syntax errors after you enter a line of code:

vba syntax compile error

I personally find this extremely annoying and disable the feature.

Compile Errors

Before attempting to run a procedure, VBA will “compile” the procedure. Compiling transforms the program from source code (that you can see) into executable form (you can’t see).

VBA Compile Errors are errors that prevent the code from compiling.

A good example of a compile error is a missing variable declaration:

vba compile error variable

Other examples include:

  • For without Next
  • Select without End Select
  • If without End If
  • Calling a procedure that does not exist

Syntax Errors (previous section) are a subset of Compile Errors.

AutoMacro | Ultimate VBA Add-in | Click for Free Trial!

Debug > Compile

Compile errors will appear when you attempt to run a Procedure. But ideally, you would identify compile errors prior to attempting to run the procedure.

You can do this by compiling the project ahead of time. To do so, go to Debug > Compile VBA Project.

vba debug compile

The compiler will “go to” the first error. Once you fix that error, compile the project again. Repeat until all errors are fixed.

You can tell that all errors are fixed because Compile VBA Project will be grayed out:

vba compile vbaproject

OverFlow Error

The VBA OverFlow Error occurs when you attempt to put a value into a variable that is too large. For example, Integer Variables can only contain values between -32,768 to 32,768. If you enter a larger value, you’ll receive an Overflow error:

vba overflow error

Instead, you should use the Long Variable to store the larger number.

Other VBA Error Terms

VBA Catch Error

Unlike other programming languages, In VBA there is no Catch Statement. However, you can replicate a Catch Statement by using On Error Resume Next and If Err.Number <> 0 Then. This is covered above in Error Handling with Err.Number.

AutoMacro | Ultimate VBA Add-in | Click for Free Trial!

VBA Ignore Error

To ignore errors in VBA, simply use the On Error Resume Next statement:

On Error Resume Next

However, as mentioned above, you should be careful using this statement as it doesn’t fix an error, it just simply ignores the line of code containing the error.

VBA Throw Error / Err.Raise

To through an error in VBA, you use the Err.Raise method.

This line of code will raise Run-time error ’13’: Type mismatch:

Err.Raise (13)

vba runtime error 13

VBA Error Trapping

VBA Error Trapping is just another term for VBA Error Handling.

VBA Error Message

A VBA Error Message looks like this:

vba runtime error 13

When you click ‘Debug’, you’ll see the line of code that is throwing the error:

vba raise error

AutoMacro | Ultimate VBA Add-in | Click for Free Trial!

VBA Error Handling in a Loop

The best way to error handle within a Loop is by using On Error Resume Next along with Err.Number to detect if an error has occurred (Remember to use Err.Clear to clear the error after each occurrence).

The example below will divide two numbers (Column A by Column B) and output the result into Column C. If there’s an error, the result will be 0.

Sub test()
Dim cell As Range

On Error Resume Next
For Each cell In Range("a1:a10")

    'Set Cell Value
    cell.Offset(0, 2).Value = cell.Value / cell.Offset(0, 1).Value
    
    'If Cell.Value is Error then Default to 0
    If Err.Number <> 0 Then
         cell.Offset(0, 2).Value = 0
         Err.Clear
    End If
 Next
End Sub

VBA Error Handling in Access

All of the above examples work exactly the same in Access VBA as in Excel VBA.

Function DelRecord(frm As Form)
'this function is used to delete a record in a table from a form
   On Error GoTo ending
   With frm
      If .NewRecord Then
         .Undo
         Exit Function
      End If
   End With
   With frm.RecordsetClone
      .Bookmark = frm.Bookmark
      .Delete
      frm.Requery
   End With
   Exit Function
   ending:
   End
End Function

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

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

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

Типы ошибок

Существуют три типа ошибок в программе:

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

Инструкция On Error

Ошибки времени выполнения можно перехватывать внутри подпрограммы. Для этого используется инструкция On Error, которая имеет три формата:

  • On Error GoTo <Метка> — при возникновении ошибки управление передается инструкции, помеченной меткой <Метка>. Метка должна быть допустимым идентификатором, к которому предъявляются такие же требования как и к переменным. Внутри подпрограммы метка указывается в самом начале помечаемой строки и после метки ставится двоеточие. В качестве примера создадим функцию для деления двух целых чисел. Внутри функции предусмотрим обработку ошибки деления на 0:
Function Деление(x As Integer, y As Integer) As Double
   On Error GoTo ПриОшибке
   Деление = x / y
   Exit Function
ПриОшибке:
   Деление = 0
End Function

Если при вызове функции во втором параметре передать значение 0, то управление будет передано в строку, помеченную с помощью метки ПриОшибке. Обратите внимание на то, что метка расположена после инструкции Exit Function. В этом случае код после инструкции Exit Function будет выполнен только в том случае, если возникнет ошибка;

  • On Error Resume Next — при возникновении ошибки управление передается следующей инструкции;
  • On Error GoTo 0 — отключает перехват ошибок.

Если внутри подпрограммы не предусмотрен перехват ошибки, то при возникновении ошибки работа программы прерывается и выводится стандартное окно с описанием и несколькими кнопками: Continue (продолжить), End (завершить выполнение программы), Debug (перейти в режим отладки) и Help (вывод справки).

Инструкция Resume

Инструкция Resume позволяет указать куда следует переходить после обработки ошибки. Инструкция имеет несколько форматов:

  • Resume [0] — управление передается инструкции, вызвавшей ошибку;
  • Resume Next — управление передается инструкции, следующей за инструкцией, вызвавшей ошибку;
  • Resume <Метка> — управление передается инструкции, помеченной меткой <Метка>.

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

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

Вся информация о последней ошибке доступна через объект Err. Объект содержит следующие свойства:

  • Number — код ошибки, например, код 11 для ошибки деления на 0. Если ошибки не произошло, то свойство содержит значение 0;
  • Description — описание ошибки, например, строка "Division by zero" для ошибки деления на 0. Пример вывода кода и описания ошибки:
Debug.Print Err.Number; Err.Description
  • Source — название текущего проекта;
  • HelpFile — путь к файлу справки;
  • HelpContext — идентификатор раздела в справочном файле;
  • LastDLLError — системный код ошибки при работе с DLL.

Объект Err содержит следующие методы:

  • Clear() — очищает всю информацию о последней ошибке. Этот метод следует вызвать после успешной обработки ошибки. Информация об ошибке автоматически очищается при выходе из подпрограммы и ряде других случаев;
  • Raise() — позволяет сгенерировать ошибку в программе. Формат метода:
Raise Number[, Source][, Description][, HelpFile][, HelpContext]

В параметре Number указывается код генерируемой ошибки (целое число от 0 до 65 535). Коды от 0 до 512 зарезервированы под системные ошибки, а остальные коды можно использовать под пользовательские ошибки. Чтобы сгенерировать ошибку с пользовательским кодом необходимо сложить код с константой vbObjectError. Остальные параметры являются необязательными и полностью аналогичны одноименным свойствам объекта Err. Пример генерации и обработки пользовательской ошибки:

Sub ГенерацияОшибки()
   On Error GoTo ПриОшибке
   Err.Raise vbObjectError + 513
   Exit Sub
ПриОшибке:
   Debug.Print Err.Number; Err.Description
   ' -2147220991 Automation error
End Sub

Способы поиска ошибок в программе

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

Первое, на что следует обратить внимание, — на объявления переменных. Например, рассмотрим простой пример:

Как вы думаете, какое значение отобразится в окне Immediate после выполнения этого кода? Думаете, что число 10? Не факт! Вот тут-то и кроется проблема не видная на первый взгляд. В первой инструкции присваивается значение переменной x, имя которой набрано на английской раскладке клавиатуры, а вот во второй инструкции выводится значение переменной x, имя которой набрано на русской раскладке клавиатуры. В результате значение присваивается одной переменной, а выводится значение другой переменной. Такие ситуации очень часто встречаются в программах на языке VBA, так как объявлять переменную не обязательно. Чтобы избежать такой ситуации следует обязательно объявлять переменные явным образом. Контроль за соблюдением этого правила можно возложить на компилятор, добавив в начале модуля следующую инструкцию:

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

Option Explicit
...
Dim x As Integer
x = 10
Debug.Print x ' 10

Далее следует обратить внимание на форматирование кода. Начинающие программисты обычно не обращают на это никакого внимания, считая этот процесс лишним. А на самом деле зря! Компилятору абсолютно все равно, разместите вы все инструкции на одной строке или выполните форматирование кода. Однако, при поиске ошибок форматирование кода позволит найти ошибку гораздо быстрее.

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

Dim Массив As Variant, i As Integer, j As Integer
Массив = Array(Array(0, 1), Array(2, 3), Array(4, 5))
For i = 0 To 2
   For j = 0 To 1
      Debug.Print Массив(i)(j)
   Next
Next

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

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

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

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

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

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

Проверить значение константы позволяет следующая конструкция:

#If MY_DEBUG Then
   ' Здесь размещаем инструкции вывода значений
#End If

Таким образом, меняя значение константы MY_DEBUG с 1 на 0, можно отлючать вывод всех промежуточных значений.

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

Прежде чем начать отладку необходимо пометить строки внутри программы с помощью точек останова. Для добавления точки останова делаем строку активной, а затем из меню Debug выбираем пункт Toggle Breakpoint. Слева от строки появится кружок, обозначающий точку останова. Добавить точку останова можно еще быстрее. Для этого достаточно щелкнуть слева от строки левой кнопкой мыши. Повторный щелчок позволяет удалить точку останова. Кроме того, для добавления или удаления точки отстанова можно воспользоваться клавишей <F9>. Чтобы удалить все точки останова следует из меню View выбрать пункт Clear All Breakpoints.

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

В режиме прерывания можно посмотреть значения различных переменных в окне Locals. Если окно не отображается, то отобразить его можно выбрав в меню View пункт Locals Window. Посмотреть значение переменной можно также если навести указатель мыши на переменную. Значение переменной отобразится во всплывающей подсказке.

При отладке можно контролировать значения отдельных переменных, а не всех сразу. Для этого следует выделить название переменной и из меню Debug выбрать пункт Add Watch. Можно также выделить название переменной и из контектного меню выбрать пункт Add Watch. В открывшемся окне устанавливаем флажок Watch Expression и нажимаем кнопку OK. Значение переменной будет отображаться в окне Watches. Чтобы отобразить окно Watches из меню View выбираем пункт Watch Window. Чтобы отменить отслеживание нужно выделить строку в окне Watches и нажать клавишу <Delete>.

Для пошагового выполнения программы предназначены следующие пункты в меню Debug или соответствующие кнопки на панели инструментов Debug (View | Toolbars | Debug):

  • Step Into (клавиша <F8>) — выполняет переход к следующей инструкции;
  • Step Over — выполняет одну инструкцию. Если в этой инструкции производится вызов подпрограммы, то подпрограмма выполняется за один шаг и отладчик переходит в режим ожидания после выхода из подпрограммы;
  • Step Out — при заходе в подпрограмму этот пункт позволяет выполнить подпрограмму за один шаг и выйти из нее. Отладчик переходит в режим прерывания после выхода из подпрограммы;
  • Run To Cursor — выполняет переход к инструкции, в которой расположен курсор.

Если необходимо посмотреть последовательность вызова подпрограмм, то следует открыть окно Call Stack, выбрав в меню View пункт Call Stack.

Подача звукового сигнала

При возникновении ошибки или при неправильном вводе данных имеет смысл привлечь внимание пользователя звуковым сигналом. Сгенерировать звуковой сигнал позволяет инструкция Beep. Пример:

Dim Результат
Beep
Результат = InputBox("Необходимо ввести значение")

Visual Basic for Applications (VBA)
Статьи по Visual Basic for Applications (VBA)

Избегание условий ошибки

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

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


Избежать ошибки времени выполнения 91 — Объект или С заблокированной переменной блока:

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

Private Sub DoSomething(ByVal target As Worksheet)
    Debug.Print target.Name
End Sub

Если target не назначена ссылка, приведенный выше код вызовет ошибку, которую легко избежать, проверяя, содержит ли объект фактическую ссылку на объект:

Private Sub DoSomething(ByVal target As Worksheet)
    If target Is Nothing Then Exit Sub
    Debug.Print target.Name
End Sub

Если target назначению не присвоена ссылка, то непризнанная ссылка никогда не используется, и ошибка не возникает.

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


Избегайте ошибки времени выполнения 9 — Подкласс вне диапазона:

Эта ошибка возникает при доступе к массиву за пределами его границ.

Private Sub DoSomething(ByVal index As Integer)
    Debug.Print ActiveWorkbook.Worksheets(index)
End Sub

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

Private Sub DoSomething(ByVal index As Integer)
    If index > ActiveWorkbook.Worksheets.Count Or index <= 0 Then Exit Sub
    Debug.Print ActiveWorkbook.Worksheets(index)
End Sub

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

Оператор Error

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

Линейные метки обозначают подпрограммы : потому что подпрограммы исходят из устаревшего кода BASIC и используют GoSub GoTo и GoSub и Return чтобы вернуться к «основной» процедуре, довольно легко написать жесткий код спагетти, если все не строго структурировано , По этой причине лучше всего:

  • процедура имеет одну и только одну подпрограмму обработки ошибок
  • подпрограмма обработки ошибок работает только в состоянии ошибки

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

Private Sub DoSomething()
    On Error GoTo CleanFail

    'procedure code here

CleanExit:
    'cleanup code here
    Exit Sub

CleanFail:
    'error-handling code here
    Resume CleanExit
End Sub

Стратегии обработки ошибок

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

CleanExit:
    Exit Sub

CleanFail:
    Select Case Err.Number
        Case 9
            MsgBox "Specified number doesn't exist. Please try again.", vbExclamation
            Resume
        Case 91
            'woah there, this shouldn't be happening.
            Stop 'execution will break here
            Resume 'hit F8 to jump to the line that raised the error
        Case Else
            MsgBox "An unexpected error has occurred:" & vbNewLine & Err.Description, vbCritical
            Resume CleanExit
    End Select
End Sub

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

Private Sub DoSomething(CheckValue as Long)

    If CheckValue = 0 Then
        On Error GoTo ErrorHandler   ' turn error handling on
        ' code that may result in error
        On Error GoTo 0              ' turn error handling off - same level
    End If

CleanExit:
    Exit Sub

ErrorHandler:
    ' error handling code here
    ' do not turn off error handling here
    Resume

End Sub

Номера строк

VBA поддерживает номера строк в стиле legacy (например, QBASIC). Скрытое свойство Erl можно использовать для идентификации номера строки, которая вызвала последнюю ошибку. Если вы не используете номера строк, Erl только вернет 0.

Sub DoSomething()
10 On Error GoTo 50
20 Debug.Print 42 / 0
30 Exit Sub
40
50 Debug.Print "Error raised on line " & Erl ' returns 20
End Sub

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

Sub DoSomething()
10 On Error GoTo 50
   Debug.Print 42 / 0
30 Exit Sub

50 Debug.Print "Error raised on line " & Erl 'returns 10
End Sub

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

Sub DoSomething()
99997 On Error GoTo 99999
99998 Debug.Print 42 / 0
99999
      Debug.Print Erl   'Prints 34462
End Sub

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

Резюме ключевого слова

Подпрограмма обработки ошибок будет либо:

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

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

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

  • Resume используется отдельно, выполнение продолжается в инструкции, вызвавшей ошибку . Если ошибка на самом деле не обрабатывается , прежде чем делать это, то та же ошибка будет поднят снова, и выполнение может войти в бесконечный цикл.
  • Resume Next продолжает выполнение инструкции сразу после инструкции, вызвавшей ошибку. Если ошибка на самом деле не обрабатывается , прежде чем делать это, то выполнение разрешается продолжать с потенциально недействительными данными, которые могут привести к логическим ошибкам и неожиданному поведению.
  • Resume [line label] продолжает выполнение на указанной метке строки (или номер строки, если вы используете номера строк в стиле устаревшего стиля). Обычно это позволяет выполнить некоторый код очистки до того, как будет чисто выйти из процедуры, например, чтобы закрыть соединение с базой данных, прежде чем вернуться к вызывающему.

Вкл.

Сам оператор On Error может использовать ключевое слово Resume чтобы проинструктировать среду выполнения VBA для эффективного игнорирования всех ошибок .

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

Вышеупомянутый акцент не может быть особо подчеркнут. On Error Resume Next эффективно игнорирует все ошибки и выталкивает их под ковер . Программа, которая взрывается с ошибкой во время выполнения с учетом недопустимого ввода, — это более эффективная программа, чем программа, которая работает с неизвестными / непреднамеренными данными — будь то только потому, что ошибка намного легче идентифицируется. On Error Resume Next можно легко скрыть ошибки .

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

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

On Error Resume Next
[possibly-failing statement]
Err.Clear 'resets current error
On Error GoTo 0

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

Public Sub Caller()
    On Error GoTo Handler
    
    Callee
    
    Exit Sub
Handler:
    Debug.Print "Error " & Err.Number & " in Caller."
End Sub

Public Sub Callee()
    On Error GoTo Handler
    
    Err.Raise 1     'This will be handled by the Callee handler.
    On Error GoTo 0 'After this statement, errors are passed up the stack.
    Err.Raise 2     'This will be handled by the Caller handler.    
    
    Exit Sub
Handler:
    Debug.Print "Error " & Err.Number & " in Callee."
    Resume Next
End Sub

Пользовательские ошибки

Часто при написании специализированного класса вы хотите, чтобы он поднимал свои собственные конкретные ошибки, и вам понадобится чистый способ для кода пользователя / вызова для обработки этих пользовательских ошибок. Оптимальным способом достижения этого является определение специального типа Enum :

Option Explicit
Public Enum FoobarError
    Err_FooWasNotBarred = vbObjectError + 1024
    Err_BarNotInitialized
    Err_SomethingElseHappened
End Enum

Используя встроенную константу vbObjectError пользовательские коды ошибок не перекрываются с зарезервированными / существующими кодами ошибок. Необходимо явно указать только первое значение перечисления, поскольку базовое значение каждого члена Enum 1 больше, чем предыдущий элемент, поэтому базовое значение Err_BarNotInitialized неявно является vbObjectError + 1025 .

Повышение собственных ошибок времени выполнения

Ошибка выполнения может быть повышена с Err.Raise оператора Err.Raise , поэтому пользовательская ошибка Err_FooWasNotBarred может быть повышена следующим образом:

Err.Raise Err_FooWasNotBarred

Метод Err.Raise также может принимать пользовательские параметры Description и Source — по этой причине рекомендуется также определять константы для хранения каждого пользовательского описания ошибки:

Private Const Msg_FooWasNotBarred As String = "The foo was not barred."
Private Const Msg_BarNotInitialized As String = "The bar was not initialized."

А затем создайте выделенный частный метод для повышения каждой ошибки:

Private Sub OnFooWasNotBarredError(ByVal source As String)
    Err.Raise Err_FooWasNotBarred, source, Msg_FooWasNotBarred
End Sub

Private Sub OnBarNotInitializedError(ByVal source As String)
    Err.Raise Err_BarNotInitialized, source, Msg_BarNotInitialized
End Sub

После этого реализация класса может просто вызвать эти специализированные процедуры для повышения ошибки:

Public Sub DoSomething()
    'raises the custom 'BarNotInitialized' error with "DoSomething" as the source:
    If Me.Bar Is Nothing Then OnBarNotInitializedError "DoSomething"
    '...
End Sub

Клиентский код может обрабатывать Err_BarNotInitialized как и любую другую ошибку, внутри своей собственной подпрограммы обработки ошибок.


Примечание: наследие Error ключевое слово также может быть использован вместо Err.Raise , но это устаревшее / осуждается.

 

Framed

Пользователь

Сообщений: 223
Регистрация: 25.01.2018

#1

04.03.2019 19:39:20

Коллеги, приветствую,

Немного запутался в теме про обработчик ошибок, хотя, скорее всего, я нашёл ответ на вопрос в

этой теме

, просто не могу его понять до конца.

Необходимо, чтобы в случае ошибки, которая возникает в определенный момент в коде, часть кода пропускалась, появлялся MsgBox с определенным текстом, после чего макрос продолжал бы работать в нормальном режиме (если будет какая-нибудь другая ошибка далее — выскочит диалоговое окно).

Знаю, что задача простая, ну вот туплю что-то…

Код
            On Error GoTo ErrorHandler            
            Set iWb = GetObject("C:UsersA670669DesktopSCR_Managers.xlsx")
            iLastRowSCR = iWb.Sheets(1).Cells(Rows.Count, 1).End(xlUp).row
            Set iBodySCR = iWb.Sheets(1).Range("B2:M" & iLastRowSCR)
            iWb.Names.Add Name:="BodySCR", RefersTo:=iBodySCR
            With .ListColumns("Rate").DataBodyRange
                .Formula = "=IFERROR(VLOOKUP(A3,SCR_Managers.xlsx!BodySCR,12,0),0)"
                .Cells.Value = .Cells.Value
            End With
            iWb.Close False
ErrorHandler:
            MsgBox "Произошла ошибка"
            On Error Resume Next

На данный момент все как надо, только вот когда даже ошибки нет вылезает MsgBox.

Заранее спасибо.

P.S. Как-то криво написал название темы, должна была быть VBA: Обработчик ошибок, пропуск кода и продолжение выполнения макроса.

Изменено: Framed05.03.2019 00:54:10

 

Anchoret

Пользователь

Сообщений: 1034
Регистрация: 01.01.1970

Anchoret

#2

04.03.2019 19:44:33

Код
On Error Resume Next
If Err then Goto ...
 

Framed

Пользователь

Сообщений: 223
Регистрация: 25.01.2018

#3

04.03.2019 19:52:06

Anchoret, вот так?

Код
 On Error Resume Next
            MsgBox "Произошла ошибка"
            If Err Then GoTo ErrorHandler
            Set iWb = GetObject("C:UsersA670669DesktopSCR_Managers.xlsx")
            iLastRowSCR = iWb.Sheets(1).Cells(Rows.Count, 1).End(xlUp).row
            Set iBodySCR = iWb.Sheets(1).Range("B2:M" & iLastRowSCR)
            iWb.Names.Add Name:="BodySCR", RefersTo:=iBodySCR
            With .ListColumns("Rate").DataBodyRange
                .Formula = "=IFERROR(VLOOKUP(A3,SCR_Managers.xlsx!BodySCR,12,0),0)"
                .Cells.Value = .Cells.Value
            End With
            iWb.Close False
ErrorHandler:






 

Sanja

Пользователь

Сообщений: 14837
Регистрация: 10.01.2013

#4

04.03.2019 19:54:37

Цитата
Framed написал: только вот когда даже ошибки нет вылезает MsgBox

Обработчик ошибок поместите в самый конец кода, а перед ним должна быть строка Exit Sub

Код
On Error GoTo ErrorHandler
    Set iWb = GetObject("C:UsersA670669DesktopSCR_Managers.xlsx")
    iLastRowSCR = iWb.Sheets(1).Cells(Rows.Count, 1).End(xlUp).Row
    Set iBodySCR = iWb.Sheets(1).Range("B2:M" & iLastRowSCR)
    iWb.Names.Add Name:="BodySCR", RefersTo:=iBodySCR
    With .ListColumns("Rate").DataBodyRange
        .Formula = "=IFERROR(VLOOKUP(A3,SCR_Managers.xlsx!BodySCR,12,0),0)"
        .Cells.Value = .Cells.Value
    End With
    iWb.Close False
    Exit Sub
'обработчик ошибок
ErrorHandler:
    MsgBox "Произошла ошибка"
End Sub

Согласие есть продукт при полном непротивлении сторон.

 

Framed

Пользователь

Сообщений: 223
Регистрация: 25.01.2018

#5

04.03.2019 20:03:30

Sanja, спасибо, но разве Exit Sub не остановит выполнение всего макроса, если ошибки не будет?

Я уточню, а то мне кажется, я плохо объяснил в шапке.

Код
'Код
'Код
'Код
 On Error GoTo ErrorHandler
            Set iWb = GetObject("C:UsersA670669DesktopSCR_Managers.xlsx")
            iLastRowSCR = iWb.Sheets(1).Cells(Rows.Count, 1).End(xlUp).row
            Set iBodySCR = iWb.Sheets(1).Range("B2:M" & iLastRowSCR)
            iWb.Names.Add Name:="BodySCR", RefersTo:=iBodySCR
            With .ListColumns("Rate").DataBodyRange
                .Formula = "=IFERROR(VLOOKUP(A3,SCR_Managers.xlsx!BodySCR,12,0),0)"
                .Cells.Value = .Cells.Value
            End With
            iWb.Close False
ErrorHandler:
            MsgBox "Произошла ошибка"
'Код
'Код
'Код

Выполняется макрос, и вот на 5 строке может выскочить ошибка, например, если файла нет, или его имя неверное. Мне нужно, чтобы в этом случае, часть кода 5-13 строка игнорировалась, не выполнялась и выскочил бы MsgBox c текстом, например, «Нет файла или имя некорректно». Далее код, который идет после ErrorHandler должен выполняться в обычном режиме (обычный режим для меня — это когда дальнейшие ошибки не вернут меня к ErrorHandler, простите за убогое объяснение).

В случае же, если ошибки на 5 строке моего примера не возникнет — код работает в штатном режиме.

Изменено: Framed04.03.2019 20:03:53

 

Anchoret

Пользователь

Сообщений: 1034
Регистрация: 01.01.1970

Anchoret

#6

04.03.2019 20:06:40

Framed,

Код
On Error Resume Next

перед строкой, в которой вероятна ошибка

Код
If Err then Goto ...

после такой строки. Ну и замечание от Sanja,

 

Framed

Пользователь

Сообщений: 223
Регистрация: 25.01.2018

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

 

БМВ

Модератор

Сообщений: 20890
Регистрация: 28.12.2016

Excel 2013, 2016

#8

04.03.2019 20:25:02

только наверно так

Код
'Код
'Код
'Код
 On Error resume next
            Set iWb = GetObject("C:UsersA670669DesktopSCR_Managers.xlsx")
            if err =0 then
                 iLastRowSCR = iWb.Sheets(1).Cells(Rows.Count, 1).End(xlUp).row
                 Set iBodySCR = iWb.Sheets(1).Range("B2:M" & iLastRowSCR)
                iWb.Names.Add Name:="BodySCR", RefersTo:=iBodySCR
                With .ListColumns("Rate").DataBodyRange
                    .Formula = "=IFERROR(VLOOKUP(A3,SCR_Managers.xlsx!BodySCR,12,0),0)"
                    .Cells.Value = .Cells.Value
                End With
                iWb.Close False
           else
                MsgBox "Произошла ошибка"
                err.clear  '  или on error goto 0
          end if
'Код
'Код
'Код
 

По вопросам из тем форума, личку не читаю.

 

Framed

Пользователь

Сообщений: 223
Регистрация: 25.01.2018

БМВ, спасибо, все отлично, только теперь в случае ошибки ниже End If, VBA продолжит выполнение кода, даже если, к примеру, название листа out of range и так далее.  

 

БМВ

Модератор

Сообщений: 20890
Регистрация: 28.12.2016

Excel 2013, 2016

Framed,  я не зря там написал ‘  или on error goto 0
В зависимости от потребностей или сбросить ошибку или и сбросить и прекратить обработку ошибок.
Конечно и через переход на метки можно сделать, но я отвык.

Изменено: БМВ04.03.2019 20:49:50

По вопросам из тем форума, личку не читаю.

 

Framed

Пользователь

Сообщений: 223
Регистрация: 25.01.2018

#11

04.03.2019 20:52:16

БМВ, простите, я проглядел. Спасибо большое за помощь, теперь я понял больше, без вас не разобрался бы.

Цитата
БМВ написал: Конечно и через переход на метки можно сделать, но я отвык.

Я где-то читал, что метки не приветствуются в VBA. Да и мне привычнее с операторами условия  :)  

 

БМВ

Модератор

Сообщений: 20890
Регистрация: 28.12.2016

Excel 2013, 2016

По вопросам из тем форума, личку не читаю.

 

vikttur

Пользователь

Сообщений: 47199
Регистрация: 15.09.2012

#13

05.03.2019 00:23:09

Цитата
Framed написал: метки не приветствуются в VBA.

Метки не беда, если не злоупотреблять и если они не нарушаюют (

не сильно нарушают

) структуру кода

 

Nordheim

Пользователь

Сообщений: 3154
Регистрация: 18.04.2017

Причина ошибки в данном куске кода в чем заключается?

«Все гениальное просто, а все простое гениально!!!»

 

Framed

Пользователь

Сообщений: 223
Регистрация: 25.01.2018

Nordheim, потенциально ошибка в том, что файл с таким названием может отсутствовать на рабочем столе у юзера. Этот файл (если он есть) в моем коде открывается, оттуда ВПР-ом подтягивается информация, после чего он закрывается. Если такого файла нет — мне нужно было, чтобы:

1. Выводилось сообщение со специальным текстом, т.е. MsgBox;
2. Пропускался кусок кода (который открывает файл, создает именной диапазон для ВПР, подтягивает куда надо данные с этого листа с помощью ВПР, превращает формулы в значения и закрывает книгу);
3. Макрос снова бы работал в обычном режиме (то есть в режиме «on error go to 0»).

Вообще, мне помогли и тему можно было закрывать, но раз уж вы спросили :)

БМВ, да, и я даже прочитал это несколько раз перед тем, как создать тему. Просто, откровенно говоря, не доходило до меня, как это правильно использовать; примеры из гугла не добавили ясности. Одним словом, еще учиться и учиться.

Изменено: Framed05.03.2019 14:33:07

 

Nordheim

Пользователь

Сообщений: 3154
Регистрация: 18.04.2017

#16

05.03.2019 14:45:40

Цитата
Framed написал:
Nordheim , потенциально ошибка в том, что файл с таким названием может отсутствовать на рабочем столе у юзера.

А если так:

Код
Sub test()
    Dim fname$, iPath$
    iPath = "C:UsersA670669DesktopSCR_Managers.xlsx"
    fname = Dir(iPath)
    If fname <> "" Then
        'обработка если файл существует
    Else: MsgBox "Произошла ошибка"
    End If
End Sub

Никакого On Error

PS:
Обработчик ошибок это конечно хорошо, вставил в начало и никаких проблем с кодом, зато потом вылезет какая ни-будь

«бяка»

в отчетах.

Изменено: Nordheim05.03.2019 14:48:24

«Все гениальное просто, а все простое гениально!!!»

 

Jack Famous

Пользователь

Сообщений: 10382
Регистрация: 07.11.2014

OS: Win 8.1 Корп. x64 | Excel 2016 x64: | Browser: Chrome

#17

05.03.2019 15:02:02

Framed, очень много чего вам посоветовали — лень читать всё))
1. В большинстве случаев от меток можно абсолютно безболезненно избавится, но иногда они помогают. Например, можно избежать «ветвления» кода далеко «вправо» — вот

ссылка

на тему с холиваром)))

Итак, в чём проблема… Всё просто — код доходит до строки ErrorHandler: MsgBox «Произошла ошибка» и выводит сообщение об ошибке (как и должен). Чтобы этого избежать, я обычно делаю, как в #4 (Sanja), но можно и «в лоб» обойти:

Код
GoTo nx
            iWb.Close False
ErrorHandler:
            MsgBox "Произошла ошибка"
nx:

— в таком случае, если мы дошли до GoTo nx, то просто «перепрыгиваем» ErrorHandler на метку nx. Если же произойдёт ошибка, то макрос «перепрыгнет» уже к метке ErrorHandler, минуя GoTo nx.

P.S.:

скорее всего, в вашем случае никакого On Error GoTo ErrorHandler не нужно — это подтверждает и наличие примеров, где легко без него можно обойтись. Я использую метки в основном, если нужно вернуться «выше по коду» (повтор ввода информации пользователем в случае ошибки) или, как уже сказал, чтобы избежать «ветвления» (многоуровневых вложенных «If—Else—End If»).
Но дело (как кодить) исключительно ВАШЕ  ;)

Изменено: Jack Famous05.03.2019 15:34:40

Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄

 

БМВ

Модератор

Сообщений: 20890
Регистрация: 28.12.2016

Excel 2013, 2016

#18

05.03.2019 15:21:22

Nordheim,
тут есть подвох, я с таким встречаюсь регулярно (правда не со скриптамии, но не суть)

Код
    iPath = "C:UsersA670669DesktopГод 2019Документы раздолбая" _
          & "Результаты совещания по вопросам бездумного использования длинных имен файлов и каталогов" _
          & "Выступление главного систематизатора……SCR_Managers.xlsx"

Короче, при полном пути более 260 символов, файл есть, он виден, но открыть его не возможно, впрочем как и скопировать или удалить, понятно что лучше в этом случае обработать длину пути, но порой проще просто обратится и обработать ошибку.
Вариант 2, это уже последствия сетевого доступа к общим файлам. При переносе файлов или каталогов права не наследуются от каталога в который поместили файлы , а сохраняются прежними. Это может привести к тому что также видеть видно, а вот прочесть никак. И в этом случае без обработки ошибки не обойтись.

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

Jack Famous, так как я родом из VBS, а там нет Resume, то перешел на метку по ошибке, обратно не вернешься, что означает не продолжить с того же места. а это означает или куча меток и отдельные обработчики для каждой ошибки или …..

По вопросам из тем форума, личку не читаю.

 

Jack Famous

Пользователь

Сообщений: 10382
Регистрация: 07.11.2014

OS: Win 8.1 Корп. x64 | Excel 2016 x64: | Browser: Chrome

#19

05.03.2019 15:32:09

Цитата
БМВ: я родом из VBS

а я, стало быть, из VBA и могу использовать крутые штуки типа возврата наверх))

Вот такая, например

Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄

 

Nordheim

Пользователь

Сообщений: 3154
Регистрация: 18.04.2017

#20

05.03.2019 15:32:29

БМВ, На сколько я понимаю в данном случае путь прописывается руками, и визуально видно сколько символов.

Цитата
БМВ написал:
при полном пути более 260 символов, файл есть, он виден, но открыть его не возможно

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

«Все гениальное просто, а все простое гениально!!!»

 

БМВ

Модератор

Сообщений: 20890
Регистрация: 28.12.2016

Excel 2013, 2016

#21

05.03.2019 16:15:03

Цитата
Nordheim написал:
На сколько я понимаю в данном случае путь прописывается руками, и визуально видно сколько символов

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

По вопросам из тем форума, личку не читаю.

 

Казанский

Пользователь

Сообщений: 8839
Регистрация: 11.01.2013

#22

05.03.2019 16:56:51

Цитата
БМВ написал:
так как я родом из VBS, а там нет Resume, то перешел на метку по ошибке, обратно не вернешься

Забыл, забыл ты свою родину ;) Нет там меток, и GoTo только в конструкции On Error GoTo 0.

 

Framed

Пользователь

Сообщений: 223
Регистрация: 25.01.2018

Jack Famous, спасибо за разъяснения;
Nordheim, вам тоже большое спасибо, на самом деле, мне очень понравилось это решение, как и решение участника БМВ.
БМВ, спасибо за полезную информацию про ограничение.

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

 

БМВ

Модератор

Сообщений: 20890
Регистрация: 28.12.2016

Excel 2013, 2016

#24

05.03.2019 18:47:08

Цитата
Казанский написал:
Забыл, забыл ты свою родину

🙂 вооот , там даже шанса не было 🙂 По сему и не применяю 🙂

По вопросам из тем форума, личку не читаю.

 

Nordheim

Пользователь

Сообщений: 3154
Регистрация: 18.04.2017

#25

05.03.2019 19:11:54

Цитата
Framed написал:
(а вот это им придется делать в любом случае самим, увы)

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

«Все гениальное просто, а все простое гениально!!!»

 

RAN

Пользователь

Сообщений: 7081
Регистрация: 21.12.2012

#26

05.03.2019 19:48:22

Цитата
БМВ написал:
Короче, при полном пути более 260 символов

Еще короче. Для Exsel, кажется, 218 символов. Попадал.  :D

 

БМВ

Модератор

Сообщений: 20890
Регистрация: 28.12.2016

Excel 2013, 2016

#27

06.03.2019 08:03:50

Off

Цитата
RAN написал:
Для Exsel, кажется, 218 символов

Это не совсем про файл, а скорее про обращение к нему из самого Excel

https://support.microsoft.com/en-us/help/213983/error-message-when-you-open-or-save-a-file-in-microsoft-excel-filename

This behavior is based on a 256-character limitation in Excel for creating links to another file. This limit of 218 characters for the path name is based on the following:•Up to 31 characters in a sheet name.

•Apostrophes and brackets used to denote the workbook name.

•An exclamation point.

•A cell reference.

For example, the path for a file might resemple the following:

  ‘c:excelpersonal…[my workbook.xls]up_to_31_char_sheetname’!$A$1

Если перевести кратко, то, для работы с другой книгой, ссылка не может быть больше 256 символов, включая дополнительные символы (скобки,апострофы, восклицательный знак), имя листа  и диапазон.   если учесть что  Адрес может быть $AAA$1000000 (12 сим) +31 на имя листа + 5 на спец символы, то на путь останется менее 218ти
256-12-31-5=208

По вопросам из тем форума, личку не читаю.

 

Nordheim

Пользователь

Сообщений: 3154
Регистрация: 18.04.2017

#28

06.03.2019 08:54:26

В дополнении  

Цитата
Nordheim написал:
А если написать юзерам что бы сохранили файл с макросом и файл из которого берутся данные, в одну папку

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

Прикрепленные файлы

  • Книга1.xlsm (16.3 КБ)

«Все гениальное просто, а все простое гениально!!!»

 

Framed

Пользователь

Сообщений: 223
Регистрация: 25.01.2018

#29

13.03.2019 17:36:49

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

Цитата
Nordheim написал:
А если написать юзерам что бы сохранили файл с макросом

Файлы не с макросом, потому что модуль с ним находится в личной книге макросов.

Цитата
Nordheim написал:
Как вариант, можно сделать выбор файла.

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

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

 

Jack Famous

Пользователь

Сообщений: 10382
Регистрация: 07.11.2014

OS: Win 8.1 Корп. x64 | Excel 2016 x64: | Browser: Chrome

#30

13.03.2019 18:02:32

Framed, если вопрос не связан с темой (Обработчик ошибок, пропуск куска кода), то создавайте новую

Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄

Содержание

  1. On Error Statement (Visual Basic)
  2. Syntax
  3. Parts
  4. Remarks
  5. Number Property
  6. Throw Statement
  7. On Error Resume Next
  8. On Error GoTo 0
  9. On Error GoTo -1
  10. Untrapped Errors
  11. Оператор On Error (Visual Basic)
  12. Синтаксис
  13. Компоненты
  14. Комментарии
  15. Свойство Number
  16. Оператор Throw
  17. При следующей ошибке возобновление
  18. При ошибке GoTo 0
  19. При ошибке goTo -1
  20. Неисправляемые ошибки

On Error Statement (Visual Basic)

Enables an error-handling routine and specifies the location of the routine within a procedure; can also be used to disable an error-handling routine. The On Error statement is used in unstructured error handling and can be used instead of structured exception handling. Structured exception handling is built into .NET, is generally more efficient, and so is recommended when handling runtime errors in your application.

Without error handling or exception handling, any run-time error that occurs is fatal: an error message is displayed, and execution stops.

The Error keyword is also used in the Error Statement, which is supported for backward compatibility.

Syntax

Parts

Term Definition
GoTo line Enables the error-handling routine that starts at the line specified in the required line argument. The line argument is any line label or line number. If a run-time error occurs, control branches to the specified line, making the error handler active. The specified line must be in the same procedure as the On Error statement or a compile-time error will occur.
GoTo 0 Disables enabled error handler in the current procedure and resets it to Nothing .
GoTo -1 Disables enabled exception in the current procedure and resets it to Nothing .
Resume Next Specifies that when a run-time error occurs, control goes to the statement immediately following the statement where the error occurred, and execution continues from that point. Use this form rather than On Error GoTo when accessing objects.

We recommend that you use structured exception handling in your code whenever possible, rather than using unstructured exception handling and the On Error statement. For more information, see Try. Catch. Finally Statement.

An «enabled» error handler is one that is turned on by an On Error statement. An «active» error handler is an enabled handler that is in the process of handling an error.

If an error occurs while an error handler is active (between the occurrence of the error and a Resume , Exit Sub , Exit Function , or Exit Property statement), the current procedure’s error handler cannot handle the error. Control returns to the calling procedure.

If the calling procedure has an enabled error handler, it is activated to handle the error. If the calling procedure’s error handler is also active, control passes back through previous calling procedures until an enabled, but inactive, error handler is found. If no such error handler is found, the error is fatal at the point at which it actually occurred.

Each time the error handler passes control back to a calling procedure, that procedure becomes the current procedure. Once an error is handled by an error handler in any procedure, execution resumes in the current procedure at the point designated by the Resume statement.

An error-handling routine is not a Sub procedure or a Function procedure. It is a section of code marked by a line label or a line number.

Number Property

Error-handling routines rely on the value in the Number property of the Err object to determine the cause of the error. The routine should test or save relevant property values in the Err object before any other error can occur or before a procedure that might cause an error is called. The property values in the Err object reflect only the most recent error. The error message associated with Err.Number is contained in Err.Description .

Throw Statement

An error that is raised with the Err.Raise method sets the Exception property to a newly created instance of the Exception class. In order to support the raising of exceptions of derived exception types, a Throw statement is supported in the language. This takes a single parameter that is the exception instance to be thrown. The following example shows how these features can be used with the existing exception handling support:

Notice that the On Error GoTo statement traps all errors, regardless of the exception class.

On Error Resume Next

On Error Resume Next causes execution to continue with the statement immediately following the statement that caused the run-time error, or with the statement immediately following the most recent call out of the procedure containing the On Error Resume Next statement. This statement allows execution to continue despite a run-time error. You can place the error-handling routine where the error would occur rather than transferring control to another location within the procedure. An On Error Resume Next statement becomes inactive when another procedure is called, so you should execute an On Error Resume Next statement in each called routine if you want inline error handling within that routine.

The On Error Resume Next construct may be preferable to On Error GoTo when handling errors generated during access to other objects. Checking Err after each interaction with an object removes ambiguity about which object was accessed by the code. You can be sure which object placed the error code in Err.Number , as well as which object originally generated the error (the object specified in Err.Source ).

On Error GoTo 0

On Error GoTo 0 disables error handling in the current procedure. It doesn’t specify line 0 as the start of the error-handling code, even if the procedure contains a line numbered 0. Without an On Error GoTo 0 statement, an error handler is automatically disabled when a procedure is exited.

On Error GoTo -1

On Error GoTo -1 disables the exception in the current procedure. It does not specify line -1 as the start of the error-handling code, even if the procedure contains a line numbered -1. Without an On Error GoTo -1 statement, an exception is automatically disabled when a procedure is exited.

To prevent error-handling code from running when no error has occurred, place an Exit Sub , Exit Function , or Exit Property statement immediately before the error-handling routine, as in the following fragment:

Here, the error-handling code follows the Exit Sub statement and precedes the End Sub statement to separate it from the procedure flow. You can place error-handling code anywhere in a procedure.

Untrapped Errors

Untrapped errors in objects are returned to the controlling application when the object is running as an executable file. Within the development environment, untrapped errors are returned to the controlling application only if the proper options are set. See your host application’s documentation for a description of which options should be set during debugging, how to set them, and whether the host can create classes.

If you create an object that accesses other objects, you should try to handle any unhandled errors they pass back. If you cannot, map the error codes in Err.Number to one of your own errors and then pass them back to the caller of your object. You should specify your error by adding your error code to the VbObjectError constant. For example, if your error code is 1052, assign it as follows:

System errors during calls to Windows dynamic-link libraries (DLLs) do not raise exceptions and cannot be trapped with Visual Basic error trapping. When calling DLL functions, you should check each return value for success or failure (according to the API specifications), and in the event of a failure, check the value in the Err object’s LastDLLError property.

Источник

Оператор On Error (Visual Basic)

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

Без обработки ошибок или обработки исключений любая возникающая ошибка во время выполнения неустранима: отображается сообщение об ошибке и выполнение останавливается.

Ключевое Error слово также используется в инструкции error, которая поддерживается для обеспечения обратной совместимости.

Синтаксис

Компоненты

Термин Определение
GoTo Линии Включает подпрограмму обработки ошибок, которая начинается со строки, указанной в требуемом аргументе строки . Аргумент строки — это любая метка строки или номер строки. При возникновении ошибки во время выполнения управление ветвляется в указанную строку, делая обработчик ошибок активным. Указанная строка должна находиться в той же процедуре, что и On Error инструкция , иначе возникнет ошибка во время компиляции.
GoTo 0 Отключает включенный обработчик ошибок в текущей процедуре и сбрасывает его до Nothing .
GoTo -1 Отключает включенного исключения в текущей процедуре и сбрасывает его до Nothing .
Resume Next Указывает, что при возникновении ошибки во время выполнения управление переходит к инструкции сразу после инструкции, в которой произошла ошибка, и выполнение продолжается с этой точки. Используйте эту форму, а не On Error GoTo при доступе к объектам.

Комментарии

Мы рекомендуем по возможности использовать структурированную обработку исключений в коде, а не не неструктурированную обработку исключений и инструкцию On Error . Дополнительные сведения см. в разделе Оператор Try. Catch. Finally.

Обработчик ошибок «включен» — это обработчик, который включается оператором On Error . «Активный» обработчик ошибок — это включенный обработчик, который находится в процессе обработки ошибки.

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

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

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

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

Свойство Number

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

Оператор Throw

Ошибка, возникающая при Err.Raise использовании метода , задает для Exception свойства только что созданный экземпляр Exception класса . Для поддержки создания исключений производных типов исключений Throw в языке поддерживается оператор . Для этого требуется один параметр, который является экземпляром исключения, который должен быть создан. В следующем примере показано, как эти функции можно использовать с существующей поддержкой обработки исключений:

Обратите внимание, что On Error GoTo оператор перехватывает все ошибки, независимо от класса исключения.

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

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 ).

При ошибке GoTo 0

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

При ошибке goTo -1

On Error GoTo -1 отключает исключение в текущей процедуре. Строка -1 не указывается в качестве начала кода обработки ошибок, даже если процедура содержит строку с нумеровкой -1. On Error GoTo -1 Без оператора исключение автоматически отключается при завершении процедуры.

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

Здесь код обработки ошибок следует за оператором Exit Sub и предшествует оператору End Sub , чтобы отделить его от потока процедуры. Код обработки ошибок можно разместить в любом месте процедуры.

Неисправляемые ошибки

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

При создании объекта, который обращается к другим объектам, следует попытаться обработать все необработанные ошибки, которые они передают обратно. Если вы не можете, сопоставьте коды ошибок в Err.Number с одной из собственных ошибок, а затем передайте их обратно вызывающему объекту. Необходимо указать ошибку, добавив код ошибки в константу VbObjectError . Например, если код ошибки равен 1052, назначьте его следующим образом:

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

Источник

Excel VBA при ошибке Возобновить Далее

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

Те, кто регулярно пишет код в Excel VBA, знают, что они могут получать ошибки даже после написания профессионального кода, но они хотят игнорировать эту ошибку и продолжать работать со следующими строками кода. Типичным примером получения сообщения об ошибке является Функция рабочего листа ВПРФункция Excel ВПР ищет определенное значение и возвращает соответствующее совпадение на основе уникального идентификатора. Уникальный идентификатор однозначно связан со всеми записями базы данных. Например, идентификатор сотрудника, номер списка учащихся, контактный номер клиента, адрес электронной почты продавца и т. д. являются уникальными идентификаторами.
читать далее
не находит искомое значение в массиве таблиц. Он не вернет ошибку #N/A; скорее, он выдаст ошибку. Как «Невозможно получить свойство VLOOKUP класса функций рабочего листа».

VBA при ошибке Возобновление следующего примера 2.4

Если вы не знаете, почему мы получаем эту ошибку, то исправить ошибку очень сложно. В VBA у нас есть функция под названием «При ошибке Возобновить Далее».

Что делает при ошибке возобновление в VBA?

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

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

Вы можете скачать этот шаблон VBA On Error Resume Next Excel здесь – VBA при ошибке Возобновить следующий шаблон Excel

Пример №1

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

VBA при ошибке Возобновить следующий пример 1

Я написал коды, чтобы скрыть листы «Продажи и прибыль», и ниже приведен код.

Код:

Sub On_Error()

    Worksheets("Sales").Visible = xlVeryHidden
    Worksheets("Profit 2019").Visible = xlVeryHidden
    Worksheets("Profit").Visible = xlVeryHidden

End Sub

Пример 1.1

Теперь я начну выполнять код построчно, используя F8 ключ.

VBA при ошибке Возобновление следующего примера 1.2

Если я нажму на F8 ключ еще раз, он скроет лист с именем «Продажи».

Пример 1.3
VBA при ошибке Возобновление следующего примера 1.4

Теперь нажмите клавишу F8 еще раз и посмотрите, что произойдет.

VBA при ошибке Возобновление следующего примера 1.5

У нас есть «Индекс вне диапазонаИндекс вне диапазона — это ошибка в VBA, которая возникает, когда мы пытаемся сослаться на что-то или на переменную, которых нет в коде. Например, если у нас нет переменной с именем x, но мы используем функцию msgbox для x, мы получим ошибку нижнего индекса вне диапазона.читать далее», потому что текущая строка кода говорит следующее.

Worksheets("Profit 2019").Visible = xlVeryHidden

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

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

Следующая строка в коде говорит

Worksheets("Profit").Visible = xlVeryHidden

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

Чтобы игнорировать эту ошибку, нам нужно добавить оператор «При ошибке возобновить дальше».

Код:

Sub On_Error()

    On Error Resume Next
    Worksheets("Sales").Visible = xlVeryHidden
    Worksheets("Profit 2019").Visible = xlVeryHidden
    Worksheets("Profit").Visible = xlVeryHidden

End Sub

  Пример 1.6

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

VBA при ошибке Возобновление следующего примера 1.7

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

Пример 1.8

Я перешел к следующей строке кода, не показав никакой ошибки из-за оператора, который мы добавили вверху, который является оператором VBA «При ошибке возобновить следующий».

Пример #2

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

VBA при ошибке Возобновить следующий пример 2.0.1

У нас есть две таблицы над первой таблицей, в которых есть Emp Name и данные о зарплате во второй таблице, и у нас есть только Emp Name, поэтому с помощью VLOOKUP нам нужно получить данные о зарплате из левой таблицы.

Ниже приведен код, который я написал для получения деталей.

Код:

Sub On_Error1()

  Dim k As Long

  For k = 2 To 8
   Cells(k, 6).Value = WorksheetFunction.VLookup(Cells(k, 5), Range("A:B"), 2, 0)
  Next k

End Sub

Пример 2.1

Теперь запустите код построчно и посмотрите, что произойдет.

VBA при ошибке Возобновление следующего примера 2.2
Пример 2.3

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

VBA при ошибке Возобновление следующего примера 2.4

На этот раз мы получили сообщение об ошибке. Давайте посмотрим на имя второго сотрудника в таблице.

  Пример 2.5

Имя второго сотрудника — «Гаятри», но его нет в первой таблице, поэтому Функция ВПР VBAФункция ВПР в VBA аналогична функции ВПР на листе, а метод использования ВПР в VBA — через приложение. Рабочий лист методаФункциячитать далее не возвращает ошибку «#Н/Д», когда функция ВПР не находит искомое значение в таблице; скорее, это дает вышеуказанное сообщение об ошибке.

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

Нам нужно добавить оператор «При ошибке возобновить дальше» внутри цикла.

Код:

Sub On_Error1()

  Dim k As Long

  For k = 2 To 8
   On Error Resume Next
   Cells(k, 6).Value = WorksheetFunction.VLookup(Cells(k, 5), Range("A:B"), 2, 0)
  Next k

End Sub

VBA при ошибке Возобновление следующего примера 2.6

Теперь запустите код и посмотрите результат.

  Пример 2.7

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

Что нужно помнить здесь

  • «On Error Resume Next» — это оператор обработчика ошибок, когда нам нужно игнорировать известную ошибку.
  • Если вы хотите игнорировать сообщение об ошибке только для определенного набора кода, закройте следующий оператор при ошибке, добавив «При ошибке Перейти к 0» утверждение.

УЗНАТЬ БОЛЬШЕ >>

Post Views: 645

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Vba ошибка permission denied
  • Vba ошибка 91 object variable or with block variable not set