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