Access функции обработки ошибок

converted to PDF by HupBaH9I

отработал

Resume Next Продолжает выполнение со строки, следующей за строкой, которая вызвала ошибку, после того как

обработчик ошибок отработал

Resume Строка Продолжает выполнение с указанной

строки и метки после обработки ошибки

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

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

Оформление обработчика ошибок. Обработчик ошибок обычно состоит из выражения Select Case (или похожего выражения для принятия решений), которое различает разные значения свойства Err и способ их обработки.

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

Для отключения обработчика ошибок вставьте следующее выражение в код вашей процедуры:

On Error Goto 0

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

1.Текущая процедура.

2.Процедуры, перечисленные в списке Вызовы (начиная с самой последней вызываемой процедуры).

3.Обработчик ошибок внутри Access, который останавливает выполнение программы и выводит диалоговое окно ошибки времени выполнения.

Ошибки, связанные с работой процессора баз данных, вызывают событие Error. Это относится к ошибкам процессора баз данных Microsoft Jet, но не к ошибкам времени выполнения Access. Выполняя процедуру события или макроса при возникновения события Error, вы можете предотвратить вывод сообщения об ошибке Microsoft Access и вывести пользовательское сообщение об ошибке, которое может оказаться более подходящим по контексту для вашего приложения.

Свойство OnError используется для того, чтобы указать макрос или процедуру Access, которая будет выполняться при возникновении события Error. Устанавливайте это свойство тем же путем, которым вы устанавливаете остальные свойства.

Например, синтаксис для процедуры события Error формы должен иметь следующую конструкцию:

Sub Form_Error(DataErr As Integer, Response As Integer)

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

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

converted to PDF by HupBaH9I

DATA_ERRDISPLAY — это значение по умолчанию. Будет выведено стандартное сообщение об ошибке Microsoft Access.

Отладка программы в Visual Basic

Основным визуальным средством отладки в Visual Basic является окно Debug. Это окно позволяет выполнять достаточно много функций, и его основные элементы представлены на рис. 12.7.

Рис. 12.7. Окно отладки Debug в Visual Basic

Это окно имеет две панели. В верхней части расположена панель Watch, которая позволяет выводить значения интересующих нас переменных, значений свойств или выражений во время выполнения программы. Переменная или выражение могут быть занесены на эту панель с помощью команды Add Watch меню Tools. После выполнения этой команды на экране появляется одноименное диалоговое окно, представленное на рис. 12.8.

converted to PDF by HupBaH9I

Рис. 12.8.

Заранее выделенное выражение автоматически помещается в поле Expression этого окна. В блоке Context определяется дипазон, в котором будет отслеживаться изменение наблюдаемой величины. Не увлекайтесь, попытка отследить значения во всем диапазоне работы программы (пункты All Procedures и All Modules) может резко замедлить выполнение программы. В блоке Watch Type вы можете задать способ реакции Visual Basic на изменение значения наблюдаемого выражения.

В нижней части окна отладки расположена панель Immediate, которая позволяет отображать информацию, связанную с отлаживаемыми операторами, а также непосредственно вводить необходимые команды, как это можно делать в окне Command Visual FoxPro.

Сама процедура выполнения отладки программы Visual Basic аналогична описанной ранее для программы Access.

12.3. Подготовка приложения для распространения

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

В этом параграфе мы рассмотрим средства подготовки пользовательского приложения для распространения.

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

В процессе создания пользовательского приложения по мере насыщения Project Manager различными модулями, Visual FoxPro автоматически создавал таблицу с расширением PJX, куда помещал необходимую информацию о составных элементах будущей прикладной программы. Используя эту таблицу, Project Manager может создать пользовательскую программу Visual FoxPro, которая будет включать в себя все элементы вашего проекта двух типов: в виде файла с расширением APP и в виде файла с расширением EXE (рис. 12.9). Для этого в Project Manager вам

converted to PDF by HupBaH9I

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

Рис. 12.9.

