Своя кнопка на управляемой форме: команда, размещение, обработчик

· 9 мин

Содержание

Кнопка в управляемой форме 1С не живёт сама по себе. Её нельзя «нарисовать» и повесить код на нажатие. Сначала создаётся команда, потом кнопка, которая на эту команду ссылается. Программист, который пытается сразу писать обработчик у кнопки, ищет событие там, где его нет.

Ниже — полный путь для платформы 8.3 с интерфейсом «Такси»: от пустого места на форме до кнопки, которая выполняет код, скрывается и блокируется по условию. Всё делается в конфигураторе, в режиме разработки конфигурации или расширения.

Как устроена кнопка: команда и элемент формы

Здесь два разных объекта, и путаница между ними — источник половины вопросов.

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

Одну команду можно повесить на несколько кнопок: например, в командной панели и в контекстном меню таблицы. Код при этом один.

Что нужноКуда смотреть
Создать действиеЗакладка «Команды» в редакторе формы
Показать действие на формеЗакладка «Элементы», кнопка добавления
Написать кодМодуль формы, процедура с директивой &НаКлиенте
Скрыть или заблокироватьСвойства кнопки или код через Элементы

Бывают ещё стандартные команды формы — «Записать», «Провести», «Закрыть». Они уже есть в списке команд, и обработчик им писать не нужно. Для своей кнопки нужна своя команда.

Подготовка: создаём команду в конфигураторе

Откройте форму объекта (документа, справочника, обработки) в конфигураторе двойным щелчком по её имени в дереве конфигурации. В редакторе формы внизу или сбоку есть закладки. Нужна закладка «Команды».

  1. Нажмите кнопку «Добавить» над списком команд.
  2. В палитре свойств задайте имя — латиницей или кириллицей без пробелов, например ПересчитатьИтоги.
  3. Заполните заголовок — то, что увидит пользователь: «Пересчитать итоги». Пробелы здесь можно.
  4. В поле «Действие» нажмите лупу и создайте обработчик. Конфигуратор сам добавит процедуру в модуль формы и откроет её.

Платформа создаст заготовку:

&НаКлиенте
Процедура ПересчитатьИтоги(Команда)
	// сюда пишем код
КонецПроцедуры

Имя процедуры совпадает с именем команды, если вы не указали другое. Менять имя процедуры вручную в модуле не стоит: связь идёт по строке в свойстве «Действие», и после переименования в одном месте второе придётся править руками.

Заодно можно задать картинку команды и подсказку — она показывается при наведении курсора. Для кнопки, которая меняет данные, подсказка не лишняя: пользователь заранее видит, что произойдёт.

Размещаем кнопку на форме: куда и как

Теперь перейдите на закладку «Элементы». Это дерево всего, что есть на форме: поля, группы, таблицы, командные панели.

Самый быстрый способ — перетащить команду из закладки «Команды» мышью в нужное место дерева «Элементы». Платформа создаст кнопку с этой командой и заголовком из команды.

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

Куда поставить

Выбор места зависит от того, что кнопка делает.

  • Командная панель формы. Подходит для действий над всем объектом: заполнить, пересчитать, отправить. Это группа «Командная панель» в верхней части дерева элементов.
  • Командная панель таблицы. Для действий над строками: «Заполнить по остаткам», «Удалить дубли ». Кнопку кладут внутрь элемента командной панели у самой табличной части.
  • Свободное место формы. Кнопка в обычной группе, рядом с полями. Так делают для «разовых» действий, которые привязаны к конкретному полю: «Рассчитать» рядом с суммой.

Чтобы кнопка не уехала в произвольный угол, заведите группу (обычную группу или группу-командную панель) и задайте у неё нужное расположение. Тогда внутри можно выровнять несколько кнопок разом.

Порядок кнопок внутри группы совпадает с порядком в дереве. Двигайте их стрелками «Вверх» и «Вниз» над деревом элементов, пока главное действие не окажется первым слева. Пользователь привыкает к расположению за пару дней, и перестановка уже работающей кнопки вызывает больше вопросов, чем сама новая функция.

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

