Не так давно очередной раз столкнулся с ошибками приложения Excel при попытке включения макросов после открытия файлов .xlsm. Вспомнил, что подобные проблемы преследуют пользователей довольно давно, но чаще всего они наблюдались с Excel 2013 и Excel 2016. Характерные особенности этой группы ошибок следующие:
- Приложение Excel закрывается при открытии файла с макросами (при включенном режиме безопасности Включить все макросы);
- Ошибка приложения Excel возникает при попытке включить содержимое (нажатии соответствующей кнопки);
- Ошибка приложения Excel возникает при сохранении файла с макросами;
Ну и по горячим следам очередного инцидента, дабы не откладывать на потом, решил для себя собрать небольшой хаб по ошибкам приложения Excel с последующей модификацией, дабы опять не терять время на поиск информации в Сети и на составление облака причин.
Суть в том, что в процессе открытия файла xlsm, и при отключенных макросах, в верхней части основного окна (над таблицей), высвечивается строка уведомления: ПРЕДУПРЕЖДЕНИЕ СИСТЕМЫ БЕЗОПАСНОСТИ Запуск макросов отключен, с кнопкой включения содержимого (макросов). Как только пользователь её нажимает, Excel попросту аварийно завершается (падает) с ошибкой Программа Microsoft 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: вставка нового листа
Выполните приведенную последовательность действий:
- Открываем [проблемный] .xlsm-файл (файл с макросами).
- Не нажимаем кнопку Включить содержимое.
- Добавляем в книгу Excel новый лист: правая кнопка мыши на ярлыках Лист1/Лист2/Лист3 → Вставить → Лист.
- Сохраняем электронную таблицу. Закрываем Excel.
- Открываем проблемный файл заново и включаем макросы.
Решение 2: перекомпиляция проекта
Выполните последовательность действий:
- Запускаем и открываем новую книгу Excel (не ваш проблемный файл).
- Открываем меню Файл — выбираем Параметры — далее открываем Центр управления безопасностью и заходим в Параметры центра управления безопасностью.
- В разделе Параметры макросов — выставляем чекбокс Отключить все макросы с уведомлением.
- В разделе Надежные расположения — выставляем чекбокс Отключить все надежные расположения.
- В разделе Надежные документы — выставляем чекбокс Отключить надежные документы.
- Жмем везде OK. Закрываем Excel.
- Открываем [проблемный] .xlsm-файл (файл с макросами).
- Не нажимаем кнопку Включить содержимое.
- Открывает редактор Visual Basic при помощи комбинации клавиш Alt+F11. Либо можно использовать обходной маневр: в настройках включаем меню Разработчик, после этого в появившемся сверху в ленте меню Разработчик выбираем пункт Visual Basic.
- В открывшемся окне редактора Visual Basic (VBA редактор) пересохраняем проект: для этого жмем на панели инструментов кнопку Сохранить (изображение дискетки или комбинация Ctrl+S).
- Выбираем из меню Debug — выбираем пункт меню Compile VBA Project:

- Еще раз сохраняем проект кнопкой Сохранить.
- Закрываем редактор Visual Basic.
- Сохраняем файл Excel через меню Файл — опцию Сохранить (или нажатием на значок дискетки в левом верхнем углу, либо комбинация клавиш Ctrl+S).
- Возвращаем все установки безопасности, сделанные на предыдущих шагах (пункты 2-5).
- Закрываем xlsm-файл.
- Заново открываем [проблемный] файл, в верхней части, в строке статуса — включаем макросы посредством кнопки Включить содержимое.
Решение 3: добавление модуля
Дополнительное решение состоит в том, что бы внести изменения в макрос без перекомпиляции.
- Открываем [проблемный] .xlsm-файл (файл с макросами).
- Не нажимаем кнопку Включить содержимое.
- Открывает редактор Visual Basic (при помощи комбинации клавиш Alt+F11).
- Открываем меню Tools → пункт Options. В открывшемся окне переходим на вкладку General и деактивируем чекбокс Compile on Demand:

Закрываем окно Опции нажатием клавиши OK.
- В левом фрейме окна проекта (Project) спускаемся вниз, находим раздел Modules, жмем на нём правую кнопку → пункт Insert → Module:

- Далее просто закрываем окно редактора Visual Basic, сохраняем основной xslm-документ и закрываем Excel.
- Заново открываем [проблемный] файл, в верхней части, в строке статуса — включаем макросы посредством кнопки Включить содержимое.
При выполнении макросов Excel могут возникнуть ошибки, которые в VBA делят на три категории:
- Ошибки компиляции
- Ошибки выполнения
- Логические ошибки (баги)
Далее мы поговорим о каждом из трёх типов ошибок VBA подробно.
Содержание
- Ошибки компиляции
- Ошибки выполнения
- Перехват ошибок выполнения
- Логические ошибки
Ошибки компиляции
Компилятор VBA рассматривает ошибки компиляции как недопустимые и выделяет их в коде ещё до того, как дело дойдёт до запуска макроса.
Если при написании кода допущена синтаксическая ошибка, то редактор VBA сигнализирует об этом немедленно: либо при помощи окна с сообщением, либо выделяя ошибку красным цветом, в зависимости от статуса режима Auto Syntax Check.
Примечание: При включённом режиме Auto Syntax Check каждый раз, при появлении в редакторе Visual Basic во введённом коде синтаксической ошибки, будет показано соответствующее сообщение. Если же этот режим выключен, то редактор VBA продолжит сообщать о синтаксических ошибках, просто выделяя их красным цветом. Опцию Auto Syntax Check можно включить/выключить в меню Tools > Options редактора Visual Basic.
В некоторых случаях ошибка компиляции может быть обнаружена при выполнении компиляции кода, непосредственно перед тем, как макрос будет выполнен. Обычно ошибку компиляции несложно обнаружить и исправить, потому что компилятор VBA даёт информацию о характере и причине ошибки.

Например, сообщение «Compile error: Variable not defined» при попытке запустить выполнение кода VBA говорит о том, что происходит попытка использовать или обратиться к переменной, которая не была объявлена для текущей области (такая ошибка может возникнуть только если используется Option Explicit).
Ошибки выполнения
Ошибки выполнения возникают в процессе выполнения кода и приводят к остановке выполнения программы. Этот тип ошибок VBA, как правило, также не сложно обнаружить и исправить, так как сообщается информация о характере ошибки и место в коде, где произошла остановка.
Примером такой ошибки может служить попытка выполнить деление на ноль. В результате будет показано сообщение «Run-time error ’11’: Division by zero«.

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