В Project Manager все внесенные в него файлы делятся на две группы: включенные в пользовательскую программу или не включаемые в нее. Например, по умолчанию не включаются в программу файлы БД и все связанные с ней файлы. Посмотрите на список файлов в Project Manager. Перед именем таких файлов вы обнаружите перечеркнутый кружок. Включаемый в пользовательскую программу файл компилируется в объектный код и недоступен для изменения. Файлы, не включаемые в пользовательскую программу, должны распространяться отдельно. Для того чтобы включить или исключить какойто файл из пользовательской программы, в меню Project выберите команду Project Info. Появляющееся после этого диалоговое окно Project Information приведено на рис. 12.10. Для изменения статуса файла откройте вкладку Files. Таким образом, перед построением пользовательской программы вы должны проверить наличие всех файлов, которые должны войти в файл приложения. Например, файлы изображений автоматически не включаются в проект, и вы должны вручную добавить их, так как распространение их в виде отдельных файлов запрещено лицензионным соглашением.

converted to PDF by HupBaH9I

Рис. 12.10.

На вкладке Project того же окна, которая показана на рис. 12.11, мы можем указать авторские реквизиты, задать параметры компиляции и выбрать значок, который будет включен в EXE-файл и может использоваться для создания ссылки при его запуске. Для подготовки пользовательской программы в параметрах компиляции следует отменить опцию Debug Info, так как при включенной опции в объектный код помещается специальный отладочный модуль, позволяющий при ошибке с помощью окна Trace указать место ее возникновения при наличии исходного файла и самой СУБД. Так как в пользовательской программе исходных текстов программ нет, то этот модуль бесполезен и только занимает лишнее место.

Рис. 12.11.

converted to PDF by HupBaH9I

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

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

Для того чтобы при компиляции установить точку запуска приложения, в Project Manager необходимо указать главную программу, как это видно на рис. 12.9. Для этого достаточно поставить курсор на этот файл и вызвать команду Set Main в меню Project. Как правило, в качестве главной программы используется или специальная программа, или файл главного меню приложения.

Для построения приложения в Visual FoxPro можно использовать и специальную программу BUILDAPP.PRG, которая при установке профессиональной версии Visual FoxPro записывается в папку TOOLS\BUILDAPP папки Visual FoxPro. Эта программа создает файл пользовательского приложения и удаляет из него исходный код событий и методов, который хранится в файлах форм SCX и визуальных библиотек VCX. Удаление исходного кода позволяет получить файл пользовательского приложения меньших размеров и более защищенный от вскрытия.

Для запуска программы используйте следующий синтаксис:

DO BUILDAPP [WITH ProjectName [, AppFileName [, DebugMode [, BuildEXE]]]]

Здесь параметр ProjectName задает имя проекта. Параметр AppFileName имя файла пользовательского приложения, причем указываемое расширение (APP или EXE) будет устанавливать тип создаваемого файла. Параметр DebugMode имеет логический тип и позволяет включить или отключить отладочный режим (для SET DEBUG ON параметр DebugMode должен быть равен .T., а для SET DEBUG OFF — .F.). Если параметр BuildEXE равен .T., то будет создаваться выполняемый EXE-файл.

Программа BUILDAPP выполняет следующие действия:

1.Определяет местоположение файлов.

2.Открывает проект.

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

4.Физически удаляет помеченные для удаления записи в файлах VCX.

5.Переносит исходный код из файлов SCX и VCX в массив.

6.Перестраивает файл пользовательского приложения.

7.Восстанавливает исходный код в файлах SCX и VCX, возвращая тем самым проект в первоначальное состояние.

Теперь скажем несколько слов о двух типах пользовательской программы, которые можно создать в Visual FoxPro.

APP-файл предназначен для работы в среде СУБД. Таким образом, компьютер, на котором будет работать ваша программа, должен быть оснащен копией Visual FoxPro.

EXE-файл на несколько десятков килобайт больше APP-файла, но для своей работы не требует наличия на компьютере Visual FoxPro. Этот файл работает совместно с библиотекой поддержки VFP300.ESL. EXE-файл работает несколько быстрее, чем APP, вероятно, за счет того, что требует меньшего количества ресурсов.

При выборе типа файла для пользовательского приложения необходимо иметь в виду, что библиотека поддержки не включает некоторые функции СУБД. Следовательно, в приложении, распространяемом в виде EXE-файла, не должны присутствовать эти исключенные функции.

Из меню Visual FoxPro не доступны следующие возможности:

Database

Form

Menu

Program

Project

Query

Table

converted to PDF by HupBaH9I

Ниже приведен список команд, при выполнении которых в пользовательском приложении произойдет ошибка «Feature not available» (функция не доступна).

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

BUILD APP MODIFY FORM

BUILD EXE MOFIFY MENU

BUILD PROJECT MODIFY PROJECT

COMPILE MODIFY QUERY

CREATE FORM MODIFY STORED PROCEDURE

CREATE MENU MODIFY STRUCTURE

CREATE QUERY MODIFY VIEW

CREATE VIEW SUSPEND

FILER SET

MODIFY CONNECTION SET STEP

MODIFY DATABASE

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

ADDLABEL.APP

AUTONAME.PRG

BROWSER.APP

BUILDAPP.PRG

BUILDAPP.SCT

BUILDAPP.SCX

BUILDER.APP

CONPROCS.PRG

CONVERT.APP

CONVERT.H

CONVERT.PJT

CONVERT.PJX

CONVERT.PRG

CVTALERT.H

CVTSCX.H

FD3.FLL

FDKEYWRD.CDX

FOREIGN.H

FOREIGN.PRG

FORMPARM.PRG

FOXHELP.DBF

FOXHELP.FPT

FOXHELP.HLP

FPCNEW.PRG

GENDBC.PRG

GENERIC.PRG

GENMENU.PRG

HC35.ERR

HC35.EXE

IMAGEDIT.EXE

IMAGEDIT.HLP

JD.FKY

JD.PRG.

LOCWORD.H

LOCWORD.PRG

MIGDB4.H

MIGDB4.PRG

MIGNAVPR.TXT

MMSETUP.PRG

MRBC.EXE

MSGRAPH.HLP

MSINFO.EXE

PRO_EXT.H

PUTNAME.PRG

RESERVED.FLL

SHED.EXE

converted to PDF by HupBaH9I

SHED.HLP

SPELLCHK.APP

TRANSPRT.PRG

VFP.EXE

WINAPIMS.LIB

WIZARD.APP

WIZARD.FLL

WZFORM.APP

WZFOXDOC.APP

WZGRAPH.APP

WZIMPORT.APP

WZMAIL.APP

WZPIVOT.APP

WZQUERY.APP

WZREPORT.APP

WZSETUP.APP

WZTABLE.APP

WZUPSIZE.APP

В Visual Basic процедура подготовки пользовательского приложения очень похожа на только что описанную для Visual FoxPro. В Visual Basic мы можем получить только EXE-файл. Для этого достаточно выбрать команду Make EXE File в меню File. Подготовка дистрибутивного комплекта дискет в Visual Basic выполняется с помощью отдельного приложения — Application Setup Wizard, представленного на рис. 12.12. Это приложение работает аналогично Setup Wizard в Visual FoxPro и путем выполнения семи шагов позволяет программисту быстро определить набор файлов, необходимый для работы приложения на компьютере пользователя.

Рис. 12.12.

Приложение 1

Дополнительные возможности новой версии Visual FoxPro 5.0

Визуальные средства проектирования Поставка программного пакета Требования к установке

Project Manager

Соседние файлы в предмете Программирование на Delphi

  • #
  • #
  • #
  • #

    28.06.201440.36 Mб95Джулипн Б. “Фундаментальные алгоритмы и структуры данных.pdf

  • #
  • #
  • #

    28.06.20145.41 Mб146Тексейра С. “Delphi 5. Руководство разработчика” (1 том).pdf

The Basics

Before delving into actual programming functions and sub-routine, we must first establish what is an error handler.

An error handler is a bit of code which will do pre-defined actions whenever an error occurs. For instance, generate a message to the user or developer describing the nature of the error. For an error handler to be useful, it must provide a minimum of information in its message to the user.

Microsoft’s Error Handler

If ever you allow Microsoft to generate code block, say by converting a macro to VBA, and include their ‘error handler’ you will get something like:

Private Sub Command3_Click()
On Error GoTo Command3_Click_Err

    'The code will be here

Command3_Click_Exit:
    Exit Sub

Command3_Click_Err:
    MsgBox Error$
    Resume Command3_Click_Exit
End Sub

Sadly, this error handler is dismal! It will result in a message box displaying a description of the error, but nothing more. Below is an example of what you can expect from Microsoft’s error handler.

Microsoft Default Error Handler

In most cases, this simply isn’t enough information, certainly not for a developer, to properly isolate an issue to remedy it.

Proper Error Handler

So what would be the minimum data to provide in an error handler? Well, that’s a very good question and the answer can vary depending on the environment you are deploying your solution, but, for me, a bare minimum would include things like:

  • Error Number
  • Error Description
  • Error Source

With this in mind, below is an example of a typical error handler I use for code I post on my website. It is a great starting point if you are new to VBA coding/error handling.

On Error GoTo Error_Handler

    'Your code will go here
    
Error_Handler_Exit:
    On Error Resume Next
    Exit {PROCEDURE_TYPE}
    
Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: {PROCEDURE_NAME}/{MODULE_NAME}" & vbCrLf & _
           "Error Description: " & Err.Description, vbCritical, _
           "An Error has Occurred!"
    Resume Error_Handler_Exit

A Concrete Example

Sub HelloWorld()
On Error GoTo Error_Handler

    MsgBox "Hello Word!"

Error_Handler_Exit:
    On Error Resume Next
    Exit Sub
    
Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: YourModuleName/HelloWorld" & vbCrLf & _
           "Error Description: " & Err.Description, vbCritical, _
           "An Error has Occurred!"
    Resume Error_Handler_Exit
End Sub

Note

Although VBA provides programmers with the possibility of using the err.source statement, it sadly does not help truly identify the culprit of the current error. This is why you must manually enter in the {MODULE_NAME} / {PROCEDURE_NAME} for each error handler. Trust me, although it may take a few extra seconds to do, it will same you loads of troubleshooting time later on (I’m talking from experience)!!!

Taking Things Even Further

The basic error handler meets a basic need and is a step forward, but for more complex procedure it still can leave you deep in troubleshooting to determine exactly where in a procedure the error is occurring. This is where adding a Line Number in the Error Handler can greatly help!

Luckily, there is the little-known Erl gem! If we add Line Numbers to our procedures, Erl we in fact return the last executed line number (which should normally be the source of our error).

So with this in mind, we can update the Basic Error Handler to

On Error GoTo Error_Handler

    'Your code will go here
 
Error_Handler_Exit:
    On Error Resume Next
    Exit {PROCEDURE_TYPE}
 
Error_Handler:
    MsgBox "The following error has occured" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: {PROCEDURE_NAME}/{MODULE_NAME}" & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occured!"
    Resume Error_Handler_Exit

Notice I use a Switch function so the Error Handler will work with, or without, line numbers being present. The result being that now, when line numbers are added to your procedure you will get something like

VBA Basic Error Handler With Line Number

Now, we starting to get information that will enable us to quickly identify, isolate and remedy an error! We instantly know the exact source of the error, the error number and description, as well as the line number within the procedure that raised the error. Doesn’t get much better than that.

Centralized Error Function

As any developer knows, it takes time to perfect code. Your Error Handler is no different and will probably go through several iterations until you get it just the way you like it. Now, if you implement the code shown above, then any changes will require you editing each procedure, 1 by 1, to update any changes you wish to implement to your error handler. This, of course, could be very time consuming.

This is why, IMHO, it makes much more sense to create and implement an Error Handling function and using it within your procedure. The end result is simplified procedural code (so we reduce the amount of code in each procedure/module) and set things up so that you can change all error handling in one location with ease.

I first found out about this approach, no this wasn’t my idea by any means, from the great Allen Browne when I read his article: Microsoft Access tips: Error Handling in VBA. One extra advantage of Allen’s approach is he logs the errors to a table enabling you to review them when you wish to and not solely have to rely on a user’s recollection of a popup message.

Over the years, I have used and improved upon Allen’s code, but it is an excellent starting and can easily be used as is in production.

So I mentioned having ‘improved’ upon it and people always ask me how exactly? Everything depends on context, but normally I add to the logging function (not displayed to the user, no need) in things like:

  • the computer name
  • OS Information (version, build, bitness, …)
  • Office/Access Information (version, build, bitness, runtime or not, language, …)

