Кнопка на управляемой форме: как вызвать свою процедуру

· 9 мин

Содержание

Кнопка на управляемой форме сама код не вызывает — между ней и процедурой всегда стоит команда. Кнопка ссылается на команду через свойство «Имя команды», у команды задано «Действие», а Действие указывает на процедуру-обработчик в модуле формы. Нажали кнопку → выполнилась команда → отработал её обработчик.

Привязать можно двумя путями: вручную в Конфигураторе (кнопка + команда рисуются мышью) или программно в коде модуля формы, когда элементы создаются на лету. Ниже — оба способа для платформы 8.3 с интерфейсом «Такси», плюс связка клиент–сервер, командный интерфейс и разбор ситуаций, когда кнопка есть, а реакции нет.

Как кнопка находит свой код: команды и обработчики

В обычных формах 8.2 кнопка напрямую хранила обработчик события «Нажатие». В управляемых формах 8.3 схема другая, и это первое, что путает новичков.

Цепочка такая:

  • 🔘 Кнопка (КнопкаФормы) — визуальный элемент. Своего кода не содержит.
  • ⚙️ Команда формы — объект, который кнопка «нажимает». Хранит заголовок, картинку, подсказку и ссылку на обработчик.
  • 📝 Процедура-обработчик — код в модуле формы с директивой &НаКлиенте и единственным параметром Команда.

Одну команду можно повесить сразу на несколько кнопок (на командной панели и в контекстном меню) — код при этом один. Это и есть смысл разделения: элемент и действие живут отдельно.

Обработчик команды всегда имеет фиксированную сигнатуру:

&НаКлиенте
Процедура ПоказатьИтог(Команда)
    Сообщить("Кнопка нажата");
КонецПроцедуры

Параметр Команда передаёт сам объект команды — он нужен редко, но убирать его из скобок нельзя, иначе платформа не свяжет процедуру с командой.

Привязка кнопки к процедуре в Конфигураторе

Способ для статических кнопок, которые есть на форме всегда. Открываете нужную форму в Конфигураторе и работаете на вкладках редактора формы.

  1. Перейдите на вкладку «Команды» → «Команды формы» и нажмите «Добавить». Задайте имя латиницей без пробелов, например ПоказатьИтог, и заголовок на русском — он будет виден на кнопке.
  2. В палитре свойств команды найдите поле «Действие» и нажмите кнопку с лупой справа. Платформа сама создаст в модуле формы заготовку процедуры &НаКлиенте Процедура ПоказатьИтог(Команда) и перенесёт вас в код.
  3. Напишите внутри процедуры нужную логику.
  4. Вернитесь на вкладку «Элементы», добавьте элемент типа «Кнопка» (перетащите в нужную группу или на командную панель).
  5. В свойствах кнопки в поле «Имя команды» выберите из списка созданную команду ПоказатьИтог.

Пока в свойстве «Имя команды» ничего не выбрано, кнопка будет серой и не нажмётся. Это самая частая причина «кнопка не работает » — забыли связать элемент с командой.

Имя команды и имя процедуры-обработчика — разные вещи. В Конфигураторе их удобно называть одинаково, но технически кнопка знает только про команду, а команда — про процедуру через поле «Действие».

Готовый обработчик, который суммирует табличную часть и кладёт результат в реквизит формы:

&НаКлиенте
Процедура ПоказатьИтог(Команда)
    ПосчитатьИтогНаСервере();
    Сообщить("Итого по документу: " + Формат(ИтогоПоДокументу, "ЧГ=0"));
КонецПроцедуры

Как создать кнопку и обработчик программно

Иногда кнопку нельзя нарисовать заранее: она нужна только при определённых условиях, или вы разрабатываете расширение и не хотите менять основную конфигурацию. Тогда и кнопку, и команду создают кодом.

Ключевое правило: элементы и команды добавляются на сервере, обычно в обработчике ПриСозданииНаСервере. На клиенте коллекции Элементы и Команды для изменения структуры недоступны.

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    // 1. Создаём команду и указываем клиентский обработчик
    НоваяКоманда = Команды.Добавить("ПересчитатьПрограммно");
    НоваяКоманда.Действие = "Подключаемый_Пересчитать";
    НоваяКоманда.Заголовок = "Пересчитать";

    // 2. Создаём кнопку и привязываем её к команде по имени
    НоваяКнопка = Элементы.Добавить("КнопкаПересчитать", Тип("КнопкаФормы"));
    НоваяКнопка.ИмяКоманды = "ПересчитатьПрограммно";

КонецПроцедуры

