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.
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
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
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 или 2, используйте Access Basic error handler.
- Возвращаемое значение служит только с целью показать, успешно ли функция записала в лог ошибку.
- Возможные расширения: Поскольку таблица 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
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
34.5k18 gold badges104 silver badges162 bronze badges
answered Jul 10, 2009 at 21:47
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
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
ToddTodd
5,9992 gold badges21 silver badges21 bronze badges
4