and in certain cases I also add things like

  • user’s selected language (for my multi-lingual databases)
  • I switch the language of the error MsgBox displayed to the user

In such a function, you can (and I have) gotten into taking screenshots so you can see the form/report/… and see the exact data, and/or send the information by e-mail, change the message for certain specific error to make them more understandable!,…. The possibilities here are endless, add anything that may help you in your job of troubleshooting issue!

Automating Insertion of Your Error Handler

If you are going to be doing some serious vba (MS Access, Word, Excel, …) work and not just a little tinkering, you should most probably seriously consider looking into buying a copy of MZ-Tools as enables you to insert your error handler into any procedure at the click of a button. You can even manage multiple versions of your error handler. Another beautiful feature of using MZ-Tools is the fact that it can automatically include things like the function name, module name, … in your error handler at runtime, eliminating another manual task.

Testing Your Error Handler

Sometimes, it would be nice to be able to trigger an error, for instance, to test your error handler. Nothing could be easier in VBA, we can simply use the Raise method to do so. That’s actually how I produced the images for this article. Here’s a simple example:

Public Function ErrorDemo()
10    On Error GoTo Error_Handler

20        Debug.Print "Line 1"
30        Debug.Print "Line 2"
40        Debug.Print "Line 3"
50        Err.Raise 9
60        Debug.Print "Line 4"
70        Debug.Print "Line 5"
          
Error_Handler_Exit:
80        On Error Resume Next
90        Exit Function
       
Error_Handler:
100       MsgBox "The following error has occured" & vbCrLf & vbCrLf & _
                 "Error Number: " & Err.Number & vbCrLf & _
                 "Error Source: ErrorDemo/mod_Helpers_Errors" & vbCrLf & _
                 "Error Description: " & Err.Description & _
                 Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
                 , vbOKOnly + vbCritical, "An Error has Occured!"
110       Resume Error_Handler_Exit
End Function

which then generates
VBA Error Raise
So on Line 50 we Raise error number 9 and as shown in the image above our error handler properly reports that back to us (and much more!).

So with a single line of code, you can easily test your code at any time you would like.

Where & When To Use Error Handling?!

Now this is one point that various developers have different viewpoints on.

We have to ask ourselves, what is the purpose of error handling? And there are a couple answers here:

  • Avoid users being able to debug code when an error occurs so they can’t access the raw VBA code of our application
  • Present comprehensible messages to the user when an error occurs
  • Avoids Global Variables from being reset when an error occurs

I’ve always view it as you should have error handling in all your procedure (with very, very few exceptions). This makes your application bulletproof, even during development and ultimately there is no down side to implementing as such.

That said, as someone like Albert Kallal explains:

Well, the mde is a “compiled” version with all of the VB source code striped
out. The ide can’t jump to the bad line of code in question.

Further, what is VERY useful in this case is that a un-handled error in a
mde DOES NOT re-set all global vars.Albert Kallal

Thus, some argue that since we should be deploying database in a compiled state (mde, accde) that there is no need for error handling. (and no I’m not saying Albert is stating that, I’m not going to put words in his mouth, but his comments explain why some developer believe this)

As stated above, while true, it still doesn’t address these issues during development and testing and ultimately why I stand behind recommending implementing proper error handling throughout. I view it as there is no downside to adding error handling throughout. Furthermore, if you do implement some type of error logging system, you will even gain insight into the runnings of your solution making it even more valuable to add error handling throughout!

Alternative and Other Options

I thought I’d also mention a couple other tools well worth mentioning, mainly Great Access Tools – Access Crash Reporter.

I’ve also seen many people refer to UtterAccess’ Global Error Handler code which can be found at Global Error Handling, so that may also be worth your while to check out.

