При сопровождении сильно кастомизированных конфигураций на обычных формах (например, УТ 10.3, УПП 1.3 или КА 1.1) часто возникает задача добавить одинаковый функционал в десятки различных документов. Прямое редактирование каждой формы превращает последующее обновление конфигурации в кошмар. В этой статье мы разберем, как реализовать динамическое добавление кнопки на командную панель формы, используя возможности встроенного языка и типовые механизмы конфигураций, чтобы максимально облегчить процесс поддержки.
Для того чтобы программно изменить интерфейс формы, нам нужно найти процедуру, которая вызывается во всех интересующих нас объектах при их открытии. В типовом решении Управление торговлей 10.3 одной из таких процедур является УстановитьДоступностьПоляВводаНомера. Она присутствует практически в каждом документе. Рассмотрим план действий: нам нужно вклиниться в выполнение этой процедуры, передать туда контекст формы и добавить кнопку.
Проанализируем ситуацию: если мы добавим вызов нашего общего модуля в одну типовую процедуру, которую используют все документы, нам придется внести изменение всего в одном месте вместо правки 12–20 различных форм.
Для добавления кнопки нам потребуется доступ к объекту ЭлементыФормы. Рассмотрим пример кода, который можно разместить в общем модуле. В качестве параметров процедура должна принимать имя метаданных объекта и саму форму.
Процедура ДобавитьКнопкуНаФорму(ИмяОбъекта, ФормаОбъекта) Экспорт
Элементы = ФормаОбъекта.ЭлементыФормы;
// Пытаемся найти командную панель товаров
КоманднаяПанель = Элементы.Найти("КоманднаяПанельТовары");
Если КоманднаяПанель <> Неопределено Тогда
// Определяем действие, которое будет выполняться при нажатии
// Важно: в обычных формах действие должно указывать на процедуру в модуле формы
ДействиеКнопки = Новый Действие("ДоговорКонтрагентаНачалоВыбора");
НоваяКнопка = КоманднаяПанель.Кнопки.Добавить(
"МояУникальнаяКнопка",
ТипКнопкиКоманднойПанели.Действие,
"Выполнить операцию",
ДействиеКнопки
);
НоваяКнопка.Отображение = ОтображениеКнопкиКоманднойПанели.НадписьКартинка;
НоваяКнопка.Картинка = БиблиотекаКартинок.Выполнить;
КонецЕсли;
КонецПроцедуры
Основная сложность в обычных формах заключается в том, что метод Новый Действие() может ссылаться только на процедуру, расположенную в модуле самой формы. Мы не можем напрямую указать процедуру общего модуля. Однако мы договорились не редактировать модули форм. Как быть?
Разберем остроумный способ решения этой проблемы. Мы можем использовать "подмену" действия. В типовых документах 1С уже есть процедуры-обработчики для стандартных реквизитов (например, НачалоВыбора для склада, договора или организации), которые вызывают логику из общих модулей. Мы можем назначить кнопке выполнение такой типовой процедуры, а внутри общего модуля поставить проверку на имя элемента.
Рассмотрим пример реализации в общем модуле, который вызывается из типового обработчика НачалоВыбора:
// В типовом общем модуле, куда заходит выполнение при начале выбора договора
Процедура НачалоВыбораДоговора(ФормаДокумента, ЭлементФормы, СтандартнаяОбработка) Экспорт
// Проверяем, не нашей ли кнопкой был вызван этот обработчик
Если ЭлементФормы.Имя = "МояУникальнаяКнопка" Тогда
СтандартнаяОбработка = Ложь; // Отменяем стандартное открытие справочника
// Вызываем нашу кастомную логику
МойОбщийМодульСервер.ВыполнитьНужноеДействие(ФормаДокумента);
Возврат;
КонецЕсли;
// Далее идет типовой код...
КонецПроцедуры
Если мы хотим перехватить системные события, такие как ПриОткрытии, не меняя код в модуле формы, мы можем воспользоваться методом УстановитьДействие. Рассмотрим, как это работает: при инициализации формы в общем модуле мы программно переназначаем стандартное событие на свою процедуру.
// Пример перехвата события ПриОткрытии
ФормаОбъекта.УстановитьДействие("ПриОткрытии", Новый Действие("МояПроцедураВОбщемМодуле"));
Важный нюанс: Этот метод имеет ограничения в обычных формах — процедура все равно должна быть видна в контексте формы. Поэтому наиболее стабильным вариантом остается использование метода, предложенного автором темы: использование уже существующих связей "Форма -> Общий модуль" через типовые обработчики выбора или изменения реквизитов.
Проанализируем преимущества данного подхода:
Для того чтобы решение было максимально надежным, придерживайтесь следующих правил:
Попытка ... Исключение при добавлении элементов, чтобы возможная ошибка в интерфейсе не блокировала работу пользователя с документом.МетаданныеОбъекта.Формы для проверки).Автозаполнение), программное добавление кнопок может потребовать предварительного отключения автозаполнения или поиска панели через коллекцию ЭлементыФормы.Таким образом, комбинируя программное создание элементов управления и использование существующих точек соприкосновения модулей форм с общими модулями, мы получаем гибкий инструмент управления интерфейсом без ущерба для обновляемости конфигурации.