При разработке внешних печатных форм (ВПФ) на платформе 1С:Предприятие 8.3 часто возникает задача ограничить их отображение в интерфейсе. Стандартный механизм регистрации ВПФ через МассивНазначений позволяет указать типы объектов (например, Справочник.Сотрудники), для которых предназначена форма. Однако в реальности бизнес-логика бывает сложнее: печатная форма может требоваться только для определенных записей, обладающих специфическим признаком (например, только для сотрудников-иностранцев или только для документов в статусе «Проведено»).
Рассмотрим подробнее несколько архитектурных подходов к решению этой задачи, проанализируем их плюсы и минусы, а также разберем примеры кода для реализации фильтрации.
Если ваша конфигурация построена на БСП (как большинство современных решений: ERP, УТ 11, УНФ, БП 3.0), основным инструментом управления командами печати является общий модуль УправлениеПечатьюПереопределяемый. В нем существует процедура ПередДобавлениемКомандПечати, которая вызывается системой непосредственно перед формированием списка кнопок в меню «Печать».
Разберем ситуацию на примере. Допустим, нам нужно скрыть ВПФ «Трудовой договор иностранца», если у сотрудника не заполнено гражданство. Проанализируем, как это реализовать:
Процедура ПередДобавлениемКомандПечати(ИмяФормы, КомандыПечати, СтандартнаяОбработка) Экспорт
// Проверяем, что мы находимся в нужной форме справочника
Если ИмяФормы = "Справочник.Сотрудники.Форма.ФормаЭлемента" Тогда
// В данном контексте нам нужно получить ссылку на текущий объект.
// Обычно данные формы доступны через параметры или контекст,
// но самый надежный способ для БСП — анализ коллекции КомандыПечати.
// Удаляем команду из списка, если условие не выполняется
Индекс = 0;
Пока Индекс < КомандыПечати.Количество() Цикл
Команда = КомандыПечати[Индекс];
// Ищем нашу внешнюю печатную форму по идентификатору
Если Команда.Идентификатор = "ВнешняяПечатнаяФормаТрудовойДоговор" Тогда
// Проверяем реквизит объекта (предположим, ссылка доступна)
Если НЕ ОбъектСоответствуетУсловию(Команда.ДополнительныеПараметры) Тогда
КомандыПечати.Удалить(Индекс);
Продолжить;
КонецЕсли;
КонецЕсли;
Индекс = Индекс + 1;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Важный нюанс: Метод УправлениеПечатьюПереопределяемый.ПередДобавлениемКомандПечати хорош тем, что он централизован. Однако стоит учитывать, что он срабатывает при инициализации команд печати на форме. Если данные на форме изменятся динамически (пользователь поменял значение реквизита без записи), список команд не обновится мгновенно.
В конфигурациях вроде 1С:Управление нашей фирмой (УНФ) логика печати часто вынесена в менеджеры объектов в процедуру ДобавитьКомандыПечати. Это самое «чистое» место для вмешательства, так как именно здесь формируется первичный массив команд.
Рассмотрим, как с помощью расширения можно динамически управлять составом команд. Мы можем создать префиксный или постфиксный метод (аннотация &После) к процедуре ДобавитьКомандыПечати в менеджере справочника Сотрудники.
&После("ДобавитьКомандыПечати")
Процедура Расш1_ДобавитьКомандыПечати(КомандыПечати)
// В переменной КомандыПечати уже содержатся команды, добавленные системой и ВПФ.
// Мы можем найти нашу команду и программно установить ей признак Видимость или просто удалить.
Для Каждого Команда Из КомандыПечати Цикл
Если Команда.Идентификатор = "МояВнешняяПечатнаяФорма" Тогда
// Условие может зависеть от функциональных опций или прав пользователя
Команда.Видимость = ПолучитьФункциональнуюОпцию("ИспользоватьСпецПечать");
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Этот метод работает глобально: и в форме списка, и в форме элемента. Однако он плохо подходит для фильтрации по конкретным значениям реквизитов объекта, так как процедура ДобавитьКомандыПечати описывает состав команд для всего типа объекта вообще, а не для конкретной ссылки.
Выясним причину, почему команды иногда остаются видимыми, даже если мы пытаемся их скрыть. В БСП существует механизм кэширования команд печати. Чтобы управлять видимостью команд «на лету» в зависимости от данных текущего объекта на форме, рекомендуется использовать метод УправлениеПечатью.НастроитьВидимостьКомандПечати(Форма).
Разберем алгоритм действий:
ПриЧтенииНаСервере или ПриСозданииНаСервере.Пример кода в форме объекта:
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
// СтандартныеПодсистемы.Печать
УправлениеПечатью.НастроитьВидимостьКомандПечати(ЭтаФорма);
// Конец СтандартныеПодсистемы.Печать
КонецПроцедуры
Этот метод заставляет систему пересчитать видимость кнопок в подменю «Печать», опираясь на текущее состояние данных объекта.
В некоторых редакциях БСП при регистрации внешней обработки в функции СведенияОВнешнейОбработке можно попытаться передать параметры видимости. В таблице команд есть колонка УсловияВидимости.
Посмотрим на пример заполнения этой структуры:
НоваяСтрока = ТаблицаКоманд.Добавить();
НоваяСтрока.Представление = НСтр("ru = 'Специальная печать'");
НоваяСтрока.Идентификатор = "СпецПечать";
НоваяСтрока.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыПечатьФормы();
// Условие видимости (работает не во всех версиях БСП для ВПФ)
НоваяСтрока.УсловияВидимости = "Статус = Значение(Перечисление.Статусы.Активен)";
Ограничение: Данный метод чаще всего работает для контекстных отчетов. Для печатных форм он может игнорироваться, поэтому полагаться только на него не стоит без предварительного тестирования в вашей конкретной версии конфигурации.
Иногда программное скрытие кнопок в меню «Печать» оказывается избыточно сложным или невозможным из-за сильной переработки типовых механизмов. В этом случае проанализируем альтернативный вариант: не скрывать кнопку, а выводить сообщение пользователю при попытке печати.
В модуле внешней обработки в процедуре Печать мы можем проверить условия и, если они не соблюдены, прервать выполнение:
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
Индекс = МассивОбъектов.Количество() - 1;
Пока Индекс >= 0 Цикл
ОбъектСсылка = МассивОбъектов[Индекс];
Если НЕ СоответствуетУсловию(ОбъектСсылка) Тогда
// Информируем пользователя
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
СтрШаблон("Сотрудник %1 не является иностранным гражданином. Печать формы невозможна.", ОбъектСсылка));
// Удаляем объект из массива на печать
МассивОбъектов.Удалить(Индекс);
КонецЕсли;
Индекс = Индекс - 1;
КонецЦикла;
Если МассивОбъектов.Количество() = 0 Тогда
Возврат; // Ничего не печатаем
КонецЕсли;
// Далее стандартная логика формирования ТабличногоДокумента...
КонецПроцедуры
Этот подход считается более дружелюбным по отношению к пользователю, так как отсутствие кнопки в списке часто воспринимается как ошибка системы («Куда делась кнопка?»), в то время как четкое сообщение объясняет причину невозможности действия.
Проанализируем ситуацию, когда пользователь выделяет в списке несколько сотрудников и нажимает «Печать». Если у одного сотрудника есть признак для печати, а у другого нет, возникает дилемма: показывать ли команду?
Существует два подхода:
Второй вариант предпочтительнее для групповой обработки документов, так как он позволяет распечатать формы для валидных объектов за один клик, просто пропустив остальные.
Для реализации скрытия ВПФ в 1С наиболее надежным методом является использование расширения для переопределения процедуры ДобавитьКомандыПечати в менеджере объекта или использование УправлениеПечатьюПереопределяемый. Однако, если логика фильтрации очень сложная и зависит от динамических данных, самым простым и стабильным решением будет проверка условий непосредственно в коде самой внешней обработки с выводом информативного сообщения пользователю.