Как получить доступ к реквизиту формы из модуля менеджера при печати в 1С?

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

Разработка в среде управляемого приложения 1С часто сталкивает нас с архитектурными ограничениями разделения контекста выполнения кода. Типичная задача: на управляемой форме документа есть реквизит (например, флажок или поле ввода числа), который не связан с реквизитами самого объекта (не записывается в базу данных). Нам требуется, чтобы в зависимости от состояния этого элемента интерфейса менялась логика формирования печатной формы в модуле менеджера. Прямое обращение из модуля менеджера к открытой форме невозможно. Давайте разберем, почему возникает эта проблема и как решить ее правильно с использованием механизмов Библиотеки стандартных подсистем (БСП).

Почему нельзя просто «прочитать» форму из модуля менеджера?

Для начала проанализируем архитектурную причину этого ограничения. В платформе 1С:Предприятие 8.3 управляемые формы и бизнес-логика разделены:

  1. Разделение контекстов выполнения. Модуль менеджера выполняется строго на сервере (причем без контекста какой-либо формы). Форма же инициализируется на клиенте и имеет серверную часть, но модуль менеджера о конкретном экземпляре формы ничего не знает.
  2. Групповая печать. Печать документа может быть вызвана не только из формы самого открытого документа, но и из формы списка (например, когда пользователь выделил несколько строк и нажал кнопку «Печать»). В этой ситуации формы объекта просто не существует в памяти компьютера, и любая попытка обратиться к ее реквизитам вызовет критическую ошибку выполнения.

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

Решение проблемы по шагам с использованием БСП

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

Рассмотрим по шагам, как реализовать этот паттерн.

Шаг 1. Модификация описания команды печати в модуле менеджера

Откроем модуль менеджера нашего документа и найдем процедуру ДобавитьКомандыПечати. Нам необходимо указать системе, что обработка команды печати будет производиться не стандартным методом БСП, а нашей собственной клиентской процедурой.

Для этого мы переопределяем свойство Обработчик у команды печати:


Процедура ДобавитьКомандыПечати(КомандыПечати) Экспорт

    КомандаПечати = КомандыПечати.Добавить();
    КомандаПечати.Идентификатор = "МояПечатнаяФорма";
    КомандаПечати.Представление = НСтр("ru = 'Печать с настройкой строк'");
    
    // Указываем собственный клиентский обработчик вместо стандартного
    КомандаПечати.Обработчик = "ОбщийМодульКлиентСерверПерехват.ВыполнитьКомандуПечатиДокумента";
    
    КомандаПечати.СписокОбъектов = Истина;
    КомандаПечати.ПроверкаПроведенияПередПечатью = Истина;

КонецПроцедуры

Шаг 2. Создание клиентского обработчика печати

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

Важно: БСП автоматически передает в процедуру-обработчик два параметра: ОписаниеКоманды и ФормаОбъекта. Через параметр ФормаОбъекта мы получаем полный доступ к элементам интерфейса открытого документа.


Процедура ВыполнитьКомандуПечатиДокумента(ОписаниеКоманды, ФормаОбъекта) Экспорт

    // Инициализируем структуру параметров печати
    ПараметрыПечати = Новый Структура;
    
    // Проверяем, что печать вызвана именно из формы объекта, а не из списка
    Если ФормаОбъекта <> Неопределено Тогда
        // Безопасно проверяем наличие нашего реквизита на форме
        ИмяРеквизита = "ФлагПечататьТолькоПервуюСтроку";
        Если ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(ФормаОбъекта, ИмяРеквизита) Тогда
            ПараметрыПечати.Вставить("ПечататьТолькоПервуюСтроку", ФормаОбъекта[ИмяРеквизита]);
        КонецЕсли;
    КонецЕсли;

    // Вызываем стандартный метод БСП, передавая заполненную структуру параметров
    УправлениеПечатьюКлиент.ВыполнитьКомандуПечати(
        "Документ.ИмяВашегоДокумента", // Имя метаданных документа
        ОписаниеКоманды.Идентификатор, 
        ОписаниеКоманды.ОбъектыПечати, 
        ФормаОбъекта, 
        ПараметрыПечати
    );

КонецПроцедуры

Шаг 3. Обработка параметров в модуле менеджера на сервере

После того как управление передано методу УправлениеПечатьюКлиент.ВыполнитьКомандуПечати, платформа выполняет серверный вызов и передает управление в процедуру Печать модуля менеджера документа. Наша структура параметров будет доступна во втором аргументе процедуры.

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


Процедура Печать(МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт

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

КонецПроцедуры

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

Альтернативный подход: Вспомогательная форма параметров (Диалог настроек)

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

В этом случае отличной альтернативой является создание вспомогательной обработки или отдельной формы настроек печати:

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

← На главную