MyTetra Share
Делитесь знаниями!
Ошибки в макросе
12.10.2019
20:24
Раздел: !Закладки - VBA - Меню VB-справка

Основная реализация

Это простой обзор нашей стратегии

  1. Поместите строку On Error Goto Label  в начале нашего верхнего Sub.
  2. Поместите Label у обработки ошибок в конце нашего верхнего
    Sub.
  3. Если происходит ожидаемая ошибка, обработайте ее и продолжайте.
  4. Если приложение не может продолжить работу, используйте Err.Raise для перехода к метке обработки ошибок.
  5. В случае непредвиденной ошибки код автоматически перейдет к метке обработки ошибок.

На следующем рисунке показан обзор того, как это выглядит

Следующий код показывает простую реализацию этой стратегии


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

Public Const ERROR_NO_ACCOUNTS As Long = vbObjectError + 514

 

Sub BuildReport()

 

    On Error Goto eh

     

    ' Если ошибка в ReadAccounts, то перейти к ошибке

    ReadAccounts

     

    ' Сделай что-нибудь с кодом

     

Done:

    Exit Sub

eh:

    ' Все ошибки будут прыгать сюда

    MsgBox Err.Source & ": Произошла следующая ошибка  " & Err.Description

End Sub

 

Sub ReadAccounts()

     

    ' ОЖИДАЕМАЯ ОШИБКА - Может обрабатываться кодом

    ' Приложение может обрабатывать A1 равным нулю

    If Sheet1.Range("A1") = 0 Then

        Sheet1.Range("A1") = 1

    End If

     

    ' ОЖИДАЕМАЯ ОШИБКА - не может быть обработана кодом

    ' Приложение не может быть продолжено, если нет учетной записи

    If Dir("C:\Документы\Отчет.xlsx") = "" Then

        Err.Raise ERROR_NO_ACCOUNTS, "UsingErr" _

                , "There are no accounts present for this month."

    End If

 

    ' НЕОЖИДАННАЯ ОШИБКА - не может быть обработана кодом

    ' Если ячейка B3 содержит текст, мы получим ошибку несоответствия типов

    Dim total As Long

    total = Sheet1.Range("B3")

     

     

    ' продолжить и читать счета

     

End Sub

Это хороший способ реализации обработки ошибок, потому что

  • Нам не нужно добавлять код обработки ошибок в каждую подпрограмму.
  • Если возникает ошибка, то VBA корректно завершает работу приложения.

Полная стратегия обработки ошибок

Стратегия выше имеет один недостаток. Он не сообщает вам, где произошла ошибка. VBA не наполняет Err.Source чем-либо полезным, поэтому мы должны сделать это сами.

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

Целью этой стратегии является предоставление вам стека * и номера строки в случае возникновения ошибки.

* Стек — это список вспомогательных функций, которые использовались в данный момент при возникновении ошибки.

Это наша стратегия

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

Мы просто «всплываем» из-за ошибки. Следующая диаграмма показывает простое визуальное представление о том, что происходит, когда в Sub3 возникает ошибка

Единственная грязная часть этого — правильное форматирование строк. Я написал две подводные лодки, которые справляются с этим, поэтому он позаботится о вас.

Это две вспомогательные подводные лодки


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

Option Explicit

 

Public Const MARKER As String = "NOT_TOPMOST"

 

' Вызывает ошибку и добавляет номер строки и имя текущей процедуры

Sub RaiseError(ByVal errorno As Long, ByVal src As String _

                , ByVal proc As String, ByVal desc As String, ByVal lineno As Long)

     

    Dim sLineNo As Long, sSource As String

     

    ' Если маркера нет, тогда RaiseError вызывается впервые.

    If Left(src, Len(MARKER)) <> MARKER Then

 

        ' Добавить номер строки ошибки, если она есть

        If lineno <> 0 Then

            sSource = vbCrLf &amp; "Line no: " &amp; lineno &amp; " "

        End If

    

        ' Добавить маркер и процедуру к источнику

        sSource = MARKER &amp; sSource &amp; vbCrLf &amp; proc

         

    Else

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

        sSource = src &amp; vbCrLf &amp; proc

    End If

     

    ' Если код останавливается здесь, убедитесь, что DisplayError находится в верхней части Sub

    Err.Raise errorno, sSource, desc

     

End Sub

 

' Отображает ошибку, когда она достигает самого верхнего sub

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

Sub DisplayError(ByVal src As String, ByVal desc As String _

                    , ByVal sProcname As String)

 

    ' Удалить маркер

    src = Replace(src, MARKER, "")

     

    Dim sMsg As String

    sMsg = " Произошла следующая ошибка: " &amp; vbCrLf &amp; Err.Description _

                    &amp; vbCrLf &amp; vbCrLf &amp; " Расположение ошибки: "

     

    sMsg = sMsg + src &amp; vbCrLf &amp; sProcname

     

    ' Показать сообщение

    MsgBox sMsg, Title:="Ошибка "

     

End Sub

Пример использования этой стратегии

Вот простое кодирование, которое использует эти Sub. В этой стратегии мы не размещаем какой-либо код в верхнем подпрограмме. Мы только вызываем подводные лодки.


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

Sub Topmost()

 

    On Error Goto EH

     

    Level1

 

Done:

    Exit Sub

EH:

    DisplayError Err.source, Err.Description, "Module1.Topmost"

End Sub

 

Sub Level1()

 

    On Error Goto EH

     

    Level2

 

Done:

    Exit Sub

EH:

   RaiseError Err.Number, Err.source, "Module1.Level1", Err.Description, Erl

End Sub

 

Sub Level2()

 

    On Error Goto EH

     

    ' Ошибка здесь

    Dim a As Long

    a = "7 / 0"

 

Done:

    Exit Sub

EH:

    RaiseError Err.Number, Err.source, "Module1.Level2", Err.Description, Erl

End Sub

Результат выглядит так

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

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

“Programmatic Access to Visual Basic Project is not trusted”

Чтобы решить эту проблему, выполните следующие действия.

  1. Перейдите в раздел «Разработчик» на ленте и нажмите «Macro Security», которая находится под кодом.
  2. Нажмите «Настройка макроса» в левом списке.
  3. Поставьте флажок в поле «Доверительный доступ к объектной модели проекта VBA».
  4. Нажмите Ok.

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

  • Обработка ошибок используется для обработки ошибок, возникающих во время работы приложения.
  • Вы пишете определенный код для обработки ожидаемых ошибок. Вы используете оператор обработки ошибок VBA
    On Error Goto [label] для отправки VBA на метку при возникновении непредвиденной ошибки.
  • Вы можете получить подробную информацию об ошибке из Err.Description.
  • Вы можете создать свою собственную ошибку, используя Err.Raise.
  • Использование одного оператора On Error в самой верхней подпрограмме перехватит все ошибки в подпрограммах, которые вызываются отсюда.
  • Если вы хотите записать имя Sub с ошибкой, вы можете обновить ошибку и сбросить ее.
  • Вы можете использовать журнал для записи информации о приложении, когда оно запущено.

Источник

Так же в этом разделе:
 
MyTetra Share v.0.52
Яндекс индекс цитирования