A Few Resources on the Subject

  • Microsoft Access tips: Error Handling in VBA
  • MZ-Tools – Productivity Tools for Visual Studio .NET (C#, VB.NET), Visual Basic and VBA
  • On Error statement (VBA) | Microsoft Docs
  • Error function (Visual Basic for Applications) | Microsoft Docs
  • Raise method (Visual Basic for Applications) | Microsoft Docs
  • Information.Erl Method (Microsoft.VisualBasic) | Microsoft Docs I couldn’t find any VBA documentation, only this .net that references VB Namespace?!

Автор Allen Browne, июнь 1997 г. Обновлено в сентябре 2009 г..

Оригинал http://allenbrowne.com/ser-23a.html

Перевел с английского Александр Артамонов, ноябрь 2011 г.


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

В каждую функция или процедуру следует включать обработку ошибок. Без нее пользователь может оказаться глядящим на дефектный код в открытом редактороме VBA в полной версии Аксесс, а в рантайм версии приложение просто падает.. Более подробно обработка ошибок изложена в статье FMS  Error Handling and Debugging.

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

1 Sub|Function SomeName()
2 On Error GoTo Err_SomeName ' Инициализировать обработку ошибок.
3 'здесь должен быть ваш код.
4 Exit_SomeName: ' Метка для возобновления после ошибки.
5 Exit Sub|Function ' Выход до обработки ошибок.
6 Err_SomeName: ' Метка для перехода при ошибке.
7 MsgBox Err.Number & Err.Description ' Место для обработчика ошибок.
8 Resume Exit_SomeName ' возобновить код и выйти.
9 End Sub|Function

Для задач, где есть возможность нескольких ошибок, строки 7-8 нужно заменить более подробным вариантом:

      Select Case Err.Number
Case 9999 ' Номер ожидаемой ошибки.
Resume Next ' Чтобы игнорировать вызвавшую ошибку строку
Case 999
Resume Exit_SomeName ' Это используется для выхода из процедуры.
Case Else ' Любая неожиданная ошибка.
Call LogError(Err.Number, Err.Description, "SomeName()")
Resume Exit_SomeName
End Select

Ветка Case Else в этом примере вызывает пользовательскую функцию записи деталей ошибки в таблицу. Это позволит подробнее разобраться уже после того, как ошибка будет очищена. Таблицу можно назвать «tLogError» и состоять она будет из следующих полей:

Имя поля

Тип данных

Описание

ErrorLogID

Счетчик

Первичный ключ.

ErrNumber

Число

Длинное целое. Номер ошибки, сгенерированный Аксессом.

ErrDescription

Текст

Размер=255. Сообщение об ошибке, сгенерированное Аксессом.

ErrDate

Дата/время

Системная дата и время ошибки. По умолчанию: =Now()

CallingProc

Текст

Имя процедуры, вызвавшей LogError()

UserName

Текст

Имя пользователя.

ShowUser

Логический

Будет или нет показан диалоговое сообщение (MsgBox) c описанием ошибки

Parameters

Текст

255. Опционально. Любые параметры, которые сочтете нужным записать.

Below is a procedure for writing to this table. It optionally allows recording the value of any variables/parameters at the time the error occurred. You can also opt to suppress the display of information about the error.

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


Function LogError(ByVal lngErrNumber As Long, ByVal strErrDescription As String, _
strCallingProc As String, Optional vParameters, Optional bShowUser As Boolean = True) As Boolean
On Error GoTo Err_LogError
' Назначение: Обобщенный обработчик ошибок.
' Записывает ошибки в таблицу "tLogError".
' Аргументы: lngErrNumber - значение Err.Number
' strErrDescription - значение Err.Description
' strCallingProc - имя процедуры/функции, сгенерировавшей ошибку.
' vParameters - необязательный параметр-строка: список параметров для записи в таблицу.
' bShowUser - необязательный параметр boolean: если False, подавляет вывод сообщения на экран.
' Автор: Allen Browne, allen@allenbrowne.com Комментарии перевел Александр Артамонов

Dim strMsg As String ' Строковое значение для отображения в MsgBox
Dim rst As DAO.Recordset ' таблица tLogError

Select Case lngErrNumber
Case 0
Debug.Print strCallingProc & " called error 0."
Case 2501 ' Cancelled
'Do nothing.
Case 3314, 2101, 2115 ' Can't save.
If bShowUser Then
strMsg = "Record cannot be saved at this time." & vbCrLf & _
"Complete the entry, or press <Esc> to undo."
MsgBox strMsg, vbExclamation, strCallingProc
End If
Case Else
If bShowUser Then
strMsg = "Error " & lngErrNumber & ": " & strErrDescription
MsgBox strMsg, vbExclamation, strCallingProc
End If
Set rst = CurrentDb.OpenRecordset("tLogError", , dbAppendOnly)
rst.AddNew
rst![ErrNumber] = lngErrNumber
rst![ErrDescription] = Left$(strErrDescription, 255)
rst![ErrDate] = Now()
rst![CallingProc] = strCallingProc
rst![UserName] = CurrentUser()
rst![ShowUser] = bShowUser
If Not IsMissing(vParameters) Then
rst![Parameters] = Left(vParameters, 255)
End If
rst.Update
rst.Close
LogError = True
End Select

Exit_LogError:
Set rst = Nothing
Exit Function

Err_LogError:
strMsg = "В программе возникла непредвиденная ситуация." & vbCrLf & _
"Пожалуйста запишите следующую информацию:" & vbCrLf & vbCrLf & _
"Вызывающая процедура: " & strCallingProc & vbCrLf & _
"Номер ошибки " & lngErrNumber & vbCrLf & strErrDescription & vbCrLf & vbCrLf & _
"Запись в таблицу невозможна из-за Ошибки " & Err.Number & vbCrLf & Err.Description
MsgBox strMsg, vbCritical, "LogError()"
Resume Exit_LogError
End Function


Замечания по функции:

  1. Для Аксесса 1 или 2, используйте Access Basic error handler.
  2. Возвращаемое значение служит только с целью показать, успешно ли функция записала в лог ошибку.
  3. Возможные расширения: Поскольку таблица tErrorLog у вас уже открыта, вы могли бы посчитать последние ошибки и подавить вывод на экран одного и того же сообщения несколько раз, или отменить повторные ошибки блокировки.

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

Option Compare Database
Option Explicit
'***************************************************************
' 03. Обработка ошибок разными методами
'***************************************************************

'==============================================================
' ADO. Обработка ошибок
Private Sub butADO_Click()
Dim cnn As New ADODB.Connection
Dim oneErr As ADODB.Error, s As String
    On Error Resume Next
    cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=?"
    ' Информация о всех ошибках
    s = "Список ошибок;------ ADO -------;"
    For Each oneErr In cnn.Errors
        s = s  "Описание;"  oneErr.Description  ";"
        s = s  "Номер;"  oneErr.Number  ";"
        s = s  "Имя приложения;"  oneErr.Source  ";"
        s = s  "SQLState;"  oneErr.SQLState  ";"
        s = s  "NativeError;"  oneErr.NativeError  ";"
        s = s  "Код справки;"  oneErr.HelpContext  ";"
        s = s  "Файл справки;"  oneErr.HelpFile  ";"
    Next
    ' Полная информация о последней ошибке
    s = s  "Последняя ошибка;------ ADO -------;"
    Me.listErrors.RowSource = s  funLastError 'Отображаем ошибку
    Resume Next
End Sub

'==============================================================
' DAO. Обработка ошибок
Private Sub butDAO_Click()
Dim dbs As DAO.Database
Dim oneErr As DAO.Error
Dim strmdb As String, s As String
    
    On Error Resume Next
    Set dbs = DBEngine.OpenDatabase("?", , 2 / 0) ' Генерируем ошибку
    'Err.Raise 11 ' Самостоятельный генератор ошибок
    
    ' Информация о всех ошибках
    s = "Список ошибок;------ DAO "  DAO.Version  " -------;"
    For Each oneErr In DBEngine.Errors
        s = s  "Описание;"  oneErr.Description  ";"
        s = s  "Номер;"  oneErr.Number  ";"
        s = s  "Имя приложения;"  oneErr.Source  ";"
    Next
    ' Полная информация о последней ошибке
    s = s  "Последняя ошибка;------ DAO -------;"
    Me.listErrors.RowSource = s  funLastError 'Отображаем ошибку
    Err.Clear
End Sub

'==============================================================
'  Возвращает информацию о последней ошибке
'  ADO и DAO
Private Function funLastError() As String
Dim s As String
    s = "Описание;"  Err.Description  ";"
    s = s  "Номер;"  Err.Number  ";"
    s = s  "Код справки;"  Err.HelpContext  ";"
    s = s  "Файл справки;"  Err.HelpFile  ";"
    s = s  "Имя приложения;"  Err.Source  ";"
    s = s  "DLL код;"  Err.LastDllError  ";"
    funLastError = s
End Function

I’m generating a query and report through VBA. I have an option of asking the user if they want to output the report as a snapshot. I first ask them if they want to make a snap shot. If they say no, nothing happens. If they say yes, they get a prompt asking where they want to save it.

Everything works great except if they say yes and then click Cancel on the prompt, it raises a runtime error 2501 saying the report action was cancelled. Here is the code.

DoCmd.OpenReport "CONCERNS", acViewPreview, lstFee.Value & " DETAILS"
If MsgBox("Do you wish to create a snapshot of this report?", vbQuestion + vbYesNo) = vbYes Then
    DoCmd.OutputTo acReport, "CONCERNS", "SnapshotFormat(*.snp)", ""
End If

This is also the end of my procedure so I don’t really care if an error happens here since all the important stuff happened already. I just know some monkey somewhere will flip if they ever see it. Is there a way to handle this error? On Error Resume Next is not an option because that would make debugging a nightmare in the future. It sounds like I’m looking for something like a Try/Catch but I don’t think VBA supports that.

asked Jul 10, 2009 at 20:31

mandroid's user avatar

mandroidmandroid

2,3085 gold badges24 silver badges37 bronze badges

On Error GoTo errHandler
  ....
  Exit Sub

errHandler:
  If (Err.Number = 2501) Then
    Resume Next
  End If

End Sub

JohnFx's user avatar

JohnFx

34.5k18 gold badges104 silver badges162 bronze badges

answered Jul 10, 2009 at 21:47

Smandoli's user avatar

SmandoliSmandoli

6,9293 gold badges49 silver badges83 bronze badges

4

All you need is to handle the error ie:

On Error Goto HandleErr
DoCmd.OpenReport "CONCERNS", acViewPreview, lstFee.Value & " DETAILS"
If MsgBox("Do you    wish to create a snapshot of this report?" _
    , vbQuestion + vbYesNo) = vbYes Then    
    DoCmd.OutputTo acReport, "CONCERNS", "SnapshotFormat(*.snp)", ""
End If

ExitHere:
Exit Sub 'or Function

HandleError:
Select Case Err.Number
Case 2501 'Report Was Cancelled
   If MsgBox ("Did you really want to cancel saving the report?", _
       vbYesNo + vbDefaultButton2 ,"Please Confirm") = vbNo then
       Resume
    Else
       Resume ExitHere
    End if
Case Else
    Msgbox "An Unexpected error Occurred " & Err.Description, _
        vbExclamation,"Error"
    Resume ExitHere
End Select

This will give the user the option to undo the cancel and let them know what they did.

answered Jul 10, 2009 at 22:03

Mark3308's user avatar

Mark3308Mark3308

1,29811 silver badges22 bronze badges

There are (at least) two ways to handle this.

1> get the filename and handle possible cancellation in a step before sending the report snapshot. I haven’t done this recently but there’s another way to generate the snapshot report than the DoCmd.OutputTo command, or some variation that doesn’t require the command itself to use a file dialog. I generated report snapshots in an old application and didn’t have to ask the user for a filename. I’ll try to find the code and show an example.

2> use On Error Resume Next, but only right before the DoCmd.OutputTo routine, then see if there’s an error, then turn it back off:

If MsgBox("Do you wish to create a snapshot of this report?", _
    vbQuestion + vbYesNo) = vbYes Then

    On Error Resume Next
    DoCmd.OutputTo acReport, "CONCERNS", "SnapshotFormat(*.snp)", ""
    if Err.Number = 2501 Then
        '' log or ignore error
    Else
        '' log or warn other unexpected errors
    End If
    On Error Goto 0

End If

answered Jul 10, 2009 at 21:45

Todd's user avatar

ToddTodd

5,9992 gold badges21 silver badges21 bronze badges

4

Понравилась статья? Поделить с друзьями:
  • Access ошибка формата
  • A8bb ошибка bmw
  • Access ошибка permission denied
  • Access ошибка при попытке импорта файла
  • A8b7 ошибка bmw