Контекстное меню в управляемой форме 1С: добавляем свою команду
Содержание
Чтобы сделать контекстное меню в 1С, нужны три вещи: команда формы, обработчик этой команды и кнопка с привязкой к команде внутри группы «Контекстное меню» нужного элемента. Всё это делается в конфигураторе, в редакторе управляемой формы 1С 8.3. Пункт можно добавить и программно, из ПриСозданииНаСервере.
Типичная задача: в списке документов пользователь хочет по правому клику выполнить своё действие над выбранной строкой или над несколькими строками сразу. Сначала разберём, что из чего состоит, потом пройдём весь путь от создания команды до отладки.
Из чего состоит контекстное меню формы
У таблицы, поля ввода и других элементов управляемой формы есть собственное контекстное меню. В редакторе формы оно отображается как дочерний элемент с именем вида СписокКонтекстноеМеню. Платформа сама кладёт туда стандартные пункты: копировать, найти, настроить список.
Пункт меню в управляемой форме — это не самостоятельный объект. Это кнопка, которая ссылается на команду:
| Объект | Что делает | Где живёт |
|---|---|---|
| Команда формы | Хранит заголовок, картинку, имя процедуры-обработчика | Закладка «Команды» редактора формы |
| Кнопка формы | Показывает команду в меню или на панели | Дерево элементов формы |
| Обработчик | Процедура с кодом на клиенте или сервере | Модуль формы |
Одну команду можно повесить на несколько кнопок: в контекстное меню таблицы, в командную панель и в подменю «Ещё». Код при этом пишется один раз.
Отдельно существуют команды командного интерфейса: они выводятся в панели разделов и навигации и открывают формы или отчёты. Для пункта «правой кнопки» они не нужны, речь здесь только о командах формы.
Создаём новую команду формы
- Откройте форму в конфигураторе (список, форму документа или любую другую управляемую форму).
- Перейдите на закладку «Команды» и нажмите «Добавить».
- В палитре свойств задайте имя без пробелов, например
ОтметитьПроверенным. - В свойстве «Заголовок» напишите текст, который увидит пользователь: «Отметить проверенным».
- В свойстве «Действие» нажмите лупу и выберите «Создать на клиенте». Платформа сама создаст процедуру в модуле формы.
После этого перетащите команду из закладки «Команды» в дерево элементов, на группу контекстного меню таблицы. Другой путь: выделите СписокКонтекстноеМеню, нажмите «Добавить» и выберите «Кнопка», затем в свойстве «Имя команды» укажите созданную команду.
Если в дереве элементов нет группы контекстного меню, включите отображение служебных элементов в настройках дерева. Для таблицы формы группа создаётся автоматически и скрыта до первого обращения.
Дополнительные свойства команды, которые стоит заполнить сразу:
- ✅ «Картинка» — значок рядом с текстом пункта;
- ✅ «Подсказка» — всплывающий текст при наведении;
- ✅ «Сочетание клавиш» — быстрый вызов без мыши;
- ✅ «Функциональные опции» — команда доступна, только если включена нужная опция.
Как запрограммировать обработчик команды
Платформа создаёт заготовку, в которую нужно вписать логику. Самый простой вариант — обработчик на клиенте:
&НаКлиенте
Процедура ОтметитьПроверенным(Команда)
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
Сообщить("Выбрана строка: " + ТекущиеДанные.Номер);
КонецПроцедуры
Проверка на Неопределено обязательна. Если список пуст или курсор стоит на строке группировки, ТекущиеДанные вернёт Неопределено, и без проверки получите ошибку при обращении к полю.
Через ТекущиеДанные доступны только те колонки, которые есть в списке на форме. Нужен реквизит, которого в списке нет, — добавьте колонку в динамический список и скройте её на форме либо получите значение через серверный вызов по ссылке.
Когда нужен серверный вызов
Изменить данные в базе из клиентской процедуры нельзя. Схема всегда одна: клиентский обработчик собирает параметры и вызывает серверную процедуру.
&НаКлиенте
Процедура ОтметитьПроверенным(Команда)
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
ОтметитьПровереннымНаСервере(ТекущиеДанные.Ссылка);
Элементы.Список.Обновить();
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ОтметитьПровереннымНаСервере(Ссылка)
Объект = Ссылка.ПолучитьОбъект();
Объект.Комментарий = "Проверено";
Объект.Записать();
КонецПроцедуры
Директива &НаСервереБезКонтекста не передаёт на сервер реквизиты формы, поэтому вызов быстрее. Если серверной процедуре нужны данные формы, используйте &НаСервере.
Поле Ссылка в ТекущиеДанные есть только у списков, где эта колонка выбрана в динамическом списке. У документов и справочников она подключается по умолчанию, у регистров — нет: там используйте ключ записи.
Работа со списками и множественным выделением
Пользователь часто выделяет несколько строк через Ctrl или Shift и ждёт, что команда сработает для всех. ТекущиеДанные в этом случае вернёт только строку под курсором, поэтому для массовых операций нужно другое свойство — ВыделенныеСтроки.
&НаКлиенте
Процедура ОтметитьПроверенным(Команда)
Выделенные = Элементы.Список.ВыделенныеСтроки;
Если Выделенные.Количество() = 0 Тогда
Возврат;
КонецЕсли;
МассивСсылок = Новый Массив;
Для Каждого Элемент Из Выделенные Цикл
МассивСсылок.Добавить(Элемент);
КонецЦикла;
ОтметитьПровереннымНаСервере(МассивСсылок);
Элементы.Список.Обновить();
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ОтметитьПровереннымНаСервере(МассивСсылок)
Для Каждого Ссылка Из МассивСсылок Цикл
Объект = Ссылка.ПолучитьОбъект();
Объект.Комментарий = "Проверено";
Объект.Записать();
КонецЦикла;
КонецПроцедуры
Что важно знать про ВыделенныеСтроки:
- 📌 в динамическом списке справочника или документа в массиве лежат ссылки;
- 📌 в списке регистра сведений вместо ссылок будут ключи записей;
- 📌 если пользователь выделил строку группировки, в массив попадёт и она — отфильтруйте такие элементы, если команда для них не имеет смысла;
- 📌 в обычной таблице формы (табличная часть, таблица значений) в массиве лежат идентификаторы строк, и строку получают методом
НайтиПоИдентификатору()коллекции.
Если за раз обрабатываются сотни документов, записывайте их в транзакции и сообщайте пользователю итог одной строкой, а не сотней сообщений.
Видимость и доступность пунктов меню
Кнопку, привязанную к команде, можно скрыть или сделать серой. Это управляется двумя свойствами элемента: Видимость и Доступность.
Из чего выбирать:
| Нужно | Свойство | Эффект для пользователя |
|---|---|---|
| Пункт вообще не должен показываться | Видимость = Ложь | Строки в меню нет |
| Пункт виден, но сейчас недоступен | Доступность = Ложь | Серый, не нажимается |
| Пункт нужен только части ролей | Права на объект или проверка роли | Остальные его не видят |
Чаще всего доступность зависит от выбранной строки. Например, команда «Провести» нужна только для непроведённых документов. Подпишитесь на событие таблицы «При активизации строки» и обновляйте кнопку там:
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Элементы.СписокКонтекстноеМенюОтметить.Доступность =
ТекущиеДанные <> Неопределено И Не ТекущиеДанные.Проведен;
КонецПроцедуры
Имя СписокКонтекстноеМенюОтметить здесь условное: это имя вашей кнопки в дереве элементов. Подставьте своё.
Событие «При активизации строки» срабатывает очень часто, при каждом шаге курсора. Не вызывайте внутри него сервер и не делайте тяжёлых вычислений. Если без сервера не обойтись, подключайте обработчик ожидания через ПодключитьОбработчикОжидания с небольшой паузой.
Для условий по ролям и правам проверку выполняют на сервере в ПриСозданииНаСервере и сразу выставляют видимость один раз при открытии формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Элементы.СписокКонтекстноеМенюОтметить.Видимость = РольДоступна("ПолныеПрава");
КонецПроцедуры
Для прикладных ограничений подставьте роль из своей конфигурации. Если пункт меняет данные, главную защиту всё равно задают права на объект: скрытая кнопка доступ не закрывает.
Добавляем пункт меню программно
Если форма типовая и менять её в конфигураторе нежелательно (поставщик обновляет конфигурацию), пункт добавляют из кода, в расширении или в обработчике ПриСозданииНаСервере. Порядок такой: создать команду, создать кнопку в группе меню, связать их.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Команда = Команды.Добавить("ОтметитьПроверенным");
Команда.Заголовок = "Отметить проверенным";
Команда.Действие = "ОтметитьПроверенным";
Кнопка = Элементы.Добавить("КнопкаОтметитьПроверенным",
Тип("КнопкаФормы"), Элементы.СписокКонтекстноеМеню);
Кнопка.ИмяКоманды = "ОтметитьПроверенным";
КонецПроцедуры
Три момента, на которых спотыкаются чаще всего:
- Процедура с именем из
Команда.Действиедолжна существовать в модуле формы и иметь директиву&НаКлиенте. Иначе команда добавится, а при нажатии будет ошибка. - Имя кнопки и имя команды не обязаны совпадать, но каждое имя в своей области должно быть уникальным.
- Группа
Элементы.СписокКонтекстноеМенюсуществует, если у таблицы включено контекстное меню. Проверьте имя таблицы: у вас она может называться неСписок.
В расширении конфигурации тот же код ставят в процедуру с директивой &После("ПриСозданииНаСервере"). Расширения доступны начиная с платформы 8.3.6, а изменённая форма попадёт в базу после загрузки расширения и обновления конфигурации базы данных.
Куда ставить пункт и как не загромоздить меню
Контекстное меню читают на ходу, поэтому порядок и состав важны.
- 🔹 Самое частое действие ставьте первым, редкие уводите в подменю.
- 🔹 Заголовок начинайте с глагола: «Отметить проверенным», «Скопировать номер». Название вроде «Проверка» не говорит, что произойдёт.
- 🔹 Не дублируйте стандартные пункты платформы: копирование, поиск, настройку списка пользователь и так найдёт.
- 🔹 Если действие опасное (удаление, массовое изменение), запрашивайте подтверждение через
ПоказатьВопросилиОповещениес описанием обработчика, иначе клик по ошибке изменит сотни записей.
Вопрос с подтверждением на клиенте асинхронный: код, который идёт после вызова, не ждёт ответа. Само действие нужно выполнять в процедуре-обработчике закрытия вопроса, а не следующей строкой.
&НаКлиенте
Процедура ОтметитьПроверенным(Команда)
Оповещение = Новый ОписаниеОповещения("ОтметитьПроверенными_Продолжение", ЭтотОбъект);
ПоказатьВопрос(Оповещение, "Отметить выделенные строки проверенными?", РежимДиалогаВопрос.ДаНет);
КонецПроцедуры
&НаКлиенте
Процедура ОтметитьПроверенными_Продолжение(Результат, ДополнительныеПараметры) Экспорт
Если Результат <> КодВозвратаДиалога.Да Тогда
Возврат;
КонецЕсли;
// здесь — сбор выделенных строк и серверный вызов
КонецПроцедуры
Обычные формы: чем отличается
В старых конфигурациях ещё встречаются обычные формы. Там контекстное меню строят иначе: у элемента управления есть свойство с действиями контекстного меню, а его пункты привязаны к процедурам модуля формы, а не к командам. Для новой разработки на 8.3 выбирайте управляемые формы — они работают и в тонком клиенте, и в веб-клиенте, а обычные формы в веб-клиенте не открываются.
Отладка и проверка контекстного меню
Контекстное меню отлаживается как любой другой клиентский код. Сначала убедитесь, что пункт вообще появился.
Порядок проверки:
- Сохраните конфигурацию и запустите «Отладка → Начать отладку» (
F5). Для клиентского кода используйте тонкий или веб-клиент, как у реальных пользователей. - Откройте форму, нажмите правую кнопку на строке списка. Пункта нет — проверьте, что кнопка стоит именно в группе контекстного меню этой таблицы, а не в командной панели формы.
- Пункт есть, но серый — смотрите свойство
Доступностьи обработчик «При активизации строки». - Поставьте точку останова (
F9) на первой строке обработчика команды и нажмите пункт. Если останов не сработал, в свойстве «Действие» указана не та процедура либо команда не привязана к кнопке. - На останове откройте «Вычислить выражение» (
Shift+F9) и посмотритеЭлементы.Список.ТекущиеДанныеиЭлементы.Список.ВыделенныеСтроки.
Если форма вообще не открывается после правки, ошибка почти всегда в ПриСозданииНаСервере: обращение к несуществующему элементу или команде. Платформа выдаст точное имя в тексте исключения.