Как открыть печатную форму или табличный документ из процедуры ОбработкаПроведения в 1С

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

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

Почему нельзя открыть печатную форму прямо из ОбработкаПроведения

Процедура ОбработкаПроведения исполняется на сервере строго внутри явной транзакции записи базы данных. В этот момент платформой накладываются следующие архитектурные ограничения:

  1. Отсутствие контекста формы и интерфейса на сервере. На сервере недоступны интерактивные методы объектов, такие как метод Показать() для табличных документов или открытие форм. Серверный код не имеет доступа к экрану пользователя.
  2. Откат транзакции. Когда в процедуре ОбработкаПроведения параметр Отказ устанавливается в значение Истина, платформа отменяет транзакцию проведения. Все изменения и подготовленные данные внутри контекста транзакции откатываются.
  3. Программное и фоновое проведение. Документы могут проводиться не только интерактивно из формы, но и программно — из групповых обработок, фоновых заданий или интеграционных Web-сервисов. В этих сценариях форма документа не создается вовсе, и попытка показать форму вызовет критическую ошибку платформы.

Решение 1. Вынос проверки на клиент в событие ПередЗаписью формы

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

Разберем по шагам реализацию этого подхода:

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

Проанализируем пример кода модуля формы:


&НаСервере
Функция ПроверитьПревышениеЛимитаНаСервере()
    // Проводим проверку бизнес-логики
    Если ЛимитПревышен() Тогда
        Возврат СформироватьПроверочнуюТаблицу();
    КонецЕсли;
    
    Возврат Неопределено;
КонецФункции

&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
    // Проверяем, что документ записывается в режиме проведения
    Если ПараметрыЗаписи.РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
        
        ТабДок = ПроверитьПревышениеЛимитаНаСервере();
        
        Если ТабДок <> Неопределено Тогда
            // Выводим проверочную таблицу пользователю
            ТабДок.Показать("Проверка лимитов");
            
            // Отменяем запись и проведение документа
            Отказ = Истина;
        КонецЕсли;
        
    КонецЕсли;
КонецПроцедуры

Решение 2. Использование структуры ДополнительныеСвойства для передачи данных

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

  1. В модуле объекта в событии ОбработкаПроведения выполняем проверку. Если условия нарушены, устанавливаем Отказ = Истина и записываем сформированный табличный документ в ЭтотОбъект.ДополнительныеСвойства.
  2. В форме документа считываем сохраненные свойства и выводим печатную форму на клиенте.

Посмотрим на пример заполнения свойства в модуле объекта:


Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    
    Если ЛимитПревышен() Тогда
        
        ТабДок = СформироватьТаблицуНарушений();
        ЭтотОбъект.ДополнительныеСвойства.Вставить("ПроверочнаяТаблица", ТабДок);
        
        Отказ = Истина;
        Возврат;
        
    КонецЕсли;
    
КонецПроцедуры

Решение 3. Использование события ОбработкаПроверкиЗаполнения

Для вывода сообщений об ошибках без открытия отдельных табличных документов рекомендуется использовать встроенный механизм платформы — процедуру ОбработкаПроверкиЗаполнения в модуле объекта. Этот метод выполняется до открытия транзакции проведения и позволяет корректно передать точные сообщения пользователю с помощью объекта СообщениеПользователю.

Выясним преимущества данного подхода: проверка срабатывает до открытия транзакции базы данных, что существенно экономит ресурсы СУБД и исключает блокировки таблиц при возникновении ошибок проведения.

← На главную