Разработка и Конфигурация · 12 мин
Как программно добавить команду в контекстное меню 1С
Пошаговое руководство: как программно добавить команду в контекстное меню формы и таблицы 1С 8.3, настроить видимость по условию, обработчик и типовые ошибки.
Контекстное меню в 1С — это выпадающий список команд, который появляется по правому клику мыши на элементе формы: таблице, поле, динамическом списке. Стандартные пункты вроде «Копировать», «Изменить», «Установить пометку удаления» платформа формирует сама, но разработчик может добавить туда собственные команды — например, «Печать акта», «Создать на основании» или «Показать связанные документы».
Существует два пути: декларативный — через дерево команд формы в конфигураторе, и программный — через коллекции Элементы и Команды в модуле формы. Программный способ нужен, когда состав меню зависит от роли пользователя, режима работы или данных объекта и не может быть жёстко задан на этапе разработки формы.
Ниже разобран полный цикл: создание команды формы, добавление кнопки в контекстное меню таблицы, назначение обработчика, управление видимостью и проверка результата. Примеры приведены для управляемых форм платформы 1С:Предприятие 8.3 — в обычных формах механика другая и рассматривается отдельно.
Когда нужен программный способ, а когда достаточно конфигуратора
Если команда должна присутствовать в меню всегда и для всех пользователей, правильнее добавить её декларативно: в редакторе формы создать команду на вкладке «Команды» и перетащить её в ветку «Контекстное меню» нужной таблицы. Такой вариант проще сопровождать, он виден при визуальном просмотре формы и не требует кода.
Программное добавление оправдано в трёх ситуациях. Первая — состав меню зависит от прав: например, пункт «Провести без контроля» должен видеть только администратор. Вторая — команда появляется по условию на данные: пункт «Открыть договор» имеет смысл, только если в строке заполнено поле «Договор». Третья — форма создаётся динамически (обработки с произвольным интерфейсом), и заранее описать меню невозможно.
Как выбрать способ
Шаг 1. Создание команды формы программно
Любая кнопка контекстного меню ссылается на команду формы, поэтому сначала команда создаётся в коллекции Команды. Код размещается в обработчике ПриСозданииНаСервере — на этом этапе форма уже существует на сервере, но ещё не показана пользователю, и состав элементов можно менять свободно.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
НоваяКоманда = Команды.Добавить("ПоказатьСвязанныеДокументы");
НоваяКоманда.Действие = "Подключаемый_ПоказатьСвязанныеДокументы";
НоваяКоманда.Заголовок = НСтр("ru = 'Связанные документы'");
НоваяКоманда.Подсказка = НСтр("ru = 'Показать документы, связанные с текущей строкой'");
НоваяКоманда.Отображение = ОтображениеКнопки.Надпись;
НоваяКоманда.Картинка = БиблиотекаКартинок.НайтиВСодержании;
КонецПроцедуры
Обратите внимание на свойство Действие: в него записывается строка — имя процедуры-обработчика в модуле формы. Сама процедура должна существовать и иметь директиву компиляции &НаКлиенте, если она обращается к клиентскому контексту (открытие форм, оповещения). Если действие указано, а процедуры нет, при нажатии на пункт меню пользователь получит ошибку «Процедура или функция с указанным именем не определена».
Шаг 2. Добавление кнопки в контекстное меню элемента
Команда сама по себе не отображается — нужен элемент формы типа «Кнопка», помещённый в контекстное меню. У каждого элемента формы, поддерживающего меню (таблица, поле), есть коллекция КонтекстноеМеню, в которую кнопка и добавляется.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// ... создание команды (см. шаг 1) ...
МенюТаблицы = Элементы.СписокТоваров.КонтекстноеМеню;
КнопкаМеню = Элементы.Добавить("КнопкаСвязанныеДокументы",
Тип("КнопкаФормы"), МенюТаблицы);
КнопкаМеню.ИмяКоманды = "ПоказатьСвязанныеДокументы";
КонецПроцедуры
Третий параметр метода Элементы.Добавить() — родительский элемент. Именно он определяет, что кнопка попадёт в контекстное меню, а не в командную панель или на форму. Если передать Неопределено, кнопка окажется в корне формы и, скорее всего, не будет видна.
Чтобы разместить пункт в конкретном месте меню, а не в конце, используйте группы: добавьте в контекстное меню элемент типа ГруппаФормы с видом ВидГруппыФормы.ГруппаКнопок и помещайте кнопки в неё. Порядок следования пунктов соответствует порядку добавления элементов в коллекцию.
Шаг 3. Обработчик нажатия и получение текущей строки
Команды контекстного меню таблиц почти всегда работают с текущей строкой. В обработчике на клиенте текущие данные получают через свойство ТекущиеДанные элемента-таблицы, а не через объект данных напрямую — это важно для динамических списков, где объект строки недоступен целиком.
&НаКлиенте
Процедура Подключаемый_ПоказатьСвязанныеДокументы(Команда)
ТекущиеДанные = Элементы.СписокТоваров.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
ПоказатьПредупреждение(, НСтр("ru = 'Строка не выбрана'"));
Возврат;
КонецЕсли;
ПараметрыФормы = Новый Структура("Отбор",
Новый Структура("Номенклатура", ТекущиеДанные.Ссылка));
ОткрытьФорму("Документ.РеализацияТоваров.ФормаСписка",
ПараметрыФормы, ЭтотОбъект);
КонецПроцедуры
Проверка ТекущиеДанные = Неопределено обязательна: пользователь может вызвать меню на пустой таблице, и без проверки обращение к полю строки вызовет ошибку. Если команда работает с выделенными строками, а не с одной текущей, используйте Элементы.СписокТоваров.ВыделенныеСтроки — это массив идентификаторов, по которым на сервере можно получить данные.
- 1Откройте модуль формы и найдите или создайте обработчик ПриСозданииНаСервере
- 2Создайте команду методом Команды.Добавить(), задайте Действие, Заголовок и Картинку
- 3Добавьте кнопку: Элементы.Добавить() с родителем — КонтекстноеМеню нужного элемента
- 4Свяжите кнопку с командой через свойство ИмяКоманды
- 5Напишите клиентский обработчик с проверкой ТекущиеДанные на Неопределено
- 6Обновите конфигурацию базы данных при необходимости и проверьте меню правым кликом
Управление видимостью и доступностью по условию
Часто команду нужно не удалять, а скрывать или делать неактивной в зависимости от контекста. Для этого у кнопки есть два свойства с разным поведением: Видимость полностью убирает пункт из меню, а Доступность оставляет его видимым, но серым и некликабельным. Доступность предпочтительнее, когда пользователь должен понимать, что функция существует, но сейчас недоступна.
Логичное место для проверки условия — обработчик ПриАктивизацииСтроки таблицы. Но он вызывается при каждом перемещении курсора, поэтому код в нём должен быть максимально лёгким: никаких серверных вызовов и запросов. Оптимально — проверка уже загруженных данных текущей строки.
&НаКлиенте
Процедура СписокТоваровПриАктивизацииСтроки(Элемент)
ТекущиеДанные = Элементы.СписокТоваров.ТекущиеДанные;
ЕстьСтрока = (ТекущиеДанные <> Неопределено)
И ЗначениеЗаполнено(ТекущиеДанные.Договор);
Элементы.КнопкаСвязанныеДокументы.Доступность = ЕстьСтрока;
КонецПроцедуры
Если видимость зависит от роли пользователя, проверку делайте один раз на сервере при создании формы через ПользователиИнформационнойБазы.ТекущийПользователь() или функции проверки прав (ПравоДоступа, роли из БСП), и сразу устанавливайте Видимость = Ложь. Не полагайтесь только на скрытие кнопки как на защиту: саму бизнес-логику всё равно нужно защищать проверками прав на сервере.
Особенности для динамических списков и обычных форм
Для таблиц, связанных с динамическим списком (списки документов, справочников), механика та же, но есть нюанс: значение ТекущиеДанные.Ссылка доступно всегда, а вот остальные поля — только если они выведены в список или добавлены в обязательные. Если обработчику нужно поле, которого нет в запросе списка, добавьте его в запрос динамического списка, иначе получите пустое значение без всякой ошибки.
В обычных формах (режим обычного приложения) подход принципиально другой: там контекстное меню строится через объект КонтекстноеМеню элемента управления и методы Добавить с указанием действия-обработчика напрямую, без промежуточной команды формы. Если вы сопровождаете старую конфигурацию на обычных формах, код из этой статьи потребует адаптации.
Проверка результата и отладка
После изменений обновите конфигурацию базы данных (F7), если менялись метаданные, или просто перезапустите сеанс, если правился только модуль формы. Откройте форму и кликните правой кнопкой по таблице: новый пункт должен появиться в меню с заданным заголовком и картинкой. Нажмите на него и убедитесь, что обработчик отрабатывает без ошибок.
Если пункта нет, проверьте три вещи по порядку: выполняется ли вообще ваш код в ПриСозданииНаСервере (поставьте точку останова), тот ли элемент формы указан как владелец меню (имена элементов чувствительны к регистру написания в конфигураторе, хотя в коде платформа имена сравнивает без учёта регистра), не переопределяется ли меню стандартными командами объекта. Отлаживать серверный код создания формы удобно в конфигураторе с включённой отладкой по протоколу HTTP или TCP в зависимости от режима запуска.
Как проверить результат
Отображается с заданным заголовком и картинкой при правом клике по таблице
Пункт отсутствует или появился в командной панели вместо меню
Выполняется обработчик, ошибок в журнале регистрации нет
Ошибка «процедура не определена» или ничего не происходит
Пункт недоступен или показывает понятное предупреждение
Ошибка обращения к полю Неопределено
У пользователя без нужной роли пункт скрыт или недоступен
Пункт виден всем, а защита отсутствует и на сервере
Частые вопросы
Можно ли добавить пункт в контекстное меню динамического списка без изменения конфигурации?
Да, если правится только модуль формы расширения. Механизм расширений конфигурации позволяет заимствовать форму и добавить в неё программный код, не снимая основную конфигурацию с поддержки. Это предпочтительный способ для типовых решений.
Как добавить пункт в меню «Ещё» вместо контекстного?
Меню «Ещё» — это подменю командной панели формы. Добавьте кнопку с родителем Элементы.ФормаКоманднаяПанель.ПодменюЕщё (точное имя зависит от формы) и свяжите с командой так же, через ИмяКоманды.
Почему картинка команды не отображается в меню?
Проверьте, что у команды свойство Отображение установлено в значение, включающее картинку (Картинка или НадписьКартинка), и что сама картинка существует в библиотеке. В контекстных меню платформа иногда показывает только надписи — это нормальное поведение ряда версий платформы.
Можно ли добавить один пункт сразу в меню нескольких таблиц?
Да. Одна команда формы может быть связана с несколькими кнопками: добавьте по кнопке в КонтекстноеМеню каждой таблицы и укажите всем одинаковое ИмяКоманды. В обработчике различать источник вызова придётся по активному элементу формы.
Как удалить или переименовать стандартный пункт контекстного меню?
Стандартные пункты платформы («Копировать», «Изменить» и подобные) программно не удаляются — их можно только дополнить своими. Если требуется убрать стандартное действие, обычно отключают соответствующие свойства таблицы (например, ТолькоПросмотр) или перехватывают стандартную обработку в событиях элемента.
Работает ли этот способ в мобильном клиенте и веб-клиенте?
Программное создание команд и кнопок работает во всех клиентах, но контекстное меню в мобильном клиенте имеет собственное представление и ограничения. Перед внедрением проверяйте поведение формы в каждом целевом клиенте, особенно отображение картинок и вложенных групп.
Что важно запомнить
Команда в контекстное меню добавляется в два действия: Команды.Добавить() создаёт команду с обработчиком, Элементы.Добавить() с родителем КонтекстноеМеню размещает кнопку. Весь код — в ПриСозданииНаСервере, проверка ТекущиеДанные на Неопределено обязательна, а скрытие кнопки никогда не заменяет проверку прав на сервере.