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

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

В практике разработчика 1С часто возникает ситуация: необходимо запустить обработку, которая в цикле создает или проводит пакет документов. При этом, если документ не проводится из-за какой-либо проверки (например, не хватило остатков на складе или не заполнено обязательное поле), платформа выводит стандартное сообщение через команду Сообщить(). Однако, если вызов метода Записать(РежимЗаписиДокумента.Проведение) обернут в блок Попытка — Исключение, сообщения часто «пропадают» для алгоритма обработки, и мы получаем лишь сам факт ошибки без конкретики. В качестве основы для такой выборки и пакетных действий подойдёт интерактивный обработчик объектов для выполнения произвольных алгоритмов.

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

Разберем основной механизм: Функция ПолучитьСообщенияПользователю

Начиная с версии платформы 8.2, разработчикам доступен мощный инструмент — функция ПолучитьСообщенияПользователю(). Рассмотрим ее работу подробнее. Главная особенность заключается в том, что все сообщения, которые генерируются системой или кодом во время серверного вызова, не выводятся мгновенно. Они накапливаются в специальном стеке (буфере) сообщений сеанса.

Проанализируем ситуацию: когда выполнение кода заходит в блок Исключение, транзакция отменяется, но сообщения, которые система успела «наговорить» до момента отмены, никуда не исчезают. Они остаются в стеке до тех пор, пока управление не вернется на сторону клиента или пока мы не очистим этот стек принудительно.

Функция ПолучитьСообщенияПользователю() принимает один необязательный параметр — УдалятьИзСтека (тип Булево). Рассмотрим два варианта использования:

  1. Перехват с очисткой: Если вызвать ПолучитьСообщенияПользователю(Истина), система вернет массив объектов и полностью очистит буфер. В этом случае пользователь вообще не увидит этих сообщений в стандартном окне — ответственность за их отображение (или запись в файл) ложится на ваш код.
  2. Чтение без очистки: Если передать Ложь, вы получите список ошибок, но в конце выполнения серверной процедуры платформа все равно покажет их пользователю в привычном виде.

Пример реализации перехвата сообщений в блоке Исключение

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


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

Анализируем структуру объекта СообщениеПользователю

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

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

Особенности работы в фоновых заданиях

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

Если вы запускаете фоновое задание программно через ФоновыеЗадания.Выполнить(), вы можете в родительском сеансе периодически опрашивать объект задания. Для этого у объекта ФоновоеЗадание существует метод ПолучитьСообщения().

Посмотрим на пример кода для мониторинга фонового задания:


Задание = ФоновыеЗадания.Выполнить("МойОбщийМодуль.ПровестиДокументы", Параметры);
// Ожидаем завершения или проверяем состояние
Пока Задание.Состояние = СостояниеФоновогоЗадания.Активно Цикл
    МассивНовыхСообщений = Задание.ПолучитьСообщения();
    Для Каждого Сообщение Из МассивНовыхСообщений Цикл
        // Обработка сообщений в реальном времени
        ОбщегоНазначенияКлиентСервер.СообщитьПользователю(Сообщение.Текст);
    КонецЦикла;
    // Пауза, чтобы не нагружать систему
    // ...
КонецЦикла;

Альтернативные подходы: модификация типовых механизмов

В некоторых старых конфигурациях (например, УПП или старые редакции УТ) разработчики часто используют собственные функции-обертки для вывода сообщений, такие как ОбщегоНазначения.СообщитьОбОшибке(). В этом случае, если стандартный механизм ПолучитьСообщенияПользователю() по каким-то причинам не подходит, можно рассмотреть вариант доработки этой общей процедуры.

Выясним причину, почему это может быть полезно: иногда требуется хранить историю всех сообщений в специальном регистре сведений или текстовом файле на сервере для последующего аудита. В таком случае в общую процедуру вывода сообщений добавляется условие: если установлен определенный «флаг логирования» (например, через глобальную переменную или параметр сеанса), то текст сообщения дублируется в журнал регистрации или файл.

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

Подведем итоги

Для эффективного получения сообщений при ошибках проведения в 1С достаточно следовать простому алгоритму:

  1. Использовать конструкцию Попытка — Исключение при вызове метода проведения.
  2. В блоке Исключение вызывать функцию ПолучитьСообщенияПользователю(Истина).
  3. Обходить полученный массив циклом и обрабатывать свойство Текст каждого объекта сообщения.
  4. Для фоновых заданий использовать специализированный метод объекта ФоновоеЗадание.

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

← На главную