Разберем типичную ситуацию: при программной записи или проведении документа в коде используется конструкция Попытка ... Исключение. Если в подписке на событие или модуле объекта срабатывает условие проверки с установкой флага Отказ = Истина и выводом сообщения через Сообщить(), вызывающий блок перехватывает лишь системное платформенное сообщение вида «Не удалось провести документ» или «Ошибка при вызове метода контекста (Записать)». При этом текст из Сообщить() не попадает в функцию ОписаниеОшибки().
Выясним причину такого поведения и рассмотрим способы передачи детального текста ошибки выше по стеку вызовов.
Проанализируем механику работы платформы 1С. Когда в обработчиках событий (например, ОбработкаПроведения или ПередЗаписью) флаг Отказ устанавливается в значение Истина, платформа отменяет транзакцию и выбрасывает стандартное системное исключение записи. Вызовы методов Сообщить() или объектов СообщениеПользователю не создают программного исключения — они всего лишь помещают строки в буфер сообщений текущего сеанса пользователя.
Чтобы прервать выполнение и передать собственный текст ошибки непосредственно в стек вызовов, используем оператор ВызватьИсключение с выражением строкового типа. Такой оператор можно вызывать в произвольном месте кода, в том числе вне блоков перехвата ошибок.
Посмотрим на пример генерации исключения внутри обработчика или подписки на событие:
Если НарушенаДатаЗапрета Тогда
ТекстСообщения = "Ошибка при проведении: нарушена дата запрета на проведение документа по причине...";
ВызватьИсключение ТекстСообщения;
КонецЕсли;
Разберем различия в формах вызова этого оператора:
ВызватьИсключение(ТекстСообщения);.Исключение ... КонецПопытки для повторного проброса ранее пойманной ошибки вверх по стеку.Теперь посмотрим, как перехватить эту ошибку в вызывающем коде:
Попытка
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
Исключение
// Получаем переданный текст ошибки
ТекстОшибки = ОписаниеОшибки();
// Для более точного анализа в современных версиях платформы:
ИнформацияОбОшибке = ИнформацияОбОшибке();
ТекстОшибкиКраткий = КраткоеПредставлениеОшибки(ИнформацияОбОшибке);
КонецПопытки;
В типовых конфигурациях для вывода ошибок валидации часто используется связка Отказ = Истина; и объект СообщениеПользователю. Это позволяет накопить сразу несколько ошибок (например, список всех незаполненных реквизитов), тогда как ВызватьИсключение немедленно прерывает алгоритм на первой же строке.
Если документ отменяет проведение через Отказ = Истина, в вызывающем коде можно извлечь все накопленные сообщения через метод ПолучитьСообщенияПользователю():
Попытка
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
Исключение
// Извлекаем все сообщения, сформированные в процессе проведения
МассивСообщений = ПолучитьСообщенияПользователю(Истина);
ТекстыОшибок = Новый Массив;
Для Каждого Сообщение Из МассивСообщений Цикл
ТекстыОшибок.Добавить(Сообщение.Текст);
КонецЦикла;
ИтоговыйТекст = СтрСоединить(ТекстыОшибок, Символы.ПС);
Если ПустаяСтрока(ИтоговыйТекст) Тогда
ИтоговыйТекст = КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
КонецЕсли;
КонецПопытки;
ВызватьИсключение останавливает выполнение текущего метода мгновенно. Если требуется проверить несколько условий и показать пользователю полный перечень замечаний, следует использовать СообщениеПользователю и флаг Отказ.ИнформацияОбОшибке() и методы ПодробноеПредставлениеОшибки() или КраткоеПредставлениеОшибки(), что позволяет избавиться от системных оберток платформы.