Вид кнопки

В свойстве «Вид» кнопки выбирается её внешность:

  • обычная кнопка с рамкой — заметна, для главного действия;
  • гиперссылка — для второстепенных действий внутри формы;
  • кнопка командной панели — плоская, выглядит как остальные команды панели.

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

Главное действие на форме лучше делать одним. Если на экране три яркие кнопки, пользователь не понимает, какую нажимать первой.

Пишем обработчик нажатия: клиент и сервер

Код команды выполняется на клиенте. Это важно: на клиенте нет прямого доступа к базе. Запросы, чтение и запись объектов — только на сервере.

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

&НаКлиенте
Процедура ПересчитатьИтоги(Команда)
	Если Объект.Товары.Количество() = 0 Тогда
		ПоказатьПредупреждение(, "Таблица товаров пуста.");
		Возврат;
	КонецЕсли;
	ПересчитатьИтогиНаСервере();
	ПоказатьОповещениеПользователя("Итоги пересчитаны");
КонецПроцедуры

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

В примере у документа предполагаются табличная часть Товары с реквизитами Количество, Цена, Сумма и реквизит СуммаДокумента. Подставьте свои имена.

Сначала проверка на клиенте: если таблица пуста, на сервер ходить незачем. Каждый вызов сервера — это сетевой запрос, и лишние вызовы замедляют форму.

Вопрос перед опасным действием

Если кнопка удаляет или перезаписывает данные, спросите пользователя. В управляемых формах диалоги не блокируют код, поэтому ответ приходит в отдельную процедуру:

&НаКлиенте
Процедура ОчиститьТаблицу(Команда)
	Оповещение = Новый ОписаниеОповещения("ПослеВопросаОчистки", ЭтотОбъект);
	ПоказатьВопрос(Оповещение, "Очистить таблицу товаров?", РежимДиалогаВопрос.ДаНет);
КонецПроцедуры

&НаКлиенте
Процедура ПослеВопросаОчистки(Результат, ДополнительныеПараметры) Экспорт
	Если Результат = КодВозвратаДиалога.Да Тогда
		Объект.Товары.Очистить();
	КонецЕсли;
КонецПроцедуры

Код после ПоказатьВопрос выполнится сразу, не дожидаясь ответа. Всё, что должно произойти после «Да», — только внутри процедуры оповещения.

Процедура оповещения должна быть доступна из формы: в примере она описана в том же модуле. Если оставить её без директивы &НаКлиенте, платформа её не найдёт.

Передача параметров и работа с данными

Бывает, что кнопке нужно что-то узнать: какая строка выделена, что введено в поле, какой документ открыт.

Текущая строка таблицы. У элемента таблицы есть свойство ТекущиеДанные. Оно пустое, если строка не выбрана, — проверяйте:

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

Число к строке прибавляется через Формат или СтрШаблон. Прямая склейка числа и текста даст ошибку или не тот вид числа.

Данные на сервер. Серверной процедуре параметры передают обычным списком. Объекты формы (Объект, реквизиты) на сервере доступны сами, их передавать не надо. А вот значения, посчитанные на клиенте, — только параметрами.

ЗаполнитьНаСервере(Элементы.Товары.ТекущаяСтрока);

Открыть другую форму с параметрами. Часто кнопка открывает форму подбора или настройки. Параметры передаются структурой:

&НаКлиенте
Процедура Настроить(Команда)
	Параметры = Новый Структура("РежимРаботы", "Расширенный");
	ОткрытьФорму("Обработка.Настройка.Форма.ФормаНастроек", Параметры, ЭтотОбъект);
КонецПроцедуры

Во вторую форму значение приходит через Параметры.РежимРаботы в обработчике ПриСозданииНаСервере. Имя формы в первом аргументе подставьте своё: его видно в дереве конфигурации.

После изменения данных на сервере формы-«соседи» сами не обновятся. Если кнопка меняет справочник, который открыт в списке, вызовите ОповеститьОбИзменении(Тип("СправочникСсылка.Номенклатура")) — подставьте нужный тип.

Видимость и доступность: показываем кнопку по условию