&НаКлиенте
Процедура Подключаемый_Пересчитать(Команда)
    ПосчитатьИтогНаСервере();
КонецПроцедуры

Разберём, что здесь важно:

  • 📌 Команды.Добавить() возвращает объект команды. Имя в свойстве Действие — это строка с именем процедуры в модуле формы. Имена должны совпадать посимвольно.
  • 📌 Обработчик программной команды обязан быть &НаКлиенте, даже если вся работа идёт на сервере. Из него уже вызывают серверные методы.
  • 📌 Префикс Подключаемый_ — не требование платформы, а общепринятое соглашение для процедур, которые назначаются через Действие. Он сразу отличает их от обычных обработчиков событий.

Если третий параметр Элементы.Добавить() (родитель) не указан, кнопка добавляется в корень формы. Чтобы положить её на конкретную командную панель, передайте элемент-группу третьим аргументом: Элементы.Добавить("КнопкаПересчитать", Тип("КнопкаФормы"), Элементы.МояПанель).

Свойство Заголовок у команды, а не у кнопки, задаёт текст на кнопке. Если оставить кнопку без привязки к команде, подписать её будет нечем.

Кнопки на командной панели и в командном интерфейсе

Кнопку можно разместить не только в теле формы, но и на панелях. Для управляемых форм 8.3 есть несколько мест, и путают их часто.

Командная панель формы. Чтобы кнопки выстроились в ряд наверху, создайте на вкладке «Элементы» группу и задайте ей в свойстве «Вид» значение «Командная панель». Кнопки, вложенные в такую группу, встанут горизонтально с нужными отступами.

Командный интерфейс формы. Отдельная вкладка редактора формы — здесь настраивается видимость и порядок стандартных команд (Записать, Провести, Печать) и ваших команд формы. Сюда же можно вынести команду без ручного создания кнопки — платформа отрисует её сама.

Общие команды. Если кнопка должна появляться в нескольких объектах (например, во всех формах справочника и его списка), создают объект «Общая команда» в дереве конфигурации. У общей команды свой модуль, и обработчик там выглядит иначе:

Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды) Экспорт
    // ПараметрКоманды — ссылка на текущий объект или массив ссылок
КонецПроцедуры

Сравним, когда что выбирать:

Где живёт кнопкаОбработчикКогда использовать
Команда формыв модуле формы, &НаКлиентедействие нужно на одной конкретной форме
Общая командамодуль общей команды, ОбработкаКомандыодно действие для многих объектов
Программнов модуле формы, &НаКлиентекнопка появляется по условию или в расширении

Для общей команды в её свойствах важно правильно задать «Группу команд» и «Тип параметра команды» — иначе кнопка либо не появится в нужном месте, либо будет неактивной, пока не выбран объект.

Клиент и сервер: откуда кнопка вызывает процедуру

Обработчик команды выполняется на клиенте. А большая часть полезной работы — запись объекта, запрос к базе, чтение регистра — делается только на сервере. Поэтому типичный обработчик кнопки устроен как «клиентская обёртка плюс серверный метод».

&НаКлиенте
Процедура ПоказатьИтог(Команда)
    ПосчитатьИтогНаСервере();   // ушли на сервер и вернулись
    Сообщить("Готово");         // снова на клиенте
КонецПроцедуры

&НаСервере
Процедура ПосчитатьИтогНаСервере()
    Сумма = 0;
    Для Каждого Строка Из Товары Цикл
        Сумма = Сумма + Строка.Сумма;
    КонецЦикла;
    ИтогоПоДокументу = Сумма;
КонецПроцедуры

Здесь Товары — табличная часть формы, ИтогоПоДокументу — её реквизит. Процедура &НаСервере видит все данные формы, меняет реквизит, и после возврата на клиент новое значение уже доступно.

Какую директиву ставить серверному методу:

  • &НаСервере — когда нужны данные формы (реквизиты, табличные части). Платформа передаёт на сервер и обратно весь контекст формы, это «дороже».
  • &НаСервереБезКонтекста — когда данные формы не нужны, а всё необходимое передаётся через параметры. Работает быстрее, контекст не гоняется.
&НаКлиенте
Процедура ПроверитьИНН(Команда)
    Результат = ПроверитьИННнаСервере(ИНН);
    Сообщить(Результат);
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПроверитьИННнаСервере(ЗначениеИНН)
    Если СтрДлина(ЗначениеИНН) = 10 Или СтрДлина(ЗначениеИНН) = 12 Тогда
        Возврат "Длина корректна";
    Иначе
        Возврат "Неверная длина ИНН";
    КонецЕсли;
КонецФункции

