При запуске excel ошибка vba

Не так давно очередной раз столкнулся с ошибками приложения Excel при попытке включения макросов после открытия файлов .xlsm. Вспомнил, что подобные проблемы преследуют пользователей довольно давно, но чаще всего они наблюдались с Excel 2013 и Excel 2016. Характерные особенности этой группы ошибок следующие:

  • Приложение Excel закрывается при открытии файла с макросами (при включенном режиме безопасности Включить все макросы);
  • Ошибка приложения Excel возникает при попытке включить содержимое (нажатии соответствующей кнопки);
  • Ошибка приложения Excel возникает при сохранении файла с макросами;

Ну и по горячим следам очередного инцидента, дабы не откладывать на потом, решил для себя собрать небольшой хаб по ошибкам приложения Excel с последующей модификацией, дабы опять не терять время на поиск информации в Сети и на составление облака причин.
Суть в том, что в процессе открытия файла xlsm, и при отключенных макросах, в верхней части основного окна (над таблицей), высвечивается строка уведомления: ПРЕДУПРЕЖДЕНИЕ СИСТЕМЫ БЕЗОПАСНОСТИ Запуск макросов отключен, с кнопкой включения содержимого (макросов). Как только пользователь её нажимает, Excel попросту аварийно завершается (падает) с ошибкой Программа Microsoft Excel не работает и характерным окном уведомления:

excel ошибка макроса

При этом было замечено, что непосредственно перед возникновением ошибки приложения Excel никаких системных обновлений и обновлений пакета Office не устанавливалось. Возможно, каким-то образом задействованы последние обновления на Office, но прямой связи я не заметил, а подробного исследования проблемы не проводил. При этом зависимости от версии операционной системы (мною лично сбои наблюдались на Windows 10 LTSC и Windows 7 Professional) так же выявлено не было. При анализе аварийного дампа приложения (*.hdmp) обычно можно увидеть подобную информацию исключения (вывод урезан):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

. . .

EXCEPTION_RECORD:  (.exr 1)

ExceptionAddress: 00007ff86a1e05ac (VBE7+0x00000000001405ac)

   ExceptionCode: c0000005 (Access violation)

  ExceptionFlags: 00000000

NumberParameters: 2

   Parameter[0]: 0000000000000001

   Parameter[1]: 0000000000000010

Attempt to write to address 0000000000000010

DEFAULT_BUCKET_ID:  NULL_CLASS_PTR_WRITE

PROCESS_NAME:  EXCEL.EXE

ERROR_CODE: (NTSTATUS) 0xc0000005 <Unable to get error code text>

EXCEPTION_CODE: (NTSTATUS) 0xc0000005 <Unable to get error code text>

EXCEPTION_CODE_STR:  c0000005

EXCEPTION_PARAMETER1:  0000000000000001

EXCEPTION_PARAMETER2:  0000000000000010

WRITE_ADDRESS:  0000000000000010

. . .

обычно это NTSTATUS с кодом c0000005 — Access violation, доступ запрещен. И чаще всего в дампе можно увидеть такой вот стек потока (вывод оптимизирован для улучшения представления):

. . .

STACK_TEXT:  

000000b9`1acfdd00 000001d3`2fb24e90 : 000001d3`5a0e0ef0 00000000`00000000 : VBE7+0x1405ac

000000b9`1acfdd08 000001d3`24c1fe20 : 00000000`00000000 000001d3`2fda9640 : 0x000001d3`2fb24e90

000000b9`1acfdd10 000001d3`6cf35760 : 000001d3`2fda9640 000001d3`045c9b30 : 0x000001d3`24c1fe20

000000b9`1acfdd18 000001d3`5a0e0ef0 : 000001d3`045c9b30 000001d3`2fcbb2b0 : 0x000001d3`6cf35760

000000b9`1acfdd20 00000000`00000000 : 000001d3`2fcbb2b0 000001d3`2fcbb318 : 0x000001d3`5a0e0ef0

. . .

из которого единственное что понятно, так это то, что падение Excel происходит в недрах функций библиотеки vbe7.dll (среда исполнения VBA), подгруженной в адресное пространство процесса. Это указывает на проблемы с обработчиком VBA-скриптов, в контексте Excel чаще именуемых макросами.

НЕРЕШЕННОЕ: при отладке приложений из комплекта MS Office, вы не увидите имен функций в стеке вызовов, поскольку отсутствуют отладочные символы как к основным исполняемым файлам (Excel/Word/Outlook), так и к многочисленным библиотекам. Интересно, есть ли какое-либо решение?

VBA

Так что же такое VBA и для чего он предназначается?

VBA (Visual Basic for Application) — язык макропрограммирования, основанный на языке Visual Basic.

В приложениях, входящих в комплект MS Office, таких как Excel, Word, PowerPoint и Access, VBA используется для автоматизации множества рутинных задач (напр.: повторяющихся однотипных действий), позволяет создавать формы для общения с пользователем и предлагает множество иного богатого функционала. При помощи VBA доступно управление электронной таблицей посредством объектно-ориентированной модели кода/данных, при помощи VBA-кода входные данные таблиц могут быть обработаны и представлены в итоговых (результирующих) таблицах и диаграммах (графиках). Таблица становится интерфейсом кода, позволяя легко работать, изменять его и управлять расчётами. На выходе VBA проект, используемый в структурах описанных выше приложений (электронные таблицы Excel, презентации PowerPoint, базы Access), компилируется в специальный бинарный исполняемый файл, который размещается внутри файла основного формата. Применительно к Excel это файл vbaProject.bin, который располагается внутри *.xslm-файла в директории /xl, представляющий собой бинарный исполняемый файл проекта, содержащий макрос в откомпилированном (готовом к исполнению) виде.

Наиболее вероятной причиной сбоя является повреждение блока кода VBA, содержащегося в книге Excel. Об истоках этого остается только догадываться, возможно что в структуре .xlsm-файла, в процессе работы с документом, происходят какие-то [непредвиденные разработчиками] изменения, способные приводить блок кода в неработоспособное состояние.