Получив такое сообщение и видя выделенную строку кода, как в приведённом выше примере, обнаружить причину ошибки будет совсем не сложно.
В случае если код сложнее, чем в нашем примере, то, чтобы получить больше информации о причине возникновения ошибки VBA, можно проверить значения используемых переменных. В редакторе VBA для этого достаточно навести указатель мыши на имя переменной, или можно открыть окно отслеживания локальных переменных (в меню редактора View > Locals Window).
Коды различных ошибок выполнения расшифрованы на сайте Microsoft Support (на английском). Наиболее часто встречающиеся ошибки VBA перечислены в этой таблице:
| 5 | Недопустимый вызов процедуры (Invalid procedure call) |
| 7 | Недостаточно памяти (Out of memory) |
| 9 | Индекс вне заданного диапазона (Subscript out of range)
Эта ошибка возникает при попытке обратиться к элементу массива за пределами заданного размера массива – например, если объявлен массив с индексами от 1 до 10, а мы пытаемся обратиться к элементу этого же массива с индексом 11. |
| 11 | Деление на ноль (Division by zero) |
| 13 | Несоответствие типа (Type mismatch)
Эта ошибка возникает при попытке присвоить переменной значение не соответствующего типа – например, объявлена переменная i типа Integer, и происходит попытка присвоить ей значение строкового типа. |
| 53 | Файл не найден (File not found)
Иногда возникает при попытке открыть не существующий файл. |
Перехват ошибок выполнения
Не все ошибки выполнения бывают вызваны недочётами в коде. Например, ошибки VBA не удастся избежать, если для работы макроса необходимо открыть файл с данными, а этого файла не существует. В таких случаях признаком профессионализма будет перехват ошибок и написание кода VBA, который будет выполняться при их возникновении. Таким образом, вместо неприятных сбоев будет происходить изящное завершение работы макроса.
Для того, чтобы помочь справиться с возникающими ошибками, VBA предоставляет разработчику операторы On Error и Resume. Эти операторы отслеживают ошибки и направляют выполнение макроса в специальный раздел кода VBA, в котором происходит обработка ошибки. После выполнения кода обработки ошибки, работа программы может быть продолжена с того места, где возникла ошибка, или макрос может быть остановлен полностью. Далее это показано на примере.
'Процедура Sub присваивает переменным Val1 и Val2 значения,
'хранящиеся в ячейках A1 и B1 рабочей книги Data.xlsx расположенной в каталоге C:Documents and Settings
Sub Set_Values(Val1 As Double, Val2 As Double)
Dim DataWorkbook As Workbook
On Error GoTo ErrorHandling
'Открываем рабочую книгу с данными
Set DataWorkbook = Workbooks.Open("C:Documents and SettingsData")
'Присваиваем переменным Val1 и Val2 данные из рабочей книги DataWorkbook
Val1 = Sheets("Лист1").Cells(1, 1)
Val2 = Sheets("Лист1").Cells(1, 2)
DataWorkbook.Close
Exit Sub
ErrorHandling:
'Если файл не найден, предлагаем пользователю разместить его в
'нужном месте и продолжить работу
MsgBox "Рабочая книга не найдена! " & _
"Пожалуйста добавьте книгу Data.xlsx в каталог C:Documents and Settings и нажмите OK."
Resume
End Sub
В этом коде производится попытка открыть файл Excel с именем Data. Если файл не найден, то пользователю будет предложено поместить этот файл в нужную папку. После того, как пользователь сделает это и нажмёт ОК, выполнение кода продолжится, и попытка открыть этот файл повторится. При желании вместо попытки открыть нужный файл, выполнение процедуры Sub может быть прервано в этом месте при помощи команды Exit Sub.
Логические ошибки
Логические ошибки (или баги) возникают в процессе выполнения кода VBA, но позволяют ему выполняться до самого завершения. Правда в результате могут выполняться не те действия, которые ожидалось, и может быть получен неверный результат. Такие ошибки обнаружить и исправить труднее всего, так как компилятор VBA их не распознаёт и не может указать на них так, как это происходит с ошибками компиляции и выполнения.
Например, при создании макроса в процедуре случайно были просуммированы не те переменные, которые требовалось просуммировать. Результат будет ошибочным, но макрос будет продолжать выполняться до завершения.
Редактор Excel VBA предоставляет набор инструментов отладки, которые помогут найти и исправить логические ошибки в коде VBA. В данной статье мы не будем рассматривать подробно эти инструменты. Любознательный пользователь может найти обзор инструментов отладки VBA на сайте Microsoft Help & Support (на английском).
Оцените качество статьи. Нам важно ваше мнение:
Обработка ошибок
Если вы когда-нибудь учились водить автомобиль, то наверняка вспомните, что при первой посадке на водительское сиденье все внимание было приковано к трем деталям: рулю, педалям и рычагу переключения передач. Происходящее вне автомобиля уходило на второй план, так как вначале нужно было стронуться с места. По мере практики навыки вождения улучшались и эти три детали постепенно уходили на задний план. Как ни странно, но руль и рычаг переключения передач всегда оказывались там, куда вы не смотря протягивали руки, а ноги сами находили педали. Теперь все внимание стало занимать происходящее на дороге. Иными словами, вы стали опытным водителем.
В программировании все абсолютно также. Начинающие программисты больше обращают внимание на первые попавшиеся на глаза операторы, функции и другие элементы языка, а сам алгоритм уходит на задний план. Если программа скомпилировалась без ошибок, то это уже большое счастье, хотя это еще не означает, что программа работает правильно. По мере практики мышление программиста меняется, он начинает обращать внимание на мелочи, на форматирование программы, использует более эффективные алгоритмы и в результате всего этого допускает меньше ошибок. Подводя итоги, можно сказать, что начинающий программист просто пишет программу, а опытный программист пытается найти оптимальный алгоритм и предусмотреть поведение программы в различных ситациях. Однако, от ошибок никто не застрахован, поэтому очень важно знать как быстро найти ошибку.
Типы ошибок
Существуют три типа ошибок в программе:
- синтаксические — это ошибки в имени оператора или подпрограммы, отсутствие закрывающей или открывающей кавычек и т. д., то есть ошибки в синтаксисе языка. Как правило, компилятор предупредит о наличии ошибки, а программа не будет выполняться совсем;
- логические — это ошибки в логике работы программы, которые можно выявить только по результатам работы программы. Как правило, компилятор не предупреждает о наличии ошибки, а программа будет выполняться, так как не содержит синтаксических ошибок. Такие ошибки достаточно трудно выявить;
- ошибки времени выполнения — это ошибки, которые возникают во время работы программы. В одних случаях ошибки времени выполнения являются следствием логических ошибок, а в других случаях причиной являются внешние события, например, нехватка оперативной памяти, отсутствие прав для записи в файл и др.
Инструкция On Error
Ошибки времени выполнения можно перехватывать внутри подпрограммы. Для этого используется инструкция On Error, которая имеет три формата:
On Error GoTo <Метка>— при возникновении ошибки управление передается инструкции, помеченной меткой<Метка>. Метка должна быть допустимым идентификатором, к которому предъявляются такие же требования как и к переменным. Внутри подпрограммы метка указывается в самом начале помечаемой строки и после метки ставится двоеточие. В качестве примера создадим функцию для деления двух целых чисел. Внутри функции предусмотрим обработку ошибки деления на0:
Function Деление(x As Integer, y As Integer) As Double
On Error GoTo ПриОшибке
Деление = x / y
Exit Function
ПриОшибке:
Деление = 0
End Function
Если при вызове функции во втором параметре передать значение 0, то управление будет передано в строку, помеченную с помощью метки ПриОшибке. Обратите внимание на то, что метка расположена после инструкции Exit Function. В этом случае код после инструкции Exit Function будет выполнен только в том случае, если возникнет ошибка;
On Error Resume Next— при возникновении ошибки управление передается следующей инструкции;On Error GoTo 0— отключает перехват ошибок.
Если внутри подпрограммы не предусмотрен перехват ошибки, то при возникновении ошибки работа программы прерывается и выводится стандартное окно с описанием и несколькими кнопками: Continue (продолжить), End (завершить выполнение программы), Debug (перейти в режим отладки) и Help (вывод справки).
Инструкция Resume
Инструкция Resume позволяет указать куда следует переходить после обработки ошибки. Инструкция имеет несколько форматов:
Resume [0]— управление передается инструкции, вызвавшей ошибку;Resume Next— управление передается инструкции, следующей за инструкцией, вызвавшей ошибку;Resume <Метка>— управление передается инструкции, помеченной меткой<Метка>.
Если инструкция Resume не указана, то выполняется только код внутри обработчика ошибки и производится выход из подпрограммы.
Получение информации об ошибке и генерация ошибки
Вся информация о последней ошибке доступна через объект Err. Объект содержит следующие свойства:
Number— код ошибки, например, код11для ошибки деления на0. Если ошибки не произошло, то свойство содержит значение0;Description— описание ошибки, например, строка"Division by zero"для ошибки деления на0. Пример вывода кода и описания ошибки:
Debug.Print Err.Number; Err.Description
Source— название текущего проекта;HelpFile— путь к файлу справки;HelpContext— идентификатор раздела в справочном файле;LastDLLError— системный код ошибки при работе с DLL.
Объект Err содержит следующие методы:
Clear()— очищает всю информацию о последней ошибке. Этот метод следует вызвать после успешной обработки ошибки. Информация об ошибке автоматически очищается при выходе из подпрограммы и ряде других случаев;Raise()— позволяет сгенерировать ошибку в программе. Формат метода:
Raise Number[, Source][, Description][, HelpFile][, HelpContext]
В параметре Number указывается код генерируемой ошибки (целое число от 0 до 65 535). Коды от 0 до 512 зарезервированы под системные ошибки, а остальные коды можно использовать под пользовательские ошибки. Чтобы сгенерировать ошибку с пользовательским кодом необходимо сложить код с константой vbObjectError. Остальные параметры являются необязательными и полностью аналогичны одноименным свойствам объекта Err. Пример генерации и обработки пользовательской ошибки:
Sub ГенерацияОшибки()
On Error GoTo ПриОшибке
Err.Raise vbObjectError + 513
Exit Sub
ПриОшибке:
Debug.Print Err.Number; Err.Description
' -2147220991 Automation error
End Sub
Способы поиска ошибок в программе
В предыдущих разделах мы научились обрабатывать ошибки времени выполнения. Однако, наибольшее количество времени программист затрачивает на другой тип ошибок — логические ошибки. В этом случае программа компилируется без ошибок, но результат выполнения программы не соответствует ожидаемому результату. Ситуация еще более осложняется, когда неверный результат проявляется лишь периодически, а не постоянно. Инсценировать такую же ситуацию, чтобы получить этот же неверный результат, бывает крайне сложно и занимает очень много времени. В этом разделе мы рассмотрим лишь «дедовские» (но по прежнему актуальные) способы поиска ошибок, а современные способы отладки приложений, доступные в VBA, изучим в следующем разделе.
Первое, на что следует обратить внимание, — на объявления переменных. Например, рассмотрим простой пример:
Как вы думаете, какое значение отобразится в окне Immediate после выполнения этого кода? Думаете, что число 10? Не факт! Вот тут-то и кроется проблема не видная на первый взгляд. В первой инструкции присваивается значение переменной x, имя которой набрано на английской раскладке клавиатуры, а вот во второй инструкции выводится значение переменной x, имя которой набрано на русской раскладке клавиатуры. В результате значение присваивается одной переменной, а выводится значение другой переменной. Такие ситуации очень часто встречаются в программах на языке VBA, так как объявлять переменную не обязательно. Чтобы избежать такой ситуации следует обязательно объявлять переменные явным образом. Контроль за соблюдением этого правила можно возложить на компилятор, добавив в начале модуля следующую инструкцию:
При наличии инструкции компилятор производит проверку объявления всех переменных. Если переменная не была объявлена явным образом, то компилятор выведет сообщение об ошибке и выполнение программы будет остановлено. Таким образом, код должен выглядеть следующим образом:
Option Explicit
...
Dim x As Integer
x = 10
Debug.Print x ' 10
Далее следует обратить внимание на форматирование кода. Начинающие программисты обычно не обращают на это никакого внимания, считая этот процесс лишним. А на самом деле зря! Компилятору абсолютно все равно, разместите вы все инструкции на одной строке или выполните форматирование кода. Однако, при поиске ошибок форматирование кода позволит найти ошибку гораздо быстрее.
Перед всеми инструкциями внутри блока должно быть расположено одинаковое количество пробелов. Обычно используют три или четыре пробела. От применения символов табуляции лучше отказаться. Если все же используете, то не следует в одном файле совмещать и пробелы и табуляцию. Для вложенных блоков количество пробелов умножают на уровень вложенности. Если для блока первого уровня вложенности использовалось три пробела, то для блока второго уровня вложенности должно использоваться шесть пробелов, для третьего уровня — девять пробелов и т. д. Пример форматирования вложенных блоков приведен в листинге 11.1.
Dim Массив As Variant, i As Integer, j As Integer
Массив = Array(Array(0, 1), Array(2, 3), Array(4, 5))
For i = 0 To 2
For j = 0 To 1
Debug.Print Массив(i)(j)
Next
Next
Длина одной строки не должна содержать более 80 символов. Если количество символов больше, то следует выполнить переход на новую строку. При этом продолжение смещается относительно основной инструкции на величину отступа или выравнивается по какому-либо элементу. Иначе приходится пользоваться горизонтальной полосой прокрутки, а это очень неудобно при поиске ошибок.
Если программа слишком большая, то следует задуматься о разделении программы на отдельные подпрограммы или классы, которые выполняют логически законченные действия. Помните, что отлаживать отдельную подпрограмму гораздо легче, чем «спагетти»-код. Причем прежде чем вставить подпрограмму (или класс) в основную программу ее следует протестировать в отдельном проекте, передавая подпрограмме различные значения и проверяя результат ее выполнения.
Обратите внимание на то, что форматирование кода должно выполняться при написании кода, а не во время поиска ошибок. Этим вы сократите время поиска ошибки и скорее всего заметите ошибку еще на этапе написания. Если все же ошибка возникла, то вначале следует инсценировать ситуацию, при которой ошибка проявляется. После этого можно начать поиск ошибки.
Причиной периодических ошибок чаще всего являются внешние данные. Например, если числа получаются от пользователя, а затем производится деление чисел, то вполне возможна ситуация, при которой пользователь введет число 0. Деление на ноль приведет к ошибке. Следовательно, все данные, которые поступают от пользователей, должны проверяться на соответствие допустимым значениям. Если данные не соответствуют, то нужно вывести сообщение об ошибке, а затем повторно запросить новое число или прервать выполнение всей программы. Кроме того, нужно обработать возможность того, что пользователь может ввести вовсе не число, а строку.
Метод Print() объекта Debug удобно использовать для вывода промежуточных значений. В этом случае значения переменных вначале выводятся в самом начале программы и производится проверка соответствия значений. Если значения соответствуют, то инструкция с методом Print() перемещается на следующую строку программы и опять производится проверка и т. д. Если значения не совпали, то ошибка возникает в инструкции, расположенной перед инструкцией с методом Print(). Если это пользовательская подпрограмма, то проверку значений производят внутри подпрограммы, каждый раз перемещая инструкцию с выводом значений. На одном из этих многочисленных этапов ошибка обычно обнаруживается. В больших программах можно логически догадаться о примерном расположении инструкции с ошибкой и начать поиск ошибки оттуда, а не с самого начала программы.
Инструкции для вывода промежуточных значений можно расставить уже при написании программы, не дожидаясь возникновения ошибки. В этом случае в начале программы объявляется константа с помощью инструкции #Const, а внутри программы производится проверка значения константы:
Проверить значение константы позволяет следующая конструкция:
#If MY_DEBUG Then
' Здесь размещаем инструкции вывода значений
#End If
Таким образом, меняя значение константы MY_DEBUG с 1 на 0, можно отлючать вывод всех промежуточных значений.
Сделать поиск ошибок более эффективным позволяет отладчик, встроенный в редактор VBA. С его помощью можно выполнять программу по шагам, при этом контролируя значения переменных на каждом шагу. Отладчик позволяет также проверить, соответствует ли порядок выполнения инструкций разработанному ранее алгоритму.
Прежде чем начать отладку необходимо пометить строки внутри программы с помощью точек останова. Для добавления точки останова делаем строку активной, а затем из меню Debug выбираем пункт Toggle Breakpoint. Слева от строки появится кружок, обозначающий точку останова. Добавить точку останова можно еще быстрее. Для этого достаточно щелкнуть слева от строки левой кнопкой мыши. Повторный щелчок позволяет удалить точку останова. Кроме того, для добавления или удаления точки отстанова можно воспользоваться клавишей <F9>. Чтобы удалить все точки останова следует из меню View выбрать пункт Clear All Breakpoints.
Когда точки останова расставлены можно начать отладку. Для этого запускаем программу на выполнение обычным способом. При достижении точки останова выполнение программы прерывается и отладчик ожидает дальнейших действий программиста. Инструкция, которая будет выполняться на следующем шаге, помечается желтой стрелкой слева от строки.
В режиме прерывания можно посмотреть значения различных переменных в окне Locals. Если окно не отображается, то отобразить его можно выбрав в меню View пункт Locals Window. Посмотреть значение переменной можно также если навести указатель мыши на переменную. Значение переменной отобразится во всплывающей подсказке.
При отладке можно контролировать значения отдельных переменных, а не всех сразу. Для этого следует выделить название переменной и из меню Debug выбрать пункт Add Watch. Можно также выделить название переменной и из контектного меню выбрать пункт Add Watch. В открывшемся окне устанавливаем флажок Watch Expression и нажимаем кнопку OK. Значение переменной будет отображаться в окне Watches. Чтобы отобразить окно Watches из меню View выбираем пункт Watch Window. Чтобы отменить отслеживание нужно выделить строку в окне Watches и нажать клавишу <Delete>.
Для пошагового выполнения программы предназначены следующие пункты в меню Debug или соответствующие кнопки на панели инструментов Debug (View | Toolbars | Debug):
- Step Into (клавиша <F8>) — выполняет переход к следующей инструкции;
- Step Over — выполняет одну инструкцию. Если в этой инструкции производится вызов подпрограммы, то подпрограмма выполняется за один шаг и отладчик переходит в режим ожидания после выхода из подпрограммы;
- Step Out — при заходе в подпрограмму этот пункт позволяет выполнить подпрограмму за один шаг и выйти из нее. Отладчик переходит в режим прерывания после выхода из подпрограммы;
- Run To Cursor — выполняет переход к инструкции, в которой расположен курсор.
Если необходимо посмотреть последовательность вызова подпрограмм, то следует открыть окно Call Stack, выбрав в меню View пункт Call Stack.
Подача звукового сигнала
При возникновении ошибки или при неправильном вводе данных имеет смысл привлечь внимание пользователя звуковым сигналом. Сгенерировать звуковой сигнал позволяет инструкция Beep. Пример:
Dim Результат
Beep
Результат = InputBox("Необходимо ввести значение")

Статьи по Visual Basic for Applications (VBA)
Отказ макроса или надстройки от выполнения своих функций имеет ряд причин. Рассмотрим наиболее распространенные из них.
Операционная система
Вплоть до Office 2016 пакет приложений Microsoft Office выпускается в различных версиях, для Windows и для Mac OS. Встроенный в приложения Office язык программирования при этом использует отличающиеся друг от друга библиотеки операционной системы. В связи с этим макрос/надстройка, написанная для работы в приложениях под Windows, может не работать, либо работать некорректно в MacOS. Проверьте операционную систему, для которой разрабатывался макрос/надстройка.
Разработчик пакета офисных приложений
Кроме Microsoft Office, пользователи достаточно часто используют альтернативные пакеты офисных приложений, такие как OpenOffice или LibreOffice. Приложения этих пакетов также имеют встроенные языки программирования, но эти языки отличаются друг от друга. Макросы или надстройки, написанные в Visual Basic for Application в приложениях пакета Microsoft Office, не будут работать в приложениях OpenOffice или LibreOffice. Уточните, для какого пакета офисных программ разработан макрос/надстройка.
Наличие компонента VBA
Для того, чтобы можно было запустить макрос или надстройку в каком-либо приложении пакета Office, необходимо, чтобы с этим пакетом был установлен компонент VBA – встроенный язык программирования Visual Basic for Application. В некоторых версиях Office этот пакет может устанавливаться отдельно. Проверьте, установлен ли этот компонент на компьютере. Нажмите сочетание клавиш Alt+F11, если после этого появляется окно редактора Visual Basic, то компонент установлен. В случае, если компонент отсутствует, его необходимо установить.
Версия Microsoft Office
Microsoft Office 2003 использует надстройки с расширением .xla (для Excel), .dot (для Word) и так далее. В более поздних версиях расширения надстроек изменились: .xlam (для Excel), .dotm (для Word). При установке надстроек старого формата в приложения Office 2007 и выше никаких проблем не происходит, а вот при попытке установить надстройку нового формата в приложения пакета Office 2003, возникает сообщение о том, что надстройки не обнаружены. Убедитесь в том, что используемая надстройка предназначена именно для той версии Office, в которой Вы работаете.
Активация Microsoft Office
Убедитесь в том, что Microsoft Office не требует активации. Проведите активацию, чтобы избежать каких-либо ограничений при использовании приложений.
Снятие блокировки файла
Файл, полученный с другого компьютера или из сети интернет может быть заблокирован. Чтобы разблокировать такой файл, необходимо кликнуть на нем правой кнопкой мыши и на вкладке «Общие» нажать кнопку «Разблокировать».

Система безопасности
Если все вышеизложенное не ответило на вопрос «почему не работает макрос?», то, скорее всего, дело в настройках системы безопасности. Перейдите на страницу https://macros-vba.ru/knigi/vba/nastrojki-sistemy-bezopasnosti и проделайте то, что написано в разделах «Надежные расположения» и «Настройка доступа к объектной модели VBA».
Используемые библиотеки
Еще одна ситуация при которой не работает макрос сопровождается появлением сообщения Can’t find project or library при этом тот же самый макрос может без нареканий работать на другом компьютере. В разных версиях приложений, в которые встроен VBA могут использоваться разные библиотеки, в связи с чем могут возникать подобные ошибки. Ошибку можно устранить, если в окне, которое следует за сообщением об ошибке снять флажки, установленные в пунктах, содержащих слово MISSING.

Это окно также можно вызвать и самостоятельно, если в редакторе VB выбрать пункт меню Tools/References.
Кроме этого не все библиотеки подключаются автоматически. Если на компьютере разработчика макроса или надстройки какая-то библиотека была подключена вручную, затем макрос или надстройка были перенесены на другой компьютер, где эта библиотека не подключена, возникает такая-же ошибка.
Другие материалы по теме:
Последнее обновление Ноя 12, 2021
Некоторые пользователи, похоже, получают ошибку VBA 400 при попытке запустить свой макрос в Excel. Дальнейших указаний нет, только окошко с кнопкой ОК.
В любом случае, не волнуйтесь, у нас есть для вас несколько простых решений. Мы предлагаем вам выполнить шаги, упомянутые в этой статье, в указанном порядке. Надеюсь, они помогут вам решить вашу проблему.
Как исправить ошибку 400 в Excel?
1 Переместите ваши макросы в новый модуль

- Чтобы создать новый модуль, перейдите в меню «Инструменты».
- Щелкните Макрос – редактор Visual Basic.
- В VBA щелкните ” Модуль” в меню “Вставка”.
- Вставьте код VBA, который хотите использовать.
- В меню «Файл» выберите «Сохранить глобально».
- Обязательно удалите старый модуль.
2 Включите доверенный доступ к VBA

- Перейдите на вкладку «Разработчик» (если она недоступна, нажмите «Файл» > «Параметры» > «Настроить ленту»> установите флажок «Разработчик» ).
- В группе Код – перейдите на вкладку Разработчик.
- Щелкните Безопасность макросов.
- Выберите «Параметры макроса разработчика» – выберите «Надежный доступ к проекту VBA».
3 Проверьте свой код

Обязательно всегда проверяйте свой код на наличие ошибок. Кроме того, также необходима проверка на наличие повреждений макросов.
Вот об этом. Мы надеемся, что это подтвержденное решение исправит вашу ошибку VBA 400. Если у вас есть другие подтвержденные предложения, сообщите нам об этом в комментариях ниже.
Источник записи: windowsreport.com
В этой статье мы обсудим методы исправления ошибки VBA 400 в Excel. Ошибка 400 в Excel обычно возникает при запуске макроса Microsoft Visual Basic для приложений (VBA). Это вызывает сбой макроса или сбой при запуске и возвращает сообщение об ошибке 400. Причины такой ошибки могут быть разными; давайте обсудим их.

Что вызывает ошибку VBA 400 в Excel?
Вот причины, из-за которых возникает ошибка 400 при запуске макроса в Excel:
- Неправильная установка программного обеспечения Office.
- В коде VBA есть ошибка.
- Недопустимое значение аргумента.
- Запущенный макрос поврежден.
- Файлы, связанные с Excel, заражены каким-либо вредоносным ПО.
- Ошибка чтения / записи из файла.
- Неверные записи в реестре.
Если вы столкнулись с ошибкой 400 в Excel, вы можете использовать перечисленные ниже решения для ее устранения.
Вот способы исправить ошибку 400, возникшую при запуске макроса в Excel:
- Переместите макросы в новый модуль.
- Включите доверенный доступ к VBA.
- Просмотрите свой код VBA.
- Восстановите Microsoft Excel.
- Удалите, а затем повторно установите Excel.
- Некоторые другие методы, такие как сканирование на наличие вредоносных программ и т. Д.
Давайте подробно обсудим эти методы.
1]Переместить макросы в новый модуль
Перенос макросов в новый модуль может решить проблему в случае внешней ошибки. Для этого вы можете использовать следующие шаги:
Перейдите на вкладку «Разработчики» и выберите «Визуальный редактор». Если вы не видите вкладку «Разработчики» на главной ленте в Excel, перейдите в «Файл»> «Параметры» и на вкладке «Настройка лент» установите флажок «Разработчики» в разделе «Основные вкладки».
Теперь в окне Microsoft Visual Basic для приложений щелкните меню «Вставка» и выберите параметр «Модуль».
После этого вставьте код макроса в этот новый модуль и сохраните его, используя специальную опцию в меню «Файл».
Кроме того, вам нужно удалить старый модуль, щелкнув его правой кнопкой мыши и используя Удалять вариант.
Наконец, щелкните Файл> Закрыть и вернуться в Microsoft Excel и посмотрите, устранена ли ошибка 400 в Excel.
2]Включить надежный доступ к VBA
Вы можете включить доверенный доступ к VBA и посмотреть, исчезла ли проблема. Вот шаги, чтобы включить доверенный доступ к VBA:
- Перейдите на вкладку «Разработчики» и нажмите «Безопасность макросов».
- В окне центра управления безопасностью включите параметр Надежный доступ к объектной модели проекта VBA.
- Нажмите кнопку ОК.
3]Проверьте свой код
Ошибка в коде VBA может вызвать ошибку 400 в Excel. Итак, вам необходимо тщательно просмотреть код макроса и исправить ошибку в коде, если таковая имеется. Также проверьте макросы на наличие повреждений.
4]Восстановить Microsoft Excel
Если ничего из вышеперечисленного не работает, проблема может быть в приложении Excel. Возможно, приложение установлено неправильно или что-то нужно исправить. Итак, восстановите Microsoft Excel, используя следующие шаги:
- Запустите приложение «Настройки» и выберите «Приложения»> «Приложения и функции».
- Справа найдите и щелкните Программа Office 365 / Microsoft 365.
- Нажмите на кнопку «Изменить», а затем выберите вариант «Онлайн-ремонт» или «Быстрое восстановление».
- Нажмите кнопку «Восстановить», чтобы восстановить Excel и другие приложения Office.
5]Удалите, а затем повторно установите Excel.
Вы также можете попробовать удалить, а затем переустановить программное обеспечение Office и Excel, чтобы начать заново. Посмотрите, устраняет ли это ошибку.
6]Некоторые другие методы
Кроме того, некоторые другие решения также могут работать, например:
- Вы можете попробовать запустить сканирование SFC, чтобы проверить и восстановить поврежденные системные файлы.
- Некоторые вредоносные программы также могут вызывать эту ошибку. Итак, проверяйте и удаляйте вредоносные программы и подозрительные приложения с помощью Microsoft Defender или сторонней антивирусной или антивредоносной программы.
- Попробуйте удалить поврежденные данные кеша и системные ненужные файлы.
Надеюсь, что приведенные выше решения помогут!
Теперь прочтите: Как исправить ошибку выполнения 1004 в Excel
.