При работе с современными конфигурациями на базе Библиотеки стандартных подсистем (БСП) версии 3.0 и выше, разработчики часто сталкиваются с ограничением: все внешние печатные формы (ВПФ) по умолчанию попадают либо в общий список кнопки «Печать» (есть инструмент управления печатными формами в пользовательском режиме), либо в подменю «Дополнительные печатные формы». Рассмотрим ситуацию, когда бизнес-логика требует более тонкой настройки интерфейса — например, размещение определенных внешних форм в созданное нами подменю «Факсимиле» или «Договоры контрагентов».
Проанализируем типичную ошибку начинающих разработчиков. Попытка добавить в таблицу команд поле МестоРазмещения или ИмяГруппы непосредственно в модуле внешней обработки приводит к ошибке: «Поле объекта не обнаружено». Это происходит потому, что структура таблицы команд жестко регламентирована программным интерфейсом БСП. Выясним причину: подсистема «Дополнительные отчеты и обработки» считывает только определенный набор колонок (Представление, Идентификатор, Использование и т.д.). Любые попытки расширить эту таблицу «изнутри» самой обработки игнорируются ядром системы.
Посмотрим на стандартный код формирования таблицы команд, который удобно редактировать, используя плагин для VS Code (удобнее через инструментарий разработчика и плагин VS Code), и который обычно используется во внешних обработках:
Функция ПолучитьТаблицуКоманд()
Команды = Новый ТаблицаЗначений;
Команды.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка"));
Команды.Колонки.Добавить("Идентификатор", Новый ОписаниеТипов("Строка"));
Команды.Колонки.Добавить("Использование", Новый ОписаниеТипов("Строка"));
Команды.Колонки.Добавить("ПоказыватьОповещение", Новый ОписаниеТипов("Булево"));
Команды.Колонки.Добавить("Модификатор", Новый ОписаниеТипов("Строка"));
Возврат Команды;
КонецФункции
Как мы видим, здесь нет механизмов для указания конкретного подменю. Для реализации нашей задачи нам потребуется комплексный подход, сочетающий подготовку внешней обработки и использование расширения конфигурации.
Прежде чем «загнать» внешнюю форму в подменю, это подменю должно существовать в метаданных или быть программно создано. Разберем, как создать группу команд печати в модуле менеджера документа (например, РеализацияТоваровУслуг) через процедуру ПриОпределенииКомандПечати. Если мы не хотим менять основную конфигурацию, используем расширение для этого модуля.
&ИзменениеИКонтроль("ПриОпределенииКомандПечати")
Процедура Расш1_ПриОпределенииКомандПечати(КомандыПечати, ГруппыКомандПечати)
// Добавляем новую группу (подменю)
НоваяГруппа = ГруппыКомандПечати.Добавить();
НоваяГруппа.Имя = "ПодменюФаксимиле";
НоваяГруппа.Представление = НСтр("ru = 'Печать с факсимиле'");
НоваяГруппа.Порядок = 10; // Определяем место группы в общем списке
КонецПроцедуры
Теперь самое важное: нам нужно заставить БСП перекинуть команду внешней обработки в созданную группу ПодменюФаксимиле. Поскольку внешняя обработка регистрируется динамически, нам нужно применить программное изменение форм и вмешаться в процесс построения команд печати на форме. Для этого идеально подходит общий модуль УправлениеПечатьюПереопределяемый.
Рассмотрим алгоритм действий в расширении. Нам необходимо перехватить процедуру ПередВыводомКомандПечати. Именно здесь система уже собрала все команды (и встроенные, и внешние) в одну коллекцию, и мы можем ими манипулировать.
&После("ПередВыводомКомандПечати")
Процедура Расш1_ПередВыводомКомандПечати(КомандыПечати, ПараметрыВывода)
Для Каждого СтрокаКоманды Из КомандыПечати Цикл
// Внешние печатные формы в БСП имеют специфический идентификатор.
// Обычно он содержит GUID или имя обработки.
// Проанализируем идентификатор, чтобы найти нашу форму.
Если Найти(СтрокаКоманды.Идентификатор, "ДоговорТест") > 0 Тогда
// Перенаправляем команду в нашу группу
СтрокаКоманды.ИмяГруппы = "ПодменюФаксимиле";
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Важный момент: при поиске команды по идентификатору учитывайте, что БСП добавляет префиксы к именам команд внешних форм (например, ДополнительнаяПечатнаяФорма_...). Проверьте точное имя идентификатора в отладчике, остановившись в указанной процедуре.
Чтобы наша логика в расширении работала стабильно, во внешней обработке в функции СведенияОВнешнейОбработке рекомендуется задавать уникальный и понятный Идентификатор. Это упростит его поиск в коллекции команд. Рассмотрим пример заполнения команды:
Процедура ДобавитьКоманду(ТаблицаКоманд, Представление, Идентификатор, Использование, ПоказыватьОповещение = Ложь, Модификатор = "")
НоваяКоманда = ТаблицаКоманд.Добавить();
НоваяКоманда.Представление = Представление;
НоваяКоманда.Идентификатор = Идентификатор; // Именно этот ID мы ловим в расширении
НоваяКоманда.Использование = Использование;
НоваяКоманда.ПоказыватьОповещение = ПоказыватьОповещение;
НоваяКоманда.Модификатор = Модификатор;
КонецПроцедуры
Проанализируем еще одну возможность, которую предоставляет БСП. Поле Модификатор часто используется для передачи дополнительных параметров печати. В некоторых кастомизированных конфигурациях (или при доработке общего модуля печати) можно реализовать логику «автораспределения».
Например, в СведенияОВнешнейОбработке мы можем указать: Модификатор = "Группа:ПодменюФаксимиле". Тогда в расширении общего модуля нам не придется зашивать жесткие идентификаторы обработок. Мы сможем написать универсальный код, который считывает значение из Модификатор и подставляет его в ИмяГруппы. Это сделает систему более гибкой: для добавления новой формы в подменю достаточно будет изменить код только в самой внешней обработке.
Пример универсального кода в расширении:
Для Каждого СтрокаКоманды Из КомандыПечати Цикл
Если СтрНачинаетсяС(СтрокаКоманды.Модификатор, "Группа:") Тогда
ИмяГруппы = СтрЗаменить(СтрокаКоманды.Модификатор, "Группа:", "");
СтрокаКоманды.ИмяГруппы = ИмяГруппы;
КонецЕсли;
КонецЦикла;
Мы выяснили, что напрямую через параметры регистрации внешней обработки (БСП 3.1) изменить подменю нельзя. Однако, используя расширение, мы получаем полный контроль над интерфейсом.
Основные правила реализации:
ГруппуКомандПечати в модуле менеджера объекта.УправлениеПечатьюПереопределяемый перехватываем момент формирования списка команд и программно меняем свойство ИмяГруппы для нашей команды.Модификатор для передачи имени целевой группы.Такой подход позволяет сохранить типовую конфигурацию на поддержке и при этом обеспечить пользователям удобный, структурированный интерфейс для работы с дополнительными печатными формами. Для этой задачи есть комплект внешних печатных форм для УНФ 3.0.