Кнопка на управляемой форме: как вызвать свою процедуру
Содержание
Кнопка на управляемой форме сама код не вызывает — между ней и процедурой всегда стоит команда. Кнопка ссылается на команду через свойство «Имя команды», у команды задано «Действие», а Действие указывает на процедуру-обработчик в модуле формы. Нажали кнопку → выполнилась команда → отработал её обработчик.
Привязать можно двумя путями: вручную в Конфигураторе (кнопка + команда рисуются мышью) или программно в коде модуля формы, когда элементы создаются на лету. Ниже — оба способа для платформы 8.3 с интерфейсом «Такси», плюс связка клиент–сервер, командный интерфейс и разбор ситуаций, когда кнопка есть, а реакции нет.
Как кнопка находит свой код: команды и обработчики
В обычных формах 8.2 кнопка напрямую хранила обработчик события «Нажатие». В управляемых формах 8.3 схема другая, и это первое, что путает новичков.
Цепочка такая:
- 🔘 Кнопка (
КнопкаФормы) — визуальный элемент. Своего кода не содержит. - ⚙️ Команда формы — объект, который кнопка «нажимает». Хранит заголовок, картинку, подсказку и ссылку на обработчик.
- 📝 Процедура-обработчик — код в модуле формы с директивой
&НаКлиентеи единственным параметромКоманда.
Одну команду можно повесить сразу на несколько кнопок (на командной панели и в контекстном меню) — код при этом один. Это и есть смысл разделения: элемент и действие живут отдельно.
Обработчик команды всегда имеет фиксированную сигнатуру:
&НаКлиенте
Процедура ПоказатьИтог(Команда)
Сообщить("Кнопка нажата");
КонецПроцедуры
Параметр Команда передаёт сам объект команды — он нужен редко, но убирать его из скобок нельзя, иначе платформа не свяжет процедуру с командой.
Привязка кнопки к процедуре в Конфигураторе
Способ для статических кнопок, которые есть на форме всегда. Открываете нужную форму в Конфигураторе и работаете на вкладках редактора формы.
- Перейдите на вкладку «Команды» → «Команды формы» и нажмите «Добавить». Задайте имя латиницей без пробелов, например
ПоказатьИтог, и заголовок на русском — он будет виден на кнопке. - В палитре свойств команды найдите поле «Действие» и нажмите кнопку с лупой справа. Платформа сама создаст в модуле формы заготовку процедуры
&НаКлиенте Процедура ПоказатьИтог(Команда)и перенесёт вас в код. - Напишите внутри процедуры нужную логику.
- Вернитесь на вкладку «Элементы», добавьте элемент типа «Кнопка» (перетащите в нужную группу или на командную панель).
- В свойствах кнопки в поле «Имя команды» выберите из списка созданную команду
ПоказатьИтог.
Пока в свойстве «Имя команды» ничего не выбрано, кнопка будет серой и не нажмётся. Это самая частая причина «кнопка не работает » — забыли связать элемент с командой.
Имя команды и имя процедуры-обработчика — разные вещи. В Конфигураторе их удобно называть одинаково, но технически кнопка знает только про команду, а команда — про процедуру через поле «Действие».
Готовый обработчик, который суммирует табличную часть и кладёт результат в реквизит формы:
&НаКлиенте
Процедура ПоказатьИтог(Команда)
ПосчитатьИтогНаСервере();
Сообщить("Итого по документу: " + Формат(ИтогоПоДокументу, "ЧГ=0"));
КонецПроцедуры
Как создать кнопку и обработчик программно
Иногда кнопку нельзя нарисовать заранее: она нужна только при определённых условиях, или вы разрабатываете расширение и не хотите менять основную конфигурацию. Тогда и кнопку, и команду создают кодом.
Ключевое правило: элементы и команды добавляются на сервере, обычно в обработчике ПриСозданииНаСервере. На клиенте коллекции Элементы и Команды для изменения структуры недоступны.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// 1. Создаём команду и указываем клиентский обработчик
НоваяКоманда = Команды.Добавить("ПересчитатьПрограммно");
НоваяКоманда.Действие = "Подключаемый_Пересчитать";
НоваяКоманда.Заголовок = "Пересчитать";
// 2. Создаём кнопку и привязываем её к команде по имени
НоваяКнопка = Элементы.Добавить("КнопкаПересчитать", Тип("КнопкаФормы"));
НоваяКнопка.ИмяКоманды = "ПересчитатьПрограммно";
КонецПроцедуры
&НаКлиенте
Процедура Подключаемый_Пересчитать(Команда)
ПосчитатьИтогНаСервере();
КонецПроцедуры
Разберём, что здесь важно:
- 📌
Команды.Добавить()возвращает объект команды. Имя в свойствеДействие— это строка с именем процедуры в модуле формы. Имена должны совпадать посимвольно. - 📌 Обработчик программной команды обязан быть
&НаКлиенте, даже если вся работа идёт на сервере. Из него уже вызывают серверные методы. - 📌 Префикс
Подключаемый_— не требование платформы, а общепринятое соглашение для процедур, которые назначаются черезДействие. Он сразу отличает их от обычных обработчиков событий.
Если третий параметр Элементы.Добавить() (родитель) не указан, кнопка добавляется в корень формы. Чтобы положить её на конкретную командную панель, передайте элемент-группу третьим аргументом: Элементы.Добавить("КнопкаПересчитать", Тип("КнопкаФормы"), Элементы.МояПанель).
Свойство Заголовок у команды, а не у кнопки, задаёт текст на кнопке. Если оставить кнопку без привязки к команде, подписать её будет нечем.
Кнопки на командной панели и в командном интерфейсе
Кнопку можно разместить не только в теле формы, но и на панелях. Для управляемых форм 8.3 есть несколько мест, и путают их часто.
Командная панель формы. Чтобы кнопки выстроились в ряд наверху, создайте на вкладке «Элементы» группу и задайте ей в свойстве «Вид» значение «Командная панель». Кнопки, вложенные в такую группу, встанут горизонтально с нужными отступами.
Командный интерфейс формы. Отдельная вкладка редактора формы — здесь настраивается видимость и порядок стандартных команд (Записать, Провести, Печать) и ваших команд формы. Сюда же можно вынести команду без ручного создания кнопки — платформа отрисует её сама.
Общие команды. Если кнопка должна появляться в нескольких объектах (например, во всех формах справочника и его списка), создают объект «Общая команда» в дереве конфигурации. У общей команды свой модуль, и обработчик там выглядит иначе:
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды) Экспорт
// ПараметрКоманды — ссылка на текущий объект или массив ссылок
КонецПроцедуры
Сравним, когда что выбирать:
| Где живёт кнопка | Обработчик | Когда использовать |
|---|---|---|
| Команда формы | в модуле формы, &НаКлиенте | действие нужно на одной конкретной форме |
| Общая команда | модуль общей команды, ОбработкаКоманды | одно действие для многих объектов |
| Программно | в модуле формы, &НаКлиенте | кнопка появляется по условию или в расширении |
Для общей команды в её свойствах важно правильно задать «Группу команд» и «Тип параметра команды» — иначе кнопка либо не появится в нужном месте, либо будет неактивной, пока не выбран объект.
Клиент и сервер: откуда кнопка вызывает процедуру
Обработчик команды выполняется на клиенте. А большая часть полезной работы — запись объекта, запрос к базе, чтение регистра — делается только на сервере. Поэтому типичный обработчик кнопки устроен как «клиентская обёртка плюс серверный метод».
&НаКлиенте
Процедура ПоказатьИтог(Команда)
ПосчитатьИтогНаСервере(); // ушли на сервер и вернулись
Сообщить("Готово"); // снова на клиенте
КонецПроцедуры
&НаСервере
Процедура ПосчитатьИтогНаСервере()
Сумма = 0;
Для Каждого Строка Из Товары Цикл
Сумма = Сумма + Строка.Сумма;
КонецЦикла;
ИтогоПоДокументу = Сумма;
КонецПроцедуры
Здесь Товары — табличная часть формы, ИтогоПоДокументу — её реквизит. Процедура &НаСервере видит все данные формы, меняет реквизит, и после возврата на клиент новое значение уже доступно.
Какую директиву ставить серверному методу:
&НаСервере— когда нужны данные формы (реквизиты, табличные части). Платформа передаёт на сервер и обратно весь контекст формы, это «дороже».&НаСервереБезКонтекста— когда данные формы не нужны, а всё необходимое передаётся через параметры. Работает быстрее, контекст не гоняется.
&НаКлиенте
Процедура ПроверитьИНН(Команда)
Результат = ПроверитьИННнаСервере(ИНН);
Сообщить(Результат);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПроверитьИННнаСервере(ЗначениеИНН)
Если СтрДлина(ЗначениеИНН) = 10 Или СтрДлина(ЗначениеИНН) = 12 Тогда
Возврат "Длина корректна";
Иначе
Возврат "Неверная длина ИНН";
КонецЕсли;
КонецФункции
Нельзя вызвать &НаСервере-процедуру напрямую из команды, сделав обработчик серверным. Обработчик команды всегда &НаКлиенте. Если поставить ему &НаСервере, платформа выдаст ошибку ещё на этапе проверки модуля.
Как обработчик узнаёт о текущих данных формы
Часто кнопка должна работать не со всем документом, а с тем, что пользователь сейчас выделил: с текущей строкой таблицы, с выбранным значением поля. Эти данные обработчик берёт из коллекции Элементы, а не из параметра Команда.
Текущая строка табличной части достаётся так:
&НаКлиенте
Процедура ПоказатьТовар(Команда)
ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
Если ТекущаяСтрока = Неопределено Тогда
Сообщить("Сначала выделите строку в таблице");
Возврат;
КонецЕсли;
Сообщить("Выбрано: " + ТекущаяСтрока.Номенклатура);
КонецПроцедуры
Здесь Товары — имя элемента таблицы на форме. Свойство ТекущиеДанные возвращает строку, по колонкам которой можно обращаться как ТекущаяСтрока.Номенклатура. Если ничего не выделено, вернётся Неопределено — эту проверку делают всегда, иначе при пустой таблице кнопка выдаст ошибку.
Если нужны все отмеченные строки (множественный выбор), используйте Элементы.Товары.ВыделенныеСтроки — коллекцию идентификаторов, по которым достают строки из табличной части.
Значение обычного поля формы (не таблицы) обработчик читает просто по имени реквизита — например, Контрагент или Дата. Специально обращаться к элементу для этого не нужно.
Внешний вид кнопки: обычная, с картинкой, гиперссылка
Одна и та же связка «кнопка → команда» может выглядеть по-разному — это настраивается свойствами кнопки, код при этом не меняется.
- 🖼 Картинка. Задайте в свойствах команды свойство с картинкой из библиотеки или своё изображение — оно появится на кнопке. На узких панелях удобно оставить только значок, убрав текст.
- 🔗 Отображение как гиперссылка. У кнопки есть свойство внешнего вида — переключив его, вы получите не прямоугольную кнопку, а ссылку-надпись. Поведение то же: клик вызывает команду.
- ⌨️ Горячая клавиша. В свойствах команды можно назначить сочетание клавиш, и действие сработает без мыши.
Всё это — косметика поверх той же команды. Логика привязки к процедуре от оформления не зависит.
Почему кнопка не срабатывает: разбор ошибок
Чаще всего проблема не в коде, а в связке «кнопка → команда → обработчик». Пробегитесь по симптомам:
&НаСервере. Верните ему &НаКлиенте, а серверную работу вынесите в отдельную процедуру.ПриСозданииНаСервере.Ещё пара рабочих приёмов для отладки:
- 🔎 Поставьте точку останова (клавиша
F9) в первой строке обработчика и запустите в режиме отладки. Если отладчик на строке не останавливается — значит, до обработчика управление не доходит, проблема в привязке, а не в коде. - 🔎 Проверьте, что форма, которую вы правите, — та же, что открывается в пользовательском режиме. У объекта может быть несколько форм, а основной назначена другая.
После правок в Конфигураторе не забывайте про «Обновить конфигурацию базы данных» (F7). Пока изменения не приняты базой, кнопка в режиме «1С:Предприятие» останется старой.
Короткий чек-лист перед тем, как считать кнопку рабочей:
Частые вопросы
Можно ли повесить код на событие «Нажатие» кнопки, как в 8.2?
Чем команда формы отличается от общей команды?
Как передать в процедуру дополнительный параметр, кроме `Команда`?
(Команда). Нужные данные берут из реквизитов формы или передают в серверный метод, который вызывается из обработчика.Почему обработчик обязательно `&НаКлиенте`?
&НаСервере или &НаСервереБезКонтекста.Как сделать кнопку видимой только при условии?
Элементы.ИмяКнопки.Видимость из кода (на сервере при создании формы или на клиенте по событию), либо привяжите видимость команды к функциональной опции.