При разработке в расширениях 1С:Предприятие 8.3 одной из приоритетных задач является сохранение высокой обновляемости конфигурации. Чтобы минимизировать конфликты при обновлении от поставщика, разработчики стараются избегать заимствования (переноса) объектов метаданных, особенно управляемых форм, в расширение. Все интерфейсные доработки — добавление реквизитов, условное оформление, переопределение динамических списков — успешно выполняются программным путем в обработчиках типа ПриСозданииНаСервере общего модуля или через перехват методов формы. Для стандартизации такой разработки можно использовать общий модуль с функциями программного создания элементов форм и команд.
Однако при попытке программно добавить кнопку для вызова глобальной или объектной команды (например, команды конкретного журнала документов или общей команды конфигурации) разработчики сталкиваются с платформенным ограничением. Попытка напрямую связать программно созданную кнопку со сторонней командой через свойство ИмяКоманды вызывает неустранимую ошибку. В этой статье мы подробно разберем причины этой проблемы и рассмотрим три эффективных способа её решения.
Когда мы настраиваем интерфейс формы интерактивно в конфигураторе, платформа позволяет перетащить общую команду или команду объекта (справочника, документа, журнала) прямо на командную панель формы. Платформа самостоятельно берет на себя связывание элемента управления и глобального обработчика.
Но если мы попытаемся проделать это программно через встроенный язык:
НоваяКнопка = Элементы.Добавить("КнопкаВыполнить", Тип("КнопкаФормы"), Элементы.КоманднаяПанель);
НоваяКнопка.ИмяКоманды = "ЖурналДокументов.СкладскиеДокументы.Команда.Перемещение"; // Вызовет ошибку!
Платформа 1С выдаст ошибку «Недопустимое значение». Свойство ИмяКоманды программно созданной кнопки формы может принимать исключительно имена локальных команд, зарегистрированных в коллекции Команды самой формы. Напрямую обратиться к глобальным или объектным командам встроенный язык не позволяет.
Выясним, какими способами можно обойти это ограничение, сохранив чистоту программного кода и не заимствуя форму визуально.
---
Это самый быстрый и изящный способ, не требующий заимствования формы в расширение вообще. Вся работа выполняется в процедуре общего модуля (например, при перехвате события ПриСозданииНаСервере с помощью директивы &После). Вместо стандартного элемента КнопкаФормы мы будем использовать ДекорацияФормы с видом Надпись, оформленную как гиперссылка.
Разберем по шагам логику построения такого интерфейсного элемента:
e1cib/command/<ПутьККоманде>.ФорматированнаяСтрока и назначаем её заголовком декорации.Проанализируем пример кода, выполняемый на сервере:
&После("ПриСозданииНаСервере")
Процедура Расш_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Получаем командную панель формы, куда хотим поместить кнопку
КоманднаяПанель = Элементы.ФормаКоманднаяПанель;
// Добавляем элемент декорации
НоваяКнопка = Элементы.Добавить("Расш_ДекорацияПеремещение", Тип("ДекорацияФормы"), КоманднаяПанель);
НоваяКнопка.Вид = ДекорацияФормыВид.Надпись;
НоваяКнопка.Гиперссылка = Истина;
// Формируем внутренний адрес команды журнала документов
АдресКоманды = "e1cib/command/ЖурналДокументов.СкладскиеДокументы.Команда.Перемещение";
// Задаем форматированный заголовок. Ссылка передается пятым параметром конструктора
НоваяКнопка.Заголовок = Новый ФорматированнаяСтрока("Создать перемещение", , , , АдресКоманды);
КонецПроцедуры
При нажатии на такую декорацию платформа 1С автоматически распознает навигационную ссылку протокола e1cib и запустит выполнение команды.
Если команда журнала документов должна открывать форму нового документа на основании выбранной строки списка, ей необходим параметр (ссылка на текущий документ). В навигационную ссылку можно динамически передавать параметры, используя синтаксис ?cmdprm=<Значение>.
Для реализации динамической передачи параметра нам потребуется обновлять ссылку при изменении активной строки списка. Рассмотрим пример доработки события ПриАктивизацииСтроки динамического списка:
&НаКлиенте
Процедура Расш_СписокПриАктивизацииСтрокиПосле(Элемент)
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Если ТекущиеДанные <> Неопределено Тогда
СсылкаНаОбъект = ТекущиеДанные.Ссылка;
// Преобразуем ссылку в строковый идентификатор навигационной ссылки
Идентификатор = ПолучитьНавигационнуюСсылку(СсылкаНаОбъект);
// Находим созданную декорацию
Декорация = Элементы.Найти("Расш_ДекорацияПеремещение");
Если Декорация <> Неопределено Тогда
// Формируем параметризованный адрес команды
АдресКоманды = "e1cib/command/ЖурналДокументов.СкладскиеДокументы.Команда.Перемещение?cmdprm=" + Идентификатор;
Декорация.Заголовок = Новый ФорматированнаяСтрока("Создать перемещение", , , , АдресКоманды);
КонецЕсли;
EndIf;
КонецПроцедуры
Преимущества метода: Полная независимость от формы. Форма не заимствуется в расширение.
Недостатки метода: Внешний вид элемента будет соответствовать текстовой гиперссылке, а не классической кнопке командной панели.
---
Если вам обязательно требуется полноценная кнопка (с заливкой, рамками, возможностью задать стандартную картинку 1С) и текстовая гиперссылка не подходит по требованиям UX/UI, применим метод «умного» заимствования.
Мы добавим форму списка журнала документов в наше расширение, но не будем изменять её визуально. Вся визуальная структура формы в расширении останется пустой (унаследованной от основной конфигурации), что исключит любые конфликты при обновлении. Мы задействуем только модуль формы для написания клиентского обработчика-посредника.
Разберем этот алгоритм по шагам:
ПриСозданииНаСервере программно добавим локальную команду формы и свяжем её с программно созданной кнопкой.ПерейтиПоНавигационнойСсылке().Рассмотрим реализацию серверной части в модуле формы:
&После("ПриСозданииНаСервере")
Процедура Расш_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Шаг 1. Регистрируем локальную команду на самой форме
НоваяКоманда = Команды.Добавить("Расш_КомандаПеремещение");
НоваяКоманда.Действие = "Расш_ОбработчикКомандыПеремещение"; // Имя процедуры на клиенте
// Шаг 2. Находим командную панель формы
КоманднаяПанель = Элементы.Найти("ФормаКоманднаяПанель");
Если КоманднаяПанель <> Неопределено Тогда
// Шаг 3. Добавляем полноценную кнопку формы
НоваяКнопка = Элементы.Добавить("Расш_КнопкаПеремещение", Тип("КнопкаФормы"), КоманднаяПанель);
НоваяКнопка.ИмяКоманды = "Расш_КомандаПеремещение";
НоваяКнопка.Заголовок = "Перемещение...";
НоваяКнопка.Картинка = БиблиотекаКартинок.ПереносДанных;
НоваяКнопка.Отображение = ОтображениеКнопки.КартинкаИТекст;
КонецЕсли;
КонецПроцедуры
Теперь опишем клиентскую часть в модуле формы, которая будет перехватывать нажатие и запускать нужную команду с контекстом текущей строки списка:
&НаКлиенте
Процедура Расш_ОбработчикКомандыПеремещение(Команда)
// Получаем текущие данные из динамического списка
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Если ТекущиеДанные <> Неопределено И ЗначениеЗаполнено(ТекущиеДанные.Ссылка) Тогда
// Конструируем навигационную ссылку с параметром текущей строки
НавСсылка = "e1cib/command/ЖурналДокументов.СкладскиеДокументы.Команда.Перемещение?cmdprm=" + ТекущиеДанные.Ссылка;
// Выполняем переход, который активирует команду журнала документов
ПерейтиПоНавигационнойСсылке(НавСсылка);
КонецЕсли;
КонецПроцедуры
Преимущества метода: Кнопка выглядит абсолютно стандартно, поддерживает картинки, подсказки и стандартное поведение кнопок панели. Изменения кода локализованы в расширении, форма визуально не засоряется лишними элементами в конфигураторе расширения. При необходимости динамического добавления множества реквизитов и элементов можно воспользоваться конструктором для программной модификации управляемых форм.
---
Если вы работаете в современной типовой конфигурации 1С (например, 1С:ERP, 1С:Комплексная автоматизация, 1С:Управление торговлей или 1С:ЗУП), то в них «из коробки» внедрена Библиотека стандартных подсистем (БСП).
Подсистема БСП «Подключаемые команды» позволяет добавлять команды объектов и журналов на любые формы списков без ручного написания кода создания кнопок. Если форма списка журнала поддерживает БСП (то есть в её коде присутствует вызов ПодключаемыеКоманды.ПриСозданииНаСервере(ЭтотОбъект)), вы можете зарегистрировать свою команду в БСП.
Разберем основные шаги по интеграции команды через БСП:
ДобавитьКомандыСозданияНаОсновании или общие переопределяемые модули.Подключаемый_ВыполнитьКоманду, который самостоятельно передаст контекст выделенных строк.Пример регистрации команды в модуле менеджера объекта для интеграции с БСП:
Процедура ДобавитьКомандыСозданияНаОсновании(ТаблицаКоманд) Экспорт
Команда = ТаблицаКоманд.Добавить();
Команда.Идентификатор = "Перемещение";
Команда.Представление = НСтр("ru = 'Создать перемещение'");
Команда.Порядок = 10;
Команда.ЗаписыватьВерсиюНовогоОбъекта = Истина;
Команда.РежимПроведенияСобытия = "Проводить";
КонецПроцедуры
При использовании БСП вам не придется писать ни одной строчки программного кода по манипуляции элементами формы списка. Платформа и подсистемы БСП сделают всю работу автоматически.
---
Выбор конкретного решения зависит от архитектуры вашей конфигурации и требований к дизайну: