Как динамически изменить команду печати в БСП и распечатать комплект макетов от разных менеджеров?

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

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

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

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

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

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

Оптимальное решение проблемы с кэшем:

Вместо того чтобы бороться с платформой и пытаться подменить идентификатор, давайте изменим архитектурный подход. Нам необходимо создать одну команду с постоянным, статичным идентификатором (например, КомплектПользовательскойНастройки).

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

Как распечатать комплект макетов от разных менеджеров печати?

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

Разберем по шагам, как правильно реализовать печать разнотипных макетов одной кнопкой с использованием паттерна «Адаптер».

  1. Создание менеджера-адаптера: В качестве свойства МенеджерПечати для нашей сводной команды необходимо указать общую обработку или нетиповой общий модуль. Этот модуль будет выступать «фасадом».
  2. Перенаправление вызовов: Внутри экспортной процедуры печати этого адаптера мы перебираем требуемые по настройке макеты и программно перенаправляем вызовы к их «родным» менеджерам печати (например, вызываем Документы.РеализацияТоваровУслуг.Печать(...), затем Документы.СчетНаОплату.Печать(...)).
  3. Сборка коллекции: После получения всех табличных документов, наш адаптер собирает их в единую КоллекциюПечатныхФорм и возвращает в стандартную форму предпросмотра БСП.

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


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

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

Посмотрим на критически важные требования БСП, о которых часто забывают при сборке комплексных печатных форм.

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

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


УправлениеПечатью.ЗадатьОбластьПечатиДокумента(ТабличныйДокумент, НомерСтрокиНачало, ОбъектыПечати, ТекущийДокумент);

Если «чужой» менеджер вернет документ без заданных областей, общая печать комплекта завершится ошибкой.

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

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

← На главную