Кнопка из кода: команда формы, элемент и обработчик в управляемой форме
Содержание
Чтобы программно добавить кнопку в командную панель управляемой формы 1С, нужны два вызова в ПриСозданииНаСервере: Команды.Добавить() создаёт команду формы и связывает её с процедурой-обработчиком, а Элементы.Добавить() с типом КнопкаФормы кладёт кнопку в нужную панель и указывает на эту команду. Сама процедура-обработчик должна уже существовать в модуле формы.
Такой приём нужен, когда форму нельзя или не хочется менять в редакторе: в расширении конфигурации, в общем модуле, который подключает кнопки к десятку форм сразу, или когда набор кнопок зависит от прав и настроек пользователя. Всё ниже относится к платформе 1С:Предприятие 8.3 и управляемым формам. Для обычных форм дан отдельный короткий раздел.
Из чего состоит кнопка в управляемой форме
В управляемой форме кнопка — это не самостоятельный объект, а связка трёх частей. Если не хватает хотя бы одной, кнопка либо не появится, либо не будет работать.
| Часть | Где живёт | За что отвечает |
|---|---|---|
| Команда формы | коллекция Команды | заголовок, картинка, подсказка, имя процедуры-обработчика |
| Кнопка | коллекция Элементы, тип КнопкаФормы | место на экране и внешний вид |
| Процедура | модуль формы | что произойдёт по нажатию |
Командная панель тоже элемент формы. У каждой формы есть своя основная панель — в коде она доступна как Элементы.ФормаКоманднаяПанель. Кроме неё, собственная панель есть у каждой таблицы формы. Для динамического списка с именем Список это Элементы.Список.КоманднаяПанель.
Отдельно существуют команды объектов метаданных — их задают в Конфигураторе у справочника, документа или общей команды. Они попадают в панели автоматически, через свойство «Группа» команды. Программно же добавляют именно команды формы: они живут, пока открыта эта форма, и нигде не сохраняются.
Всё, что вы добавили кодом, существует только в текущем экземпляре формы. При следующем открытии ПриСозданииНаСервере отработает заново и создаст кнопку снова. Поэтому код добавления не должен падать при повторном вызове.
Добавление кнопки в командную панель через код формы
Базовый пример: на форму документа добавляем кнопку «Заполнить по шаблону» в основную командную панель.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ДобавитьКнопкуЗаполнения();
КонецПроцедуры
&НаСервере
Процедура ДобавитьКнопкуЗаполнения()
ИмяКоманды = "ЗаполнитьПоШаблону";
// 1. Команда формы
Команда = Команды.Добавить(ИмяКоманды);
Команда.Заголовок = "Заполнить по шаблону";
Команда.Подсказка = "Заполнить табличную часть из сохранённого шаблона";
Команда.Действие = "ЗаполнитьПоШаблонуОбработчик";
Команда.Картинка = БиблиотекаКартинок.ЗаполнитьФорму;
Команда.Отображение = ОтображениеКнопки.КартинкаИТекст;
// 2. Кнопка в основной командной панели
Кнопка = Элементы.Добавить("Кнопка" + ИмяКоманды, Тип("КнопкаФормы"),
Элементы.ФормаКоманднаяПанель);
Кнопка.ИмяКоманды = ИмяКоманды;
Кнопка.Вид = ВидКнопкиФормы.КнопкаКоманднойПанели;
КонецПроцедуры
// 3. Обработчик
&НаКлиенте
Процедура ЗаполнитьПоШаблонуОбработчик(Команда)
ЗаполнитьПоШаблонуНаСервере();
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьПоШаблонуНаСервере()
// заполнение табличной части
КонецПроцедуры
Что здесь происходит по шагам:
Команды.Добавить(ИмяКоманды)создаёт команду формы. Имя должно быть уникальным в пределах формы.- В свойство
Действиезаписывается строка с именем процедуры, а не ссылка на неё. Элементы.Добавить(Имя, Тип, Родитель)создаёт кнопку. Третий параметр — группа, в которую она попадёт, то есть командная панель.Кнопка.ИмяКомандысвязывает кнопку с командой. Именно это свойство делает кнопку рабочей.
Картинку ЗаполнитьФорму в примере замените на ту, что точно есть в вашей конфигурации. Если такой картинки нет, модуль просто не скомпилируется. Список доступных картинок виден в Конфигураторе: Общие → Общие картинки плюс стандартная библиотека платформы в синтакс-помощнике.
Кнопка не в конец, а в нужное место
Элементы.Добавить() всегда ставит элемент последним в группе. Чтобы кнопка встала перед конкретным элементом, используйте Элементы.Вставить(): последний параметр — элемент, перед которым нужно вставить.
Кнопка = Элементы.Вставить("КнопкаЗаполнитьПоШаблону", Тип("КнопкаФормы"),
Элементы.ФормаКоманднаяПанель, Элементы.ФормаЗаписать);
Имя ФормаЗаписать — пример. Точное имя стандартной кнопки посмотрите в дереве элементов формы в Конфигураторе: у автоматически созданных кнопок оно начинается с имени панели.
Переставить уже существующую кнопку можно методом Элементы.Переместить(Элемент, Родитель, МестоРасположения).
Кнопка в панель таблицы и в подменю
В панель табличной части или списка кнопку добавляют так же, меняется только родитель:
Кнопка = Элементы.Добавить("КнопкаПроверитьСтроки", Тип("КнопкаФормы"),
Элементы.Товары.КоманднаяПанель);
Кнопка.ИмяКоманды = "ПроверитьСтроки";
Если команд набралось больше трёх-четырёх, соберите их в подменю. Подменю — это группа формы особого вида:
Подменю = Элементы.Добавить("ПодменюСервис", Тип("ГруппаФормы"),
Элементы.ФормаКоманднаяПанель);
Подменю.Вид = ВидГруппыФормы.Подменю;
Подменю.Заголовок = "Сервис";
Кнопка = Элементы.Добавить("КнопкаЗаполнитьПоШаблону", Тип("КнопкаФормы"), Подменю);
Кнопка.ИмяКоманды = "ЗаполнитьПоШаблону";
Повторяющиеся строки удобно вынести в процедуру общего модуля, которая принимает форму, имя команды, заголовок и родителя. Тогда одна и та же кнопка добавляется в десяток форм одной строкой.
Кнопка через расширение конфигурации
Расширение — правильный способ добавить кнопку в типовую конфигурацию , не снимая её с поддержки. Механизм расширений появился в платформе 8.3.6. Есть два пути.
Путь 1. Визуально, без кода добавления
- В Конфигураторе откройте
Конфигурация → Расширения конфигурациии создайте расширение. Назначение — «Адаптация» или «Дополнение». - В дереве основной конфигурации найдите нужную форму, щёлкните правой кнопкой и выберите
Добавить в расширение. Форма будет заимствована. - Откройте заимствованную форму в расширении. На вкладке «Команды» добавьте команду, задайте ей действие — Конфигуратор сам создаст процедуру в модуле формы расширения.
- Перетащите команду в нужную командную панель в дереве элементов.
- Обновите конфигурацию базы данных расширения (F7) и запустите 1С:Предприятие.
Этот путь проще, но при каждом обновлении типовой расширение сравнивает заимствованную форму с исходной. Если поставщик сильно переделал форму, придётся проверить, на месте ли ваша кнопка.
Путь 2. Код в модуле заимствованной формы
Удобен, когда кнопка нужна по условию или в нескольких формах. В модуле формы расширения пишем процедуру с аннотацией &После:
&НаСервере
&После("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
Если Команды.Найти("Расш1_ЗаполнитьПоШаблону") <> Неопределено Тогда
Возврат;
КонецЕсли;
Команда = Команды.Добавить("Расш1_ЗаполнитьПоШаблону");
Команда.Заголовок = "Заполнить по шаблону";
Команда.Действие = "Расш1_ЗаполнитьПоШаблону";
Кнопка = Элементы.Добавить("Расш1_КнопкаЗаполнитьПоШаблону", Тип("КнопкаФормы"),
Элементы.ФормаКоманднаяПанель);
Кнопка.ИмяКоманды = "Расш1_ЗаполнитьПоШаблону";
КонецПроцедуры
&НаКлиенте
Процедура Расш1_ЗаполнитьПоШаблону(Команда)
// действие кнопки
КонецПроцедуры
Три практических правила для расширений:
- 🏷️ Префикс в именах. Префикс расширения (
Расш1_или свой) в именах команд, элементов и процедур защищает от совпадения с тем, что поставщик добавит в следующем релизе. - 🔗 Аннотация привязана к обработчику.
&После("ПриСозданииНаСервере")работает, только если у исходной формы есть такой обработчик. Если его нет, назначьте событиюПриСозданииНаСерверепроцедуру прямо в свойствах заимствованной формы. - 🛡️ Безопасный режим. По умолчанию расширение работает в безопасном режиме. Для простой кнопки это не мешает. Но если обработчик пишет файлы или вызывает внешние компоненты, режим придётся отключать в свойствах расширения.
Как связать кнопку с обработчиком и передать в него данные
Процедура, имя которой записано в Команда.Действие, должна:
- 📍 лежать в модуле той же формы (для расширения — в модуле заимствованной формы);
- 💻 иметь директиву
&НаКлиенте— команда формы всегда вызывается на клиенте; - 🔢 принимать ровно один параметр — саму команду.
Параметр Команда пригождается, когда одна процедура обслуживает несколько кнопок. Например, вы добавили в цикле пять кнопок «Шаблон 1» … «Шаблон 5», и все они ведут в один обработчик:
&НаКлиенте
Процедура ВыбратьШаблон(Команда)
НомерШаблона = Число(СтрЗаменить(Команда.Имя, "Шаблон", ""));
ПрименитьШаблонНаСервере(НомерШаблона);
КонецПроцедуры
Для такого кода имена команд должны строиться как "Шаблон" + Формат(Номер, "ЧГ=0"). Без Формат число больше 999 получит разделитель групп, и разбор имени сломается.
Если для кнопки нужны данные, которых нет в имени команды, сохраните их в реквизит формы или в структуру, заполненную на сервере при создании формы. Свойство Команда.Действие принимает только имя процедуры, параметров туда не передать.
Хотите, чтобы кнопка в форме объекта была недоступна в режиме «только просмотр»? Поставьте команде ИзменяетСохраняемыеДанные = Истина. Платформа сама заблокирует её, если форма открыта только на чтение.
Видимость и доступность программно добавленных кнопок
Скрыть или заблокировать кнопку можно двумя способами — через элемент или через команду.
| Что меняем | Код | Результат |
|---|---|---|
| Видимость кнопки | Элементы.КнопкаЗаполнитьПоШаблону.Видимость = Ложь | кнопки нет на экране |
| Доступность кнопки | Элементы.КнопкаЗаполнитьПоШаблону.Доступность = Ложь | кнопка серая |
| Доступность команды | Команды.ЗаполнитьПоШаблону.Доступность = Ложь | блокируются все кнопки этой команды |
Самое надёжное — вообще не создавать кнопку, если пользователю она не положена. Проверку делайте на сервере, до Команды.Добавить:
Если Не РольДоступна("ПолныеПрава") И Не РольДоступна("ЗаполнениеПоШаблону") Тогда
Возврат;
КонецЕсли;
Роль ЗаполнениеПоШаблону в примере — ваша собственная роль, её нужно создать. Если опираться на права к объекту, используйте ПравоДоступа("Изменение", Метаданные.Документы.РеализацияТоваровУслуг) с нужным объектом метаданных.
Если доступность зависит от данных формы — статуса документа, заполненности поля, — меняйте её в двух местах: в ПриСозданииНаСервере для начального состояния и в обработчике ПриИзменении нужного поля. Свойства Видимость и Доступность можно менять и на клиенте, лишний серверный вызов для этого не нужен.
Скрытая кнопка — не защита. Если действие нельзя выполнять без прав, проверяйте права и внутри серверной процедуры-обработчика. Серверную процедуру можно вызвать и без кнопки, а проверка прав на сервере сработает всегда.
Если пользователь перенастроил панель
Пользователь может открыть «Изменить форму» и скрыть или переставить кнопки. Если после доработки кнопка «пропала» у одного человека и видна у остальных, сначала сбросьте ему настройки формы: в том же окне «Изменить форму» есть возврат к стандартным настройкам.
Обычные формы: как это делалось раньше
В конфигурациях на обычных формах (толстый клиент, старые самописные решения) модели «команда + элемент» нет. Кнопка добавляется прямо в коллекцию кнопок панели, а действие задаётся объектом Действие:
Процедура ПриОткрытии()
ЭлементыФормы.ОсновнаяКоманднаяПанель.Кнопки.Добавить(
"ЗаполнитьПоШаблону",
ТипКнопкиКоманднойПанели.Действие,
"Заполнить по шаблону",
Новый Действие("ЗаполнитьПоШаблонуНажатие"));
КонецПроцедуры
Процедура ЗаполнитьПоШаблонуНажатие(Кнопка)
// действие
КонецПроцедуры
В обычных формах нет директив &НаКлиенте и &НаСервере, а событие обычно используют ПриОткрытии. Расширения конфигурации
обычные формы заимствовать не умеют, так что этот код пишут в самой конфигурации.
Ошибки при программном добавлении кнопки и их отладка
Порядок отладки, который быстро находит причину:
- Поставьте точку останова на первой строке процедуры добавления и откройте форму в режиме отладки (
F5из Конфигуратора). Если остановки нет — код не вызывается, проверьте, назначена ли процедура-обработчик событию формы. - Пройдите код по шагам
F10и послеЭлементы.Добавитьпосмотрите в табло значение переменнойКнопка: свойстваРодитель,ИмяКоманды,Видимость. - Если кнопка есть, но не работает, поставьте точку останова в обработчике. Не останавливается — проверьте строку
Действиеи директиву&НаКлиенте. - Для расширения убедитесь, что оно подключено к базе и активно в списке расширений. После правок расширения базу нужно обновить.
Ищете имя стандартной панели или кнопки, а Конфигуратора под рукой нет? Откройте форму в режиме отладки и раскройте в табло коллекцию Элементы: там видны все имена, включая автоматически созданные.
Частые вопросы
Можно ли удалить программно добавленную кнопку?
Элементы.Удалить(Элемент). Команду удаляют через Команды.Удалить(Команда). Удалять так можно только то, что добавлено кодом; элементы из Конфигуратора можно лишь скрыть.Можно ли добавить кнопку на форму из внешней обработки, не меняя конфигурацию?
Почему кнопку добавляют в ПриСозданииНаСервере, а не в ПриОткрытии?
Команды.Добавить и Элементы.Добавить выполняются на сервере. В ПриСозданииНаСервере форма собирается один раз до показа, без лишнего серверного вызова и мерцания интерфейса.Как задать кнопке горячую клавишу?
СочетаниеКлавиш, ему присваивают Новый СочетаниеКлавиш(Клавиша.F8) с нужной клавишей и модификаторами. Не занимайте сочетания, которые использует платформа.