Решение 1: вставка нового листа

Выполните приведенную последовательность действий:

  1. Открываем [проблемный] .xlsm-файл (файл с макросами).
  2. Не нажимаем кнопку Включить содержимое.
  3. Добавляем в книгу Excel новый лист: правая кнопка мыши на ярлыках Лист1/Лист2/Лист3 → ВставитьЛист.
  4. Сохраняем электронную таблицу. Закрываем Excel.
  5. Открываем проблемный файл заново и включаем макросы.

Решение 2: перекомпиляция проекта

Выполните последовательность действий:

  1. Запускаем и открываем новую книгу Excel (не ваш проблемный файл).
  2. Открываем меню Файл — выбираем Параметры — далее открываем Центр управления безопасностью и заходим в Параметры центра управления безопасностью.
  3. В разделе Параметры макросов — выставляем чекбокс Отключить все макросы с уведомлением.
  4. В разделе Надежные расположения — выставляем чекбокс Отключить все надежные расположения.
  5. В разделе Надежные документы — выставляем чекбокс Отключить надежные документы.
  6. Жмем везде OK. Закрываем Excel.

  7. Открываем [проблемный] .xlsm-файл (файл с макросами).
  8. Не нажимаем кнопку Включить содержимое.
  9. Открывает редактор Visual Basic при помощи комбинации клавиш Alt+F11. Либо можно использовать обходной маневр: в настройках включаем меню Разработчик, после этого в появившемся сверху в ленте меню Разработчик выбираем пункт Visual Basic.
  10. В открывшемся окне редактора Visual Basic (VBA редактор) пересохраняем проект: для этого жмем на панели инструментов кнопку Сохранить (изображение дискетки или комбинация Ctrl+S).
  11. Выбираем из меню Debug — выбираем пункт меню Compile VBA Project:

    recompile vba project

  12. Еще раз сохраняем проект кнопкой Сохранить.
  13. Закрываем редактор Visual Basic.

  14. Сохраняем файл Excel через меню Файл — опцию Сохранить (или нажатием на значок дискетки в левом верхнем углу, либо комбинация клавиш Ctrl+S).
  15. Возвращаем все установки безопасности, сделанные на предыдущих шагах (пункты 2-5).
  16. Закрываем xlsm-файл.
  17. Заново открываем [проблемный] файл, в верхней части, в строке статуса — включаем макросы посредством кнопки Включить содержимое.

Решение 3: добавление модуля

Дополнительное решение состоит в том, что бы внести изменения в макрос без перекомпиляции.

  1. Открываем [проблемный] .xlsm-файл (файл с макросами).
  2. Не нажимаем кнопку Включить содержимое.
  3. Открывает редактор Visual Basic (при помощи комбинации клавиш Alt+F11).
  4. Открываем меню Tools → пункт Options. В открывшемся окне переходим на вкладку General и деактивируем чекбокс Compile on Demand:

    compile on demand

    Закрываем окно Опции нажатием клавиши OK.

  5. В левом фрейме окна проекта (Project) спускаемся вниз, находим раздел Modules, жмем на нём правую кнопку → пункт InsertModule:

    vba insert module

  6. Далее просто закрываем окно редактора Visual Basic, сохраняем основной xslm-документ и закрываем Excel.
  7. Заново открываем [проблемный] файл, в верхней части, в строке статуса — включаем макросы посредством кнопки Включить содержимое.

Four ways to fix runtime error 1004 in Excel:

Workable Solutions Step-by-step Troubleshooting
Fix 1. Delete the GWXL97.XLA Files Fix the Excel error 1004 is to find and delete the error file. Go to C:Program FilesMS OfficeOfficeXLSTART…Full steps
Fix 2. Check the Trust Access to the VBA Project Object Model Enable a VBA project trust option in Excel Trust Center to fix Excel error 1004. Open a blank Excel file…Full steps
Fix 3. Create Another Excel Template Start a new Excel workbook and make sure there is only one worksheet in it. Format the workbook first…Full steps
Fix 4. Repair Corrupted Excel File Repair corrupted Excel files with a file recovery tool. EaseUS file repair tool fixes severely corrupted XLS and XLSX files and retrieves everything from Excel…Full steps

Microsoft Visual Basic for Applications (VBA) is developed to help users write programs for the Windows operating system. It runs as an internal programming language in Microsoft Office, such as Word, Excel, and PowerPoint.

Some users have reported that when running VBA in an Excel chart or trying to generate a Macro in Excel documents, an error message popped up saying: Runtime error 1004. And then they find themselves cannot access the Excel files. If you have the same encounter as these users, this post is the right place for you. You can find both the reasons and the corresponding solutions of this error code on this page.

How to Fix Excel Error 104

Runtime Error Details

The error message contains more information than the error code 1004. Generally, follow the error code, you can see a brief description. The most repeated error messages are listed below:

  1. Runtime error 1004: Application or object-defined error.
  2. Runtime error 1004: Method Ranger of Object Worksheet failed.
  3. Runtime error 1004: Copy Method of Worksheet Class failed.

The Reason Why You See Runtime Error 1004 in Excel

If you want to know how to fix runtime error 1004 in Excel properly, you need to understand what leads to this issue. The following are the most prominent reasons.

  • Macro Name Error

The Macro you are running is copying the original worksheet to a workbook with a defined name that you did not save and close before running the Macro.

  • File Conflict

When opening the VBA Excel file, it gets conflicted with other programs.

  • Too Many Legend Entries

The Excel chart contains more legend entries than space available to display the legend entries on the chart.

  • Excel File Corruption

Your .xls files got corrupted, infected, or damaged.

Although many reasons would cause this Excel error 1004 problem, luckily, some valid methods can help users re-access the files. Let’s check them one by one.

Fix 1. Delete the GWXL97.XLA Files to Fix Runtime Error 1004 in Excel

The easiest method to fix the Excel error 1004 is to find and delete the error file.

