При разработке сложных алгоритмов во встроенном языке 1С:Предприятие 7.7 часто возникает необходимость прервать выполнение кода и передать управление в блок Исключение. Это может потребоваться при невыполнении критически важных бизнес-условий, например, если на складе не хватает остатка товара, не заполнена обязательная аналитика или у пользователя недостаточно прав для проведения операции.
В современных версиях платформы 1С 8.х для этого существует удобный оператор ВызватьИсключение, который принимает в качестве параметра строковое описание ошибки. К сожалению, в 1С 7.7 возможности этого оператора крайне ограничены, а его использование напрямую часто приводит к синтаксическим ошибкам. Выясним, почему стандартные механизмы работают именно так, и разберем несколько эффективных способов решения этой проблемы — как на чистом встроенном языке, так и с использованием внешних компонент.
Для начала проанализируем, почему мы не можем использовать стандартные конструкции встроенного языка так же легко, как в 1С 8.х. В платформе 1С 7.7 оператор ВызватьИсключение (или его англоязычный аналог Raise) имеет два ключевых ограничения:
ВызватьИсключение "Моя ошибка"; вызовет ошибку компиляции "Неопознанный оператор".Исключение ... КонецПопытки. Его единственная задача в версии 7.7 — повторно сгенерировать (пробросить) уже случившуюся системную ошибку на более высокий уровень выполнения (во внешнюю попытку). Если написать его в основном теле блока Попытка, программа также выдаст синтаксическую ошибку.Именно поэтому разработчики часто прибегают к искусственному провоцированию системных сбоев (например, делению на ноль 1/0). Но в таком случае встроенная функция ОписаниеОшибки() возвращает некрасивое техническое сообщение "Деление на 0", которое пугает пользователей и не несет полезной информации о сути произошедшего сбоя. Ниже мы разберем, как обойти эти ограничения.
Рассмотрим первый метод, который не требует подключения никаких внешних библиотек и работает абсолютно на любой конфигурации "из коробки". Суть метода заключается в использовании глобальной или локальной переменной-флага, которая будет хранить наш кастомный текст ошибки перед тем, как мы принудительно вызовем системный сбой.
Разберем этот алгоритм по шагам на практическом примере:
ТекстОшибки = "";
Попытка
// ... какой-то сложный код ...
Если Число(ОстатокТовара) < 0 Тогда
ТекстОшибки = "Ошибка проведения: Недостаточно товара на складе!";
// Намеренно провоцируем ошибку выполнения (деление на ноль)
Знаменатель = 0;
Сбой = 1 / Знаменатель;
КонецЕсли;
// ... продолжение выполнения ...
Исключение
// Проверяем, была ли ошибка вызвана искусственно
Если ПустаяСтрока(ТекстОшибки) = 0 Тогда
Сообщить(ТекстОшибки, "!");
Else
// Если произошел реальный системный сбой (например, ошибка базы данных)
Сообщить("Критическая ошибка системы: " + ОписаниеОшибки(), "!!");
КонецЕсли;
КонецПопытки;
Преимущества метода: Полная автономность решения, отсутствие зависимости от внешних компонент и настроек операционной системы.
Недостатки: Код выглядит перегруженным из-за искусственных вычислений. Кроме того, если в конфигураторе включена опция "Останавливаться по ошибке", отладчик будет постоянно прерывать выполнение программы на строке деления на ноль, что сильно затрудняет процесс разработки.
Посмотрим на более изящный способ, который позволяет генерировать полноценные исключения с красивым текстом без необходимости деления на ноль. Мы можем задействовать штатный системный ActiveX-объект Windows — MSScriptControl.ScriptControl. С его помощью мы выполним короткий скрипт на языке VBScript, который выбросит COM-исключение. Платформа 1С перехватит его в блоке Исключение, а функция ОписаниеОшибки() вернет именно наш текст.
Проанализируем пример реализации:
Попытка
// ... выполняем операции ...
Если Константа.РазрешитьПродажуВМинус.Получить() = 0 Тогда
// Создаем объект скрипта
Скрипт = СоздатьОбъект("MSScriptControl.ScriptControl");
Скрипт.Language = "VBScript";
// Вызываем ошибку выполнения в VBScript (код 513) с нашим сообщением
Скрипт.ExecuteStatement("Err.Raise 513, ""1C_Script"", ""Внимание! Запрещено проведение в минус.""");
КонецЕсли;
// ... выполняем операции ...
Исключение
// ОписаниеОшибки() вернет строку с нашим кастомным сообщением
Сообщить(ОписаниеОшибки(), "!");
КонецПопытки;
Преимущества метода: Чистый синтаксис в блоке обработки ошибок. Нам больше не нужно заводить дополнительные переменные для отслеживания источника сбоя, так как текст ошибки напрямую передается в системную функцию ОписаниеОшибки().
Недостатки: Требуется наличие зарегистрированного в операционной системе компонента MSScriptControl. В современных 64-битных версиях Windows (начиная с Windows 10/11 и Windows Server 2016) данный компонент может отсутствовать или требовать ручной регистрации через утилиту regsvr32.
Если в вашей базе данных установлена и активно используется внешняя компонента 1С++ (которая является стандартом де-факто для расширения возможностей 1С 7.7), мы можем задействовать мощный объектно-ориентированный механизм обработки исключений через класс ВыполняемыйМодуль.
Этот класс предоставляет метод ВыброситьИскл(ОбъектИскл, ТекстИскл). Данный метод позволяет передавать "наверх" не просто текстовую строку, а полноценный объект 1С (например, СписокЗначений, ТаблицуЗначений или экземпляр другого класса 1С++), который затем можно извлечь и проанализировать в блоке перехвата.
Рассмотрим подробнее пример практического применения:
Процедура ВыполнитьПроведение()
Модуль = СоздатьОбъект("ВыполняемыйМодуль");
Попытка
Сообщить("Начало проверки транзакции...");
Если Док.Выбран() = 0 Тогда
// Формируем объект ошибки для передачи
ПараметрыОшибки = СоздатьОбъект("СписокЗначений");
ПараметрыОшибки.ДобавитьЗначение(Док, "Документ");
ПараметрыОшибки.ДобавитьЗначение("Критично", "Статус");
// Выбрасываем исключение
Модуль.ВыброситьИскл(ПараметрыОшибки, "Попытка проведения незаписанного документа!");
КонецЕсли;
// ... код проведения ...
Исключение
// Получаем системный текст ошибки
Сообщить("Ошибка: " + ОписаниеОшибки(), "!");
// Получаем переданный нами объект ошибки средствами 1С++
ДанныеИсключения = Модуль.ПолучитьИсключение();
Если ПустоеЗначение(ДанныеИсключения) = 0 Тогда
Если ТипЗначенияСтр(ДанныеИсключения) = "СписокЗначений" Тогда
СтатусОшибки = ДанныеИсключения.Получить("Статус");
Сообщить("Уровень критичности ошибки: " + СтатусОшибки);
КонецЕсли;
КонецЕсли;
КонецПопытки;
КонецПроцедуры
Преимущества метода: Это наиболее продвинутый и профессиональный способ работы с ошибками в 1С 7.7. Он позволяет строить гибкую архитектуру логирования с передачей подробного контекста ошибки (стек вызовов, связанные объекты, коды ошибок) без захламления глобальной области видимости.
Недостатки: Требуется обязательное подключение и инициализация внешней компоненты 1С++ в системе.
Выяснив основные технические варианты реализации, важно остановиться на правилах хорошего тона при проектировании архитектуры конфигурации 1С 7.7:
Возврат.