Два свойства решают почти всё:

  • Видимость — кнопки нет на форме вообще;
  • Доступность — кнопка есть, но серая и не нажимается.

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

Статически это настраивается галочками в свойствах кнопки. Динамически — из кода, через коллекцию Элементы:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	Элементы.КнопкаПересчитать.Видимость = ПравоДоступа("Изменение", Метаданные.Документы.РасходнаяНакладная);
КонецПроцедуры

&НаКлиенте
Процедура ПриИзмененииТовары()
	Элементы.КнопкаПересчитать.Доступность = Объект.Товары.Количество() > 0;
КонецПроцедуры

КнопкаПересчитать здесь — имя элемента формы, а не команды. Оно видно в дереве «Элементы» и в свойствах кнопки. Имя документа в Метаданные.Документы тоже замените своим.

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

Событие ПриИзмененииТовары в примере условное. Реальное событие таблицы выбирают в палитре её свойств: событие с При, которое срабатывает при окончании редактирования строки.

Кнопка, созданная программно

Иногда набор кнопок заранее неизвестен, например, по одной на каждый склад. Тогда их создают в коде при открытии формы:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	Команда = Команды.Добавить("НоваяКоманда");
	Команда.Заголовок = "Выполнить";
	Команда.Действие = "ВыполнитьДинамически";

	Кнопка = Элементы.Добавить("НоваяКнопка", Тип("КнопкаФормы"), Элементы.ГруппаКоманд);
	Кнопка.ИмяКоманды = "НоваяКоманда";
КонецПроцедуры

&НаКлиенте
Процедура ВыполнитьДинамически(Команда)
	ПоказатьПредупреждение(, "Команда выполнена.");
КонецПроцедуры

Группа ГруппаКоманд должна быть создана на форме заранее. Процедура из свойства «Действие» обязательно описывается в модуле формы вручную: автоматически, как в конфигураторе, она не появится.

Типичные ошибки и как их найти

Если после правок что-то не работает , проверьте по списку, начиная с самого вероятного.

  • 🔴 Нажатие ничего не делает. Откройте свойства команды: поле «Действие» пустое или содержит имя процедуры, которой в модуле нет. Платформа молча ничего не вызывает.
  • 🔴 Ошибка при обращении к базе на клиенте. Запрос или чтение объекта оказались в процедуре с &НаКлиенте. Вынесите их в процедуру с &НаСервере и вызовите из клиентской.
  • 🔴 Изменения реквизитов пропали. Серверная процедура поменяла данные, но форма их не перерисовала, потому что работала через &НаСервереБезКонтекста. Такая процедура не видит Объект и реквизиты формы. Нужен обычный &НаСервере.
  • 🔴 Кнопки нет на форме. Проверьте видимость самой кнопки и группы, в которую она вложена. Скрытая группа скрывает всё внутри.
  • 🔴 Кнопка не нажимается. Смотрите «Доступность» и пользовательские настройки формы: пользователь мог убрать кнопку через «Настройки формы» — это не ошибка кода.

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

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

Перед сдачей кнопки в работу
Выполнено: 0 / 5

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

Можно ли добавить кнопку в типовой документ без изменения конфигурации?
Через расширение конфигурации — да: типовая форма заимствуется, в ней создаются команда и кнопка. Основная конфигурация при этом не меняется.
Чем отличается «Действие» команды от события кнопки?
У кнопки нет собственного события нажатия. Действие хранится в команде, а кнопка лишь вызывает команду по имени.
Как сделать горячую клавишу для кнопки?
В свойствах команды есть поле «Сочетание клавиш». Задайте комбинацию, и она будет вызывать то же действие, что и нажатие.
Почему кнопка серая, хотя доступность в коде не меняется?
Часто причина в стандартных свойствах команды: она может быть недоступна для режима «Только просмотр» или пока объект не записан. Проверьте свойства команды и режим формы.
Можно ли вызвать одну команду из нескольких мест?
Да. Перетащите ту же команду на другую группу или в командную панель таблицы. Появится вторая кнопка, а код останется в единственной процедуре.