Step 1. Go to C:Program FilesMS OfficeOfficeXLSTART.

Step 2. Find GWXL97.XLA file and delete it.

Step 3. Reopen your Excel file and check if the problem is solved.

Fix 2. Check the Trust Access to the VBA Project Object Model

Another solution you can try is to enable a VBA project trust option in Excel Trust Center. Follow the detailed steps and have a try.

Step 1. Open a blank Excel file and click «Files» on the upper left.

Step 2. Click Option and go to Trust Center.

Enter Excel Option

Step 3. Find and enter the Trust Center Settings.

Enter Trust Center Settings

Step 4. Under Macro Settings, tick the option of «Trust access to the VBA project object model.»

Trust Access to the VBA Project

Now you can check your Excel file.

Fix 3. Create Another Excel Template to Fix Runtime Error 1004 in Excel

This method could be a little bit complicated, but it’s useful and worth trying.

Step 1. Please start a new Excel workbook and make sure there is only one worksheet in it.

Step 2. Format the workbook first and then put the data you need onto it.

Step 3. Tap File > Save As, first enter the file name, and click the unfold arrow in Save as Type column.

Excel Save As

Excel 2003: Choose Excel 97-2003 Template.

Excel 2007 or Later: Choose Excel Template.

Choose the Right Template

Step 4. Click «Save» to confirm.

Now you can insert it programmatically by using the following code: Add Type:=pathfilename. The file name is the one you set when you create the new Excel template.

Fix 4. Repair Corrupted Excel Files Due to Error 1004 

If all the above solutions can’t help you out, then there is one possibility that the Excel file you want to open is damaged. To fix a damaged Excel file, you can rely on file repair software. EaseUS Data Recovery Wizard is a great choice.

With this tool, click the «Repair» button and wait for it to fix all the corrupted documents for you.

  • Repair various corrupted files, including repairing Word, Excel, and PDF document 
  • Fix unreadable contents in Word efficiently
  • Repair corrupted PDF files, extract the text, comments, labels, graphics, etc. 
  • Compatible with Microsoft Office 2019, 2016, 2013, 2010, & previous versions.

Download the software and follow the detailed steps below to fix corrupted Excel files.

Step 1. Launch EaseUS Data Recovery Wizard, and then scan disk with corrupted documents. This software enables you to fix damaged Word, Excel, PPT, and PDF files in same steps. 

select the disk with corrupted documents

Step 2. EaseUS data recovery and repair tool will scan for all lost and corrupted files. You can find the target files by file type or type the file name in the search box. 

find corrupted documents

Step 3. EaseUS Data Recovery Wizard can repair your damaged documents automatically. After file preview, you can click «Recover» to save the repaired Word, Excel, and PDF document files to a safe location.

repair corrrupt documents

The Bottom Line

After reading, you must have a thorough understanding of how to fix Runtime error 1004. If you can make sure that the Excel file you want to open is valid, then the first three methods would help you out.

Once you got a damaged Excel file, a professional file recovery tool is a wiser choice. EaseUS file repair software is highly recommended by many users & IT professionals to help you repair Word, Excel, PowerPoint, and PDF files. 

 

Возникает при переходе по ссылке из одного листа на другой

 

Сергей

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

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

Юрий я не рунописец но пока начинаю это читать

1004 Ошибка, определенная приложением или объектом. Довольно распространенное универсальное сообщение об ошибке. Данная ошибка возникает тогда, когда ошибка генерируется не в VBA. Другими словами, ошибка определяется в Excel (или в другом объекте) и передается в VBA. Также эта ситуация возникает в случае если ошибка генерируется специально (для этого используется метод Raise объекта Err), но она не определена в VBA

Прикладывайте примеры

Лень двигатель прогресса, доказано!!!

 

Юрий М

Модератор

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

Контакты см. в профиле

Юрий, я подправил название темы: так больше конкретики. Ведь с Вашим названием все вопросы по ошибкам можно смело задавать в Вашей теме. Так лучше? Ну почему бы самому не придумать нормальное название?

 

Сергей

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

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

Юрий Глодовский, я почему говорю про пример и почему так быстро привел описание ошибки, потому что ща сам сижу втыкаю в неё, так ка записал макрорекодером макрос попытался его усовершенствовать и мне выдает такую фигню и я не думаю что мы с вами делаем одно и тоже

Лень двигатель прогресса, доказано!!!

 

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

 

Юрий М

Модератор

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

Контакты см. в профиле

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

 

Сергей

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

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

#7

16.05.2014 22:53:10

Цитата
Юрий Глодовский пишет: У меня вопрос в какую сторону хотя бы копать.

это не ко мне, сам тупил над такой же ошибкой около 30 минут, грохнул макрос рисую заново, но это чисто развлекуха под пиво к работе у меня ни как не относится

Лень двигатель прогресса, доказано!!!

 

Юрий Глодовский

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

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

#8

16.05.2014 23:42:20

Юрий М, в третьей строке, тот что If Not Intersect…

Код
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
    '// Проверяем, что выделенная ячейка пересеклась с колонкой "А"
    If Not Intersect(Target, Columns("C")) Is Nothing And Target.Parent.Name = "База" Then
        '//Проверяем, что это не первая строка (там у нас будет заголовок таблицы)
        If Target.Row <> 1 Then
            If Target.Cells.Count = 1 Then '// Если выделена только одна ячейка
                '// Проверяем, что ячейка не пуста
                If Len(Target.Offset(0, -2).Value) <> 0 Then
                    '// На всякий случай - предотвращение ошибок во время файловых операций
                    On Error Resume Next
                    '// Внимание Mkdir (в отличие от DOS-версии) не умеет создавать цепочку папок
                    '// Это означает, что папка, в которой нужно создавать новую, уже должна существовать
                    Dim HomeDir$
                    HomeDir = "D:Base" '// Задаем исходную папку (у Вас - это: "D:Base")
                    MkDir (HomeDir & "" & Target.Offset(0, -2).Value)
                    If Err = 0 Then Cells(Target.Row, "C").Formula = "=HYPERLINK(""" & HomeDir & """&A" & Target.Row & ",""IIIII"")"
                End If
            End If
        End If
    End If
End Sub
 
 

Сергей

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

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

#9

16.05.2014 23:44:38

Цитата
Юрий М пишет: Начните с того, что прогоните код пошагово: для начала выясним — на какой строке и в какой процедуре возникает эта ошибка.

Юрий Глодовский, обращайте внимание на советы, если не знаете как это сделать, спрашивайте, дадут либо ссылку либо совет как это сделать, КОТ хоть и сидит со скелетом но форумчан редко ест

Лень двигатель прогресса, доказано!!!

 

Hugo

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

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

#10

16.05.2014 23:46:23

У меня нет ошибки.
Но попробуйте

Код
    If Not Intersect(Target, ActiveSheet.Columns("C")) Is Nothing And Target.Parent.Name = "База" Then 

кто его знает…
или

Код
    If Not Intersect(Target, target.parent.Columns(3)) Is Nothing And Target.Parent.Name = "База" Then 

Изменено: Hugo17.05.2014 08:31:16

 

Юрий М

Модератор

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

Контакты см. в профиле

Без файла сложно, конечно… Лист «База» есть?

 

Hugo

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

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

Юра, у меня листа База не было. В начале :)
Это не влияет. Нет листа — не выполняется условие всего лишь…

 

Сергей

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

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

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

Лень двигатель прогресса, доказано!!!

 

Юрий Глодовский

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

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

#14

17.05.2014 00:00:16

Цитата
Hugo пишет: If Not Intersect(Target, target.parent.Columns(3)) Is Nothing And Target.Parent.Name = «База» Then

Этот вариант помог. Большое спасибо.
Сергей, посмотрите, может вам пригодится.

 

Юрий М

Модератор

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

Контакты см. в профиле

#15

17.05.2014 00:02:43

Немного смущает несоответствие комментария и строки кода. Комментарий ошибку не вызовет, но всё же:

Код
'// Проверяем, что выделенная ячейка пересеклась с колонкой "А" 

А проверяем столбец С.

 

Сергей

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

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

#16

17.05.2014 00:13:50

Цитата
Юрий Глодовский пишет: может вам пригодится.

в будущем может, на данном моменте эволюции понимания в VBA у меня даже таких строк нет

Лень двигатель прогресса, доказано!!!

 

Казанский

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

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

#17

17.05.2014 01:13:52

Замечу, что Target.Parent это Sh, который передается в процедуру.
Лучше разбить первую проверку на две, чтобы сначала шла быстрая операция сравнения имени, а потом громоздкий Intersect:

Код
If Sh.Name = "База" Then
  If Not Intersect(Target, Sh.Columns(3)) Is Nothing Then 

Return to VBA Code Examples

In this Article

  • VBA Error 1004 – Object does not exist
  • VBA Error 1004 – Name Already Taken
  • VBA Error 1004 – Incorrectly Referencing an Object
  • VBA Error 1004 – Object Not Found

This tutorial will explain the VBA Error 1004- Application-Defined or Object-Defined Error.

VBA run-time error 1004 is known as an Application-Defined or Object-Defined error which occurs while the code is running. Making coding errors (See our Error Handling Guide) is an unavoidable aspect learning VBA but knowing why an error occurs helps you to avoid making errors in future coding.

VBA Error 1004 – Object does not exist

If we are referring to an object in our code such as a Range Name that has not been defined, then this error can occur as the VBA code will be unable to find the name.

Sub CopyRange()
  Dim CopyFrom As Range
  Dim CopyTo As Range
  Set CopyFrom = Sheets(1).Range("CopyFrom")
  Set CopyTo = Sheets(1).Range("CopyTo")
  CopyFrom.Copy
CopyTo.PasteSpecial xlPasteValues
End Sub

The example above will copy the values from the named range “CopyFrom” to the named range “CopyTo” – on condition of course that these are existing named ranges!  If they do not exist, then the Error 1004 will display.

VBA Error1004 1

The simplest way to avoid this error in the example above is to create the range names in the Excel workbook, or refer to the range in the traditional row and column format eg: Range(“A1:A10”).

VBA Error 1004 – Name Already Taken

The error can also occur if you are trying to rename an object to an object that already exists – for example if we are trying to rename Sheet1 but the name you are giving the sheet is already the name of another sheet.

Sub NameWorksheet()
  ActiveSheet.Name = "Sheet2"
End Sub

If we already have a Sheet2, then the error will occur.

VBA Error1004 2

VBA Error 1004 – Incorrectly Referencing an Object

The error can also occur when you have incorrectly referenced an object in your code. For example:

Sub CopyRange()
  Dim CopyFrom As Range
  Dim CopyTo As Range
  Set CopyFrom = Range("A1:A10")
  Set CopyTo = Range("C1:C10")
  Range(CopyFrom).Copy
  Range(CopyTo).PasteSpecial xlPasteValues
End Sub

This will once again give us the Error 10004

VBA Error1004 1

Correct the code, and the error will no longer be shown.

Sub CopyRange()
  Dim CopyFrom As Range
  Dim CopyTo As Range
  Set CopyFrom = Range("A1:A10")
  Set CopyTo = Range("C1:C10")
  CopyFrom.Copy
  CopyTo.PasteSpecial xlPasteValues
End Sub

VBA Error 1004 – Object Not Found

This error can also occur when we are trying to open a workbook and the workbook is not found – the workbook in this instance being the object that is not found.

Sub OpenFile()
 Dim wb As Workbook
 Set wb = Workbooks.Open("C:DataTestFile.xlsx")
End Sub

Although the message will be different in the error box, the error is still 1004.

VBA Error 1004 FileNotFound

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!
vba save as

Learn More!

На чтение 25 мин. Просмотров 16.3k.

VBA Error Handling

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

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

Если вы новичок в VBA, то вы можете прочитать пост от начала до конца, так как он выложен в логическом порядке.

Содержание

  1. Краткое руководство по обработке ошибок
  2. Введение
  3. Ошибки VBA
  4. Заявление об ошибке
  5. Err объект
  6. Логирование
  7. Другие элементы, связанные с ошибками
  8. Простая стратегия обработки ошибок
  9. Полная стратегия обработки ошибок
  10. Обработка ошибок в двух словах

Краткое руководство по обработке ошибок

Пункт Описание
On Error Goto 0 При возникновении ошибки код останавливается и отображает
ошибку.
On Error Resume Next Игнорирует ошибку и
продолжает.
On Error Goto [Label] Переход к определенной метке при возникновении ошибки.
Это позволяет нам справиться
с ошибкой.
Err Object При возникновении ошибки
информация об ошибке
сохраняется здесь.
Err.Number Номер ошибки.
(Полезно, только если вам
нужно проверить, произошла ли конкретная ошибка.)
Err.Description Содержит текст ошибки.
Err.Source Вы можете заполнить это, когда используете Err.Raise.
Err.Raise Функция, которая позволяет
генерировать вашу собственную ошибку.
Error Function Возвращает текст ошибки из
номера ошибки.
Вышло из употребления.
Error Statement Имитирует ошибку. Вместо этого используйте Err.Raise.

Введение

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

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

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

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

VBA Error Handling

Ошибки VBA

В VBA есть три типа ошибок

  1. Синтаксис
  2. Компиляция
  3. Время выполнения

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

Синтаксические ошибки

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

Например, если вы введете If и забудете ключевое слово Then,
VBA отобразит следующее сообщение об ошибке.

VBA Error Handling

Некоторые примеры синтаксических ошибок

' then отсутствует
If a > b

' не хватает = после i
For i 2 To 7

' отсутствует правая скобка
b = left("АБВГ",1

Синтаксические ошибки относятся только к одной строке. Они
возникают, когда синтаксис одной строки неверен.

Примечание. Диалоговое окно «Ошибка синтаксиса» можно отключить, выбрав «Сервис» -> «Параметры» и отметив «Автосинтаксическая проверка». Строка по-прежнему будет отображаться красным цветом в случае ошибки, но диалоговое окно не появится.

Ошибки компиляции

Ошибки компиляции происходят более чем в одной строке.
Синтаксис в одной строке правильный, но неверный, если учесть весь код проекта.

Примеры ошибок компиляции:

  • Оператор If без соответствующего оператора End If
  • For без Next
  •  Select без End Select
  • Вызов Sub или Function, которые не существуют
  • Вызов Sub или Function с неверными параметрами
  • Присвоение Sub или Function того же имени, что и для модуля
  • Переменные не объявлены (Option Explicit должен присутствовать в верхней части модуля)

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

VBA Error Handling

Использование Debug-> Compile

Чтобы найти ошибки компиляции, мы используем Debug->
Compile VBA Project из меню Visual Basic.

Когда вы выбираете Debug-> Compile, VBA отображает первую
обнаруженную ошибку.

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

Debug-> Compile также будет включать синтаксические
ошибки в поиск, что очень полезно.

Если ошибок не осталось и вы запускаете Debug-> Compile,
может показаться, что ничего не произошло. Однако «Компиляция» будет недоступна
в меню «Отладка». Это означает, что ваше приложение не имеет ошибок компиляции
в текущий момент.

Debug->Compile Error Summary

Debug-> Compile находит ошибки компиляции (проекта).

Он также найдет синтаксические ошибки.

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

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

Debug-> Compile Usage

Вы должны всегда использовать Debug-> Compile, прежде чем
запускать свой код. Это гарантирует, что ваш код не будет иметь ошибок
компиляции при запуске.

Если вы не запускаете Debug-> Compile, то VBA может
обнаружить ошибки компиляции при запуске. Их не следует путать с ошибками
времени выполнения.

Ошибки во время выполнения

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

VBA Error Handling

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

Другие примеры ошибок времени выполнения

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

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

Ожидаемые и неожиданные ошибки

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

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

Sub OtkritFail()
    
    Dim sFile As String
    sFile = "C:ДокументыОтчет.xlsx"
    
    ' Используйте Dir, чтобы проверить, существует ли файл
    If Dir(sFile) = "" Then
        ' если файл не существует, отобразить сообщение
        MsgBox "Файл не найден" & sFile
        Exit Sub
    End If
    
    ' Код достигнет только если файл существует
    Workbooks.Open sFile
    
End Sub

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

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

Ошибки времени выполнения, которые не являются ошибками VBA

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

Позвольте мне объяснить это на примере. Представьте, что у
вас есть приложение, которое требует, чтобы вы добавили значения в переменные a
и b

Допустим, вы по ошибке используете звездочку вместо знака
плюс

Это не ошибка VBA. Ваш синтаксис кода является совершенно
законным. Однако, с вашей точки зрения, это ошибка.

Эти ошибки не могут быть обработаны с помощью обработки ошибок, поскольку они, очевидно, не будут генерировать никаких ошибок. Вы можете справиться с этими ошибками, используя Unit Testing and Assertions.

Заявление об ошибке

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

  1. Ожидаемые ошибки — напишите конкретный код для
    их обработки.
  2. Неожиданные ошибки — используйте операторы
    обработки ошибок VBA для их обработки.

Оператор VBA On Error используется для обработки ошибок.
Этот оператор выполняет некоторые действия при возникновении ошибки во время
выполнения.

Есть четыре различных способа использовать это утверждение

  1. On Error Goto 0 — код останавливается на строке с ошибкой и отображает сообщение.
  2. On Error Resume Next — код перемещается на следующую строку. Сообщение об ошибке не отображается.
  3. On Error Goto [label] — код перемещается на определенную строку или метку. Сообщение об ошибке не отображается. Это тот, который мы используем для обработки ошибок.
  4. On Error Goto -1 — очищает текущую ошибку.

Давайте посмотрим на каждое из этих утверждений по очереди.

On Error Goto 0

Это поведение по умолчанию VBA. Другими словами, если вы не
используете On Error, это поведение вы увидите.

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

Давайте посмотрим на пример. В следующем коде мы не
использовали строку On Error, поэтому VBA будет использовать поведение On Error
Goto 0 по умолчанию.

Sub IspDefault()

    Dim x As Long, y As Long
    
    x = 6
    y = 6 / 0
    x = 7

End Sub

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

VBA Error Handling

Когда появляется ошибка, вы можете выбрать End или Debug

Если вы выберете Конец, то приложение просто остановится.

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

VBA Error Handling

Это нормально, когда вы пишете код VBA, поскольку он
показывает вам точную строку с ошибкой.

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

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

Используя On Error Goto [label], мы можем дать пользователю
более контролируемое сообщение об ошибке. Это также предотвращает остановку
приложения. Мы можем заставить приложение работать предопределенным образом.

On Error Resume Next

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

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

Если мы добавим Resume Next к нашему примеру Sub, то VBA
проигнорирует ошибку деления на ноль

Sub UsingResumeNext()

    On Error Resume Next
    
    Dim x As Long, y As Long
    
    x = 6
    y = 6 / 0
    x = 7

End Sub

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

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

Sub OtprSoobsch()

   On Error Resume Next
   
    ' Требуется ссылка:
    ' Библиотека объектов Microsoft Outlook 15.0
    Dim Outlook As Outlook.Application
    Set Outlook = New Outlook.Application

    If Outlook Is Nothing Then
        MsgBox " Не удается создать сеанс Microsoft Outlook." _
                   & " Письмо не будет отправлено."
        Exit Sub
    End If
    
End Sub

В этом коде мы проверяем, доступен ли Microsoft Outlook на компьютере. Все,
что мы хотим знать — это доступно или нет. Нас не интересует конкретная ошибка.

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

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

On Error Goto [label]

Вот как мы используем обработку ошибок в VBA. Это эквивалент функциональности Try and Catch, которую вы видите на
таких языках, как C # и
Java.

При возникновении ошибки вы отправляете ошибку на
определенный ярлык. Обычно это внизу саба.

Давайте применим это к подводной лодке, которую мы
использовали

Sub IspGotoLine()

    On Error Goto eh
    
    Dim x As Long, y As Long
    
    x = 6
    y = 6 / 0
    x = 7
    
Done:
    Exit Sub
eh:
    MsgBox "Произошла следующая ошибка: " & Err.Description
End Sub

Снимок экрана ниже показывает, что происходит при возникновении ошибки.

VBA Error Handling

VBA переходит на метку eh, потому что мы указали это в
строке «Перейти к ошибке».

Примечание 1: Метка, которую мы используем в операторе On… Goto, должна быть в текущей Sub / Function. Если нет, вы получите ошибку компиляции.

Примечание 2: Когда возникает ошибка при использовании On Error Goto [label], обработка ошибок возвращается к поведению по умолчанию, т.е. код остановится на строке с ошибкой и отобразит сообщение об ошибке. См. Следующий раздел для получения дополнительной информации об этом.

On Error Goto -1

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

При возникновении ошибки с помощью функции On Error Goto [label] поведение обработки ошибки возвращается к поведению по умолчанию, т.е. On Error Goto 0 . Это означает, что если произойдет другая ошибка, код остановится на текущей строке.

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

Посмотрите на код ниже. Первая ошибка приведет к переходу
кода на метку eh. Вторая ошибка остановится на строке с ошибкой 1034.

Sub DveOshibki()

    On Error Goto eh
        
    ' генерировать ошибку «Несоответствие типов»
    Error (13)

Done:
    Exit Sub
eh:
    ' генерировать «определенную приложением» ошибку
    Error (1034)
End Sub

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

В коде ниже мы добавили строку

после того как мы поймаем первую ошибку.

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

Sub DveOshibki()

    On Error Goto eh
        
    ' генерировать ошибку «Несоответствие типов»
    Error (13)

Done:
    Exit Sub
eh:
    On Error Goto eh_other
    ' генерировать «определенную приложением» ошибку
    Error (1034)
Exit Sub
eh_other:
    Debug.Print "ehother " & Err.Description
End Sub

Для устранения ошибки мы используем On Error Goto -1.
Думайте об этом как об установке ловушки для мыши. Когда ловушка сработает, вам
нужно установить ее снова.

В приведенном ниже коде мы добавляем эту строку, и вторая
ошибка теперь приведет к переходу кода на метку eh_other.

Sub DveOshibki()

    On Error Goto eh
        
    ' генерировать ошибку «Несоответствие типов»
    Error (13)

Done:
    Exit Sub
eh:
    ' явная ошибка
    On Error Goto -1
    
    On Error Goto eh_other
    ' генерировать «определенную приложением» ошибку
    Error (1034)
Exit Sub
eh_other:
    Debug.Print "ehother " & Err.Description
End Sub

Примечание 1. Вероятно, в редких случаях полезно использовать On Error Goto -1. Мне лично никогда не приходилось пользоваться этой линией. Помните, что как только вы выйдете из Sub, ошибка все равно будет очищена.

Примечание 2. у объекта Err есть член Clear. Использование Clear очищает текст и цифры в объекте Err, но НЕ сбрасывает ошибку.

Использование On Error

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

  • Остановитесь и отобразите ошибку.
  • Игнорируйте ошибку и продолжайте.
  • Перейти к определенной строке.

VBA всегда будет настроен на одно из этих действий. Когда вы
используете On Error, VBA изменит ваше поведение и забудет о любом предыдущем.

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

Sub ErrorSostoyaniya()

    Dim x As Long
    
    ' Перейти на этикетке, если ошибка
    On Error Goto eh
    
    ' это проигнорирует ошибку в следующей строке
    On Error Resume Next
    x = 1 / 0
    
    ' это отобразит сообщение об ошибке в следующей строке
    On Error Goto 0
    x = 1 / 0
  
Done:  
   Exit Sub
eh:
    Debug.Print Err.Description
End Sub

Err объект

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

При возникновении ошибки времени выполнения VBA
автоматически заполняет объект Err деталями.

Приведенный ниже код выведет «Error Number: 13 Type
Mismatch», которое возникает, когда мы пытаемся поместить строковое значение в
длинное целое число.

Sub IspErr()

    On Error Goto eh
    
    Dim total As Long
    total = "aa"

Done:
    Exit Sub
eh:
    Debug.Print "Номер ошибки: " & Err.Number _
            & " " & Err.Description
End Sub

Err.Description предоставляет подробную информацию об ошибке, которая происходит. Это текст, который вы обычно видите, когда возникает ошибка, например, «Несоответствие типов»

Err.Number — это идентификационный номер ошибки, например, номер ошибки для «Несоответствие типов» — 13. Единственное время, когда вам действительно нужно это, если вы проверяете, что произошла конкретная ошибка, и это необходимо только в редких случаях.

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

Получение номера строки

Функция Erl используется для возврата номера строки, где
произошла ошибка.

Это часто вызывает путаницу. В следующем коде Erl вернет ноль.

Sub IspErr()

    On Error Goto eh
    
    Dim val As Long
    val = "aa"

Done:
    Exit Sub
eh:
    Debug.Print Erl
End Sub

Это потому, что нет номеров строк. Большинство людей не
понимают этого, но VBA позволяет вам иметь номера строк.

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

Sub IspErr()

10        On Error Goto eh
          
          Dim val As Long
20        val = "aa"

Done:
30        Exit Sub
eh:
40        Debug.Print Erl
End Sub

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

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

Использование Err.Raise

Err.Raise позволяет нам создавать ошибки. Мы можем
использовать его для создания пользовательских ошибок для нашего приложения,
что очень полезно. Это эквивалент оператора Throw в Java C #.

Формат следующий

Err.Raise [error number], [error source], [error description]

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

Public Const ERROR_INVALID_DATA As Long = vbObjectError + 513

Sub ReadWorksheet()

    On Error Goto eh
    
    If Len(Sheet1.Range("A1")) <> 5 Then
        Err.Raise ERROR_INVALID_DATA, "ReadWorksheet" _
            , "Значение в ячейке A1 должно иметь ровно 5 символов."
    End If
    
    ' продолжить, если ячейка имеет действительные данные
    Dim id As String
    id = Sheet1.Range("A1")
    

Done:
    Exit Sub
eh:
    ' Err.Raise отправит код сюда
    MsgBox " Обнаружена ошибка: " & Err.Description
End Sub

Когда мы создаем ошибку, используя Err.Raise, нам нужно присвоить ей номер. Мы можем использовать любое
число от 513 до 65535 для нашей ошибки. Мы должны использовать vbObjectError с номером,
например

Err.Raise vbObjectError + 513

Использование Err.Clear

Err.Clear используется для очистки текста и чисел из объекта
Err.Object. Другими словами, он очищает описание и номер.

Редко вам понадобится его использовать, но давайте
рассмотрим пример, где вы могли бы.

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

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

Sub IspErrClear()

    Dim count As Long, i As Long

    ' Продолжите, если ошибка, так как мы проверим номер ошибки
    On Error Resume Next
    
    For i = 0 To 9
        ' генерировать ошибку для каждого второго
        If i Mod 2 = 0 Then Error (13)
        
        ' Проверьте на ошибку
        If Err.Number <> 0 Then
            count = count + 1
            Err.Clear    ' Очистить Err, как только он считается
        End If
    Next

    Debug.Print " Количество ошибок было: " & count
End Sub

Примечание: Err.Clear сбрасывает текст и цифры в объекте ошибки, но не очищает ошибку — см. On Error Goto -1 для получения дополнительной информации об очистке фактической ошибки.

Логирование

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

Код ниже показывает очень простую процедуру регистрации

Sub Logger(sType As String, sSource As String, sDetails As String)
    
    Dim sFilename As String
    sFilename = "C:templogging.txt"
    
    ' Архивный файл определенного размера
    If FileLen(sFilename) > 20000 Then
        FileCopy sFilename _
            , Replace(sFilename, ".txt", Format(Now, "ddmmyyyy hhmmss.txt"))
        Kill sFilename
    End If
    
    ' Откройте файл для записи
    Dim filenumber As Variant
    filenumber = FreeFile 
    Open sFilename For Append As #filenumber
    
    Print #filenumber, CStr(Now) & "," & sType & "," & sSource _
                                & "," & sDetails & "," & Application.UserName
    
    Close #filenumber
    
End Sub

Вы можете использовать это так:

' Создать уникальный номер ошибки
Public Const ERROR_DATA_MISSING As Long = vbObjectError + 514

Sub CreateReport()

    On Error Goto eh
    
    If Sheet1.Range("A1") = "" Then
       Err.Raise ERROR_DATA_MISSING, "CreateReport", "Данные отсутствуют в ячейке A1"
    End If

    ' другой код здесь
Done:
    Exit Sub
eh:
    Logger "Error", Err.Source, Err.Description
End Sub

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

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

Sub ReadingData()
    
    Logger "Information", "ReadingData()", "Starting to read data."
       
    Dim coll As New Collection
    ' Read data
    Set coll = ReadData
    
    If coll.Count < 10 Then
        Logger "Warning", "ReadingData()", "Number of data items is low."
    End If
    Logger "Information", "ReadingData()", "Number of data items is " & coll.Count
    
    Logger "Information", "ReadingData()", "Finished reading data."

End Sub

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

Другие элементы, связанные с ошибками

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

Функция ошибки

Функция Error используется для печати описания ошибки с
заданным номером ошибки. Он включен в VBA для обеспечения обратной
совместимости и не нужен, поскольку вместо него можно использовать описание
Err.Description.

Ниже приведены некоторые примеры

' Распечатать текст «Деление на ноль»
Debug.Print Error(11)
' Распечатать текст "Несоответствие типов"
Debug.Print Error(13)
' Распечатать текст "Файл не найден"
Debug.Print Error(53)

Заявление об ошибке

Заявление об ошибке позволяет имитировать ошибку. Он включен
в VBA для обратной совместимости. Вместо этого вы должны использовать
Err.Raise.

В следующем коде мы моделируем ошибку «Разделить на ноль».

Sub ZayavlObOshibke()

    On Error Goto eh
        
    ' Это создаст деление на ноль ошибок
    Error 11
    
    Exit Sub
eh:
    Debug.Print Err.Number, Err.Description
End Sub

Это утверждение включено в VBA для обратной совместимости.
Вместо этого вы должны использовать Err.Raise.

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

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

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

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

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

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

error-handling

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

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
возникает ошибка

Error Handling – bubbling

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

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

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 & "Line no: " & lineno & " "
        End If
   
        ' Добавить маркер и процедуру к источнику
        sSource = MARKER & sSource & vbCrLf & proc
        
    Else
        ' Если ошибка уже возникла, просто добавьте имя процедуры
        sSource = src & vbCrLf & 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 = " Произошла следующая ошибка: " & vbCrLf & Err.Description _
                    & vbCrLf & vbCrLf & " Расположение ошибки: "
    
    sMsg = sMsg + src & vbCrLf & sProcname
    
    ' Показать сообщение
    MsgBox sMsg, Title:="Ошибка "
    
End Sub

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

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

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

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

error handling output

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

error handling output line

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

“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 с ошибкой, вы можете обновить ошибку и сбросить ее.
  • Вы можете использовать журнал для записи информации о приложении, когда оно запущено.

Если вы используете Excel, вы можете столкнуться с ошибкой «Ошибка выполнения 424» с сообщением «Требуется объект».

Это ошибка в VBA (Visual Basic для приложений) и в основном проявляется, когда вы указываете на объект, который либо не существует, либо не находится за пределами текущей области.

Если вы видите ошибку, когда кто-то «обрабатывает» какой-то макрос/автоматизированную функцию в электронных таблицах Excel, вероятная проблема заключается в том, что вы называете объект «вне контекста». Это означает, что вы можете загрузить объект, но его содержимое может быть изменено или изменено. Есть также некоторые другие потенциальные проблемы, которые я объясню в этом руководстве…

причина

Ошибка, которую вы видите, будет иметь следующее сообщение:

Ошибка времени запуска «424»

Требуется объект

Чтобы объяснить, почему он показывает ошибку и что это значит, Microsoft выпустила свой пакет «Visual Basic» в конце 90-х.

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

Из-за этого Microsoft представила «VBA» (Visual Basic для приложений) в своем пакете программного обеспечения Office, а именно в Excel и Word. Это позволило типам разработчиков создавать автоматические функции в электронных таблицах Excel, указывать на «объекты» в самой электронной таблице и так далее.

Каждый раз, когда мы используем Visual Basic, мы вызываем ряд «объектов» в памяти. Эти объекты являются просто переменными, используемыми в ряде дополнительных функций, включая пользовательские функции и так далее. Проблема — и это относится к большинству языков программирования — в том, что если указать на объект, который не вызывается, приложение рухнет.

решение

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

1. Убедитесь, что переменные определены правильно

Основная проблема заключается в том, что вы вызываете метод для несуществующей переменной (объекта). Наиболее распространенная причина этого заключается в том, что вы просто неправильно вводите имя переменной и поэтому не объявляете ее в своем приложении VBA. Возьмем следующий пример:

Подтест ()

Application33.WorksheetFunction.Sum (диапазон (“A1: A100”))

Последняя подписка

Вышеприведенное вызовет ошибку, потому что вы пытаетесь вызвать метод WorksheetFunction для «Application33», указанного в объекте.

К сожалению, объект Application33 не существует в памяти, что не позволяет вашему приложению загрузить его. Чтобы исправить это, вам нужно просмотреть исходный код (почти всегда будут указаны неправильные ссылки) и исправить все имена объектов с ошибками.

2. Если вы используете Excel, убедитесь, что есть диапазоны/селекторы

Одна из наиболее распространенных причин ошибки заключается в том, что вы пытаетесь указать несуществующий объект или значение. Это типичная проблема при использовании одного из объектов VLookup или ActiveX. Если вы столкнулись с этой ошибкой, убедитесь, что код указывает только на существующие объекты:

Частный дополнительный тест ()

Это вызовет ошибку

Application.WorksheetFunction.VLookup(TeamName, Range (“TeamNameLookup”), 3, False).

Стоимость должна быть

Application.WorksheetFunction.VLookup(TeamName, Sheets (“YourSheetName”). Диапазон (“TeamNameLookup”), 3, False)

Последняя подписка

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

3. Убедитесь, что у вас есть правильные определения

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

От неправильного определения переменных как неверных интерпретаций объектов до вызова «Option Explicit» вы можете пытаться указать переменные/объекты, которые не определены только потому, что они определены неправильно.

Например…

Вариант очевиден

Персональный дополнительный тест ()

Здесь вам нужно объявить переменные, прежде чем пытаться указать/заполнить их

Например…

Затемните your_path как строку

Установите your_path = “x/y/z”

Последняя подписка

В приведенном выше примере, если переменная «ваш_путь» не объявлена ​​до ее установки, вы получите ошибку 424 (поскольку объект «ваш_путь» не существует). Отсюда вы также должны убедиться, что вы можете вызывать соответствующие объекты (если вы указываете значение рабочего листа, вы должны убедиться, что рабочий лист существует и может быть загружен).

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

Понравилась статья? Поделить с друзьями:
  • При запуске dead island вылетает пустая ошибка
  • При запуске dead island riptide вылазит ошибка
  • При запуске crossout выдает ошибку
  • При запуске coreldraw выдает ошибку 127
  • При запуске civilization 6 выдает ошибку