Как повторно вызвать «ПриСозданииНаСервере» для формы «ПечатьДокументов» в 1С?

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

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

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

Почему прямой вызов «ПриСозданииНаСервере» не работает?

Проанализируем ситуацию с точки зрения архитектуры платформы «1С:Предприятие». Процедура-обработчик ПриСозданииНаСервере вызывается ядром платформы в процессе конструирования контекста формы на сервере. В этот момент выполняются критически важные операции:

  1. Инициализируются реквизиты формы.
  2. Платформа считывает переданные параметры открытия формы и сопоставляет их с реквизитами.
  3. Строится графическое дерево элементов управления.
  4. Определяются права доступа текущего пользователя к элементам формы.

Если мы принудительно вызовем этот метод из кода клиента или другого серверного метода, платформа воспримет это как вызов обычной процедуры. Никакого перестроения интерфейса или сброса параметров не произойдет. Более того, это может вызвать трудноотлавливаемые ошибки из-за повторного выполнения кода инициализации над уже созданными объектами.

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

Способ 1. Гарантированный перезапуск формы через уникальный ключ (КлючУникальности)

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

Для реализации этого метода нам потребуется использовать механизм уникальных ключей. Если мы попытаемся открыть форму с тем же ключом уникальности, платформа просто вернет ссылку на уже открытое окно и событие ПриСозданииНаСервере не сработает. Чтобы обойти это, мы генерируем новый УникальныйИдентификатор.

Рассмотрим по шагам, как это реализовать в модуле формы ПечатьДокументов при нажатии на кнопку обновления:


&НаКлиенте
Процедура ПереоткрытьФормуПечати()
    
    // 1. Собираем параметры текущей формы, которые нам понадобятся для повторного открытия
    ПараметрыПереоткрытия = Новый Структура;
    ПараметрыПереоткрытия.Вставить("ИменаМакетов", Параметры.ИменаМакетов);
    ПараметрыПереоткрытия.Вставить("ОбъектыПечати", Параметры.ОбъектыПечати);
    ПараметрыПереоткрытия.Вставить("ПараметрыВывода", Параметры.ПараметрыВывода);
    
    // Добавляем новые параметры, которые изменил пользователь на форме
    ПараметрыПереоткрытия.Вставить("ДополнительныйПараметр", Объект.НовоеЗначениеПараметра);
    
    // 2. Генерируем новый GUID для ключа уникальности
    НовыйКлюч = Строка(Новый УникальныйИдентификатор);
    
    // 3. Открываем новое окно формы печати
    ОткрытьФорму("ОбщаяФорма.ПечатьДокументов", ПараметрыПереоткрытия, , НовыйКлюч);
    
    // 4. Закрываем текущую (старую) форму, чтобы она не оставалась висеть у пользователя
    ЭтаФорма.Закрыть();
    
КонецПроцедуры

Этот способ гарантирует, что платформа отработает весь жизненный цикл формы заново. Пользователь увидит обновленный табличный документ без "зависаний" интерфейса. Главный минус метода — мимолетное мерцание экрана при закрытии старого и открытии нового окна, что может быть не очень эстетично в веб-клиенте.

Способ 2. Выделение логики инициализации в отдельную процедуру (Рефакторинг)

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

Вместо того чтобы держать весь код внутри ПриСозданииНаСервере, мы выполняем декомпозицию:

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

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


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Первичная инициализация при открытии формы
    ИнициализироватьПараметрыФормы();
    
    // Вызов общего метода заполнения
    СформироватьПечатныеДокументыНаСервере();
    
КонецПроцедуры

&НаСервере
Процедура СформироватьПечатныеДокументыНаСервере()
    
    // Очищаем старый табличный документ на форме перед заполнением
    ЭтотОбъект.ТабличныйДокумент.Очистить();
    
    // Здесь располагается весь сложный код генерации печатных форм
    // (Получение макетов, заполнение областей, вывод секций)
    ВывестиДанныеВТабличныйДокумент(ЭтотОбъект.ТабличныйДокумент);
    
КонецПроцедуры

&НаКлиенте
Процедура ПриИзмененииНастроекПечати(Элемент)
    
    // Пользователь изменил параметр, вызываем только серверное заполнение без пересоздания формы
    СформироватьПечатныеДокументыНаСервере();
    
КонецПроцедуры

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

Способ 3. Вызов существующих внутренних процедур формы

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

Обычно в модуле формы БСП присутствуют процедуры со следующими названиями:

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


&НаКлиенте
Процедура КомандаОбновитьЭкран(Команда)
    ВыполнитьОбновлениеНаСервере();
КонецПроцедуры

&НаСервере
Процедура ВыполнитьОбновлениеНаСервере()
    // Вызываем штатную процедуру БСП, которая перестроит ТабличныйДокумент
    ЗаполнитьПечатныеФормы(); 
КонецПроцедуры

Это компромиссный вариант: мы не переоткрываем форму и не пишем сложный код рефакторинга, а просто используем заложенную авторами БСП модульность.

Способ 4. Использование стандартного метода «УправлениеПечатьюКлиент»

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

Для этого в БСП предусмотрен общий модуль УправлениеПечатьюКлиент. Вместо ручного манипулирования формой мы можем повторно инициализировать процесс печати из формы-владельца:


&НаКлиенте
Процедура ОбновитьПечатьИзДокумента()
    
    // Формируем коллекцию для повторной отправки на печать
    ПараметрыОтправки = Новый Структура;
    ПараметрыОтправки.Вставить("ИсточникДанных", Объект.Ссылка);
    
    // Вызываем стандартный метод БСП
    УправлениеПечатьюКлиент.ВыполнитьКомандуПечати(
        "Документ_РеализацияТоваровУслуг", 
        "Акт", 
        Новый Массив, 
        ЭтаФорма, 
        ПараметрыОтправки
    );
    
КонецПроцедуры

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

Резюме и рекомендации

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

  1. Если вам нужно максимально быстрое решение без изменения логики формы — используйте Способ 1 (переоткрытие через КлючУникальности). Он надежен и гарантирует отсутствие старых кэшированных данных.
  2. Если вы проектируете систему «на перспективу» и заботитесь о производительности веб-клиента — выберите Способ 2 (выделение логики в отдельный метод). Это исключит мерцание интерфейса и снизит нагрузку на сервер.
  3. Если конфигурация сильно кастомизирована и содержит много типовых механизмов — изучите структуру модуля и воспользуйтесь Способом 3 (вызов штатных процедур заполнения).

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

← На главную