Нельзя вызвать &НаСервере-процедуру напрямую из команды, сделав обработчик серверным. Обработчик команды всегда &НаКлиенте. Если поставить ему &НаСервере, платформа выдаст ошибку ещё на этапе проверки модуля.

Как обработчик узнаёт о текущих данных формы

Часто кнопка должна работать не со всем документом, а с тем, что пользователь сейчас выделил: с текущей строкой таблицы, с выбранным значением поля. Эти данные обработчик берёт из коллекции Элементы, а не из параметра Команда.

Текущая строка табличной части достаётся так:

&НаКлиенте
Процедура ПоказатьТовар(Команда)
    ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
    Если ТекущаяСтрока = Неопределено Тогда
        Сообщить("Сначала выделите строку в таблице");
        Возврат;
    КонецЕсли;
    Сообщить("Выбрано: " + ТекущаяСтрока.Номенклатура);
КонецПроцедуры

Здесь Товары — имя элемента таблицы на форме. Свойство ТекущиеДанные возвращает строку, по колонкам которой можно обращаться как ТекущаяСтрока.Номенклатура. Если ничего не выделено, вернётся Неопределено — эту проверку делают всегда, иначе при пустой таблице кнопка выдаст ошибку.

Если нужны все отмеченные строки (множественный выбор), используйте Элементы.Товары.ВыделенныеСтроки — коллекцию идентификаторов, по которым достают строки из табличной части.

Значение обычного поля формы (не таблицы) обработчик читает просто по имени реквизита — например, Контрагент или Дата. Специально обращаться к элементу для этого не нужно.

Внешний вид кнопки: обычная, с картинкой, гиперссылка

Одна и та же связка «кнопка → команда» может выглядеть по-разному — это настраивается свойствами кнопки, код при этом не меняется.

  • 🖼 Картинка. Задайте в свойствах команды свойство с картинкой из библиотеки или своё изображение — оно появится на кнопке. На узких панелях удобно оставить только значок, убрав текст.
  • 🔗 Отображение как гиперссылка. У кнопки есть свойство внешнего вида — переключив его, вы получите не прямоугольную кнопку, а ссылку-надпись. Поведение то же: клик вызывает команду.
  • ⌨️ Горячая клавиша. В свойствах команды можно назначить сочетание клавиш, и действие сработает без мыши.

Всё это — косметика поверх той же команды. Логика привязки к процедуре от оформления не зависит.

Почему кнопка не срабатывает: разбор ошибок

Чаще всего проблема не в коде, а в связке «кнопка → команда → обработчик». Пробегитесь по симптомам:

Диагностика: выберите симптом

Ещё пара рабочих приёмов для отладки:

  • 🔎 Поставьте точку останова (клавиша F9) в первой строке обработчика и запустите в режиме отладки. Если отладчик на строке не останавливается — значит, до обработчика управление не доходит, проблема в привязке, а не в коде.
  • 🔎 Проверьте, что форма, которую вы правите, — та же, что открывается в пользовательском режиме. У объекта может быть несколько форм, а основной назначена другая.

После правок в Конфигураторе не забывайте про «Обновить конфигурацию базы данных» (F7). Пока изменения не приняты базой, кнопка в режиме «1С:Предприятие» останется старой.

Короткий чек-лист перед тем, как считать кнопку рабочей:

Проверка привязки кнопки
Выполнено: 0 / 5

Частые вопросы

Можно ли повесить код на событие «Нажатие» кнопки, как в 8.2?
В управляемых формах у кнопки нет события «Нажатие». Весь код идёт через команду и её обработчик. Событие «Нажатие» осталось только у кнопок в обычных (неуправляемых) формах.
Чем команда формы отличается от общей команды?
Команда формы живёт внутри одной формы и её обработчик — в модуле этой формы. Общая команда — отдельный объект конфигурации с собственным модулем, её можно подключить сразу к нескольким объектам и их формам.
Как передать в процедуру дополнительный параметр, кроме `Команда`?
Сигнатуру обработчика менять нельзя — только (Команда). Нужные данные берут из реквизитов формы или передают в серверный метод, который вызывается из обработчика.
Почему обработчик обязательно `&НаКлиенте`?
Нажатие кнопки происходит в интерфейсе, то есть на клиенте. Платформа вызывает обработчик именно там. Серверную логику подключают отдельной процедурой с директивой &НаСервере или &НаСервереБезКонтекста.
Как сделать кнопку видимой только при условии?
Управляйте свойством Элементы.ИмяКнопки.Видимость из кода (на сервере при создании формы или на клиенте по событию), либо привяжите видимость команды к функциональной опции.