Свой пункт по правой кнопке мыши: команда формы, общая команда и расширение

· 9 мин

Содержание

Чтобы добавить команду в контекстное меню 1С, откройте форму в Конфигураторе, создайте команду на вкладке Команды, а затем перетащите её на вкладке Элементы в подчинённый элемент таблицы с именем вида СписокКонтекстноеМеню. Останется написать обработчик — процедуру, которую 1С вызовет по щелчку.

В типовой конфигурации то же самое делают в расширении, чтобы не снимать её с поддержки. Всё описанное относится к платформе 1С:Предприятие 8.3 и управляемым формам, одинаково для БП 3.0, ЗУП 3.1, УТ 11 и собственных конфигураций.

Как устроено контекстное меню в управляемой форме

У управляемой формы нет одного общего контекстного меню. Своё меню есть у каждой таблицы и у каждого поля ввода. В дереве элементов формы оно видно как отдельный подчинённый элемент:

  • 📋 Список → СписокКонтекстноеМеню и СписокКоманднаяПанель — для динамического списка;
  • 📦 Товары → ТоварыКонтекстноеМеню — для табличной части документа;
  • ✏️ Контрагент → КонтрагентКонтекстноеМеню — для поля ввода.

Каждое такое меню — это группа кнопок. Свойство Автозаполнение (по умолчанию включено) добавляет в неё стандартные команды: «Добавить», «Скопировать», «Изменить», «Пометить на удаление» и другие. Ваши кнопки встают рядом с ними.

Команда в меню — это всего лишь кнопка, которая ссылается на команду. Сама команда бывает трёх видов:

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

Способ 1. Команда формы в контекстном меню списка

Самый быстрый путь, если команда нужна в одной форме своей конфигурации или обработки.

Создание команды

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

Привязка к контекстному меню

  1. Перейдите на вкладку Элементы в левой верхней части редактора.
  2. Разверните таблицу Список, найдите элемент СписокКонтекстноеМеню.
  3. Перетащите команду мышью с вкладки Команды на СписокКонтекстноеМеню. Появится кнопка с именем вида СписокКонтекстноеМенюСуммаВыделенных.
  4. Порядок пунктов меняют стрелками на панели дерева элементов или перетаскиванием.
  5. Чтобы отделить свою команду от стандартных, добавьте в меню группу с видом «Группа кнопок» и положите кнопку в неё — 1С нарисует разделитель.

Если нужна та же команда и на панели над списком, перетащите её ещё раз в СписокКоманднаяПанель. Одна команда может иметь сколько угодно кнопок.

Способ 2. Общая команда для нескольких форм

Общая команда удобна, когда пункт нужен и в списке, и в карточке, и в форме выбора. Код пишется один раз — в модуле самой команды.

Настройка свойств

  1. В дереве конфигурации откройте Общие → Общие команды и добавьте новую.
  2. В свойстве Тип параметра команды выберите тип ссылки, например ДокументСсылка.РеализацияТоваровУслуг. Можно отметить несколько типов.
  3. Режим использования параметра: Одиночный — команда получит одну ссылку, Множественный — массив выделенных строк.
  4. Группа задаёт место по умолчанию, например Командная панель формы. Отдельной стандартной группы «контекстное меню» в этом списке нет — в меню команду ставят руками в форме.
  5. Если команда меняет данные, включите свойство Изменяет данные. Тогда пользователю с правом только на чтение кнопка будет недоступна.

Размещение в контекстном меню

Откройте нужную форму, вкладка Команды → подвкладка Глобальные команды. Там собраны команды, которые подходят к данным формы, сгруппированные по источнику параметра. Найдите свою под источником Список и перетащите её в СписокКонтекстноеМеню — источник параметра подставится сам.

Код общей команды живёт в её модуле:

&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)

	// При режиме «Множественный» ПараметрКоманды — массив ссылок
	Если ПараметрКоманды.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;

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

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

Форма-владелец передаётся третьим параметром, поэтому открытая форма будет связана с той, откуда её вызвали.

Добавление команды в типовую конфигурацию через расширение

В БП 3.0, ЗУП 3.1 или УТ 11 менять форму напрямую — значит снять объект с поддержки и усложнить каждое обновление. Расширения конфигурации появились в платформе 8.3.6 и решают задачу без этого.

  1. В Конфигураторе: Конфигурация → Расширения конфигурации, добавьте новое расширение. Назначение — Адаптация или Дополнение.
  2. В основной конфигурации найдите нужную форму, щёлкните по ней правой кнопкой и выберите «Добавить в расширение». Форма появится в расширении как заимствованная.
  3. Откройте заимствованную форму в расширении. Дальше всё как в способе 1: новая команда на вкладке Команды, кнопка в СписокКонтекстноеМеню, обработчик в модуле формы расширения.
  4. Сохраните расширение и обновите его конфигурацию базы данных — это отдельный шаг от сохранения. Перезапустите сеанс 1С:Предприятия.

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

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

Готовое расширение можно сохранить в файл .cfe и подключить в рабочей базе без Конфигуратора: Все функции → Стандартные → Управление расширениями конфигурации.

Перед подключением расширения в рабочую базу проверьте его на копии: ошибка в ПриСозданииНаСервере заимствованной формы не даст открыть форму никому.

Код обработчика: как получить строку, на которой щёлкнули

Контекстное меню вызывают на конкретной строке, поэтому почти любой обработчик начинается с вопроса «какая строка?». Ответ зависит от вида таблицы:

  • 🔹 Элементы.Список.ТекущаяСтрока — ссылка на текущий объект динамического списка;
  • 🔹 Элементы.Список.ВыделенныеСтроки — массив ссылок на все выделенные строки;
  • 🔹 Элементы.Товары.ТекущиеДанные — данные текущей строки табличной части (или Неопределено, если строк нет).

Пример: команда «Сумма выделенных» для списка реализаций. Пользователь выделяет несколько документов, жмёт правую кнопку — и видит общую сумму.

&НаКлиенте
Процедура СуммаВыделенных(Команда)

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

	Сумма = СуммаДокументовНаСервере(Выделенные);
	ПоказатьПредупреждение(, СтрШаблон("Выделено документов: %1. Сумма: %2",
		Формат(Выделенные.Количество(), "ЧГ=0"),
		Формат(Сумма, "ЧДЦ=2; ЧН=0")));

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

&НаСервереБезКонтекста
Функция СуммаДокументовНаСервере(Ссылки)

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	ЕСТЬNULL(СУММА(Док.СуммаДокумента), 0) КАК Сумма
	|ИЗ
	|	Документ.РеализацияТоваровУслуг КАК Док
	|ГДЕ
	|	Док.Ссылка В (&Ссылки)";
	Запрос.УстановитьПараметр("Ссылки", Ссылки);

	Выборка = Запрос.Выполнить().Выбрать();
	Выборка.Следующий();
	Возврат Выборка.Сумма;

КонецФункции

Серверная функция объявлена &НаСервереБезКонтекста: на сервер уходит только массив ссылок, а не вся форма. Для команды, которая вызывается часто, это заметно быстрее.

Для табличной части проверка другая:

&НаКлиенте
Процедура ПоказатьНоменклатуру(Команда)

	ТекущиеДанные = Элементы.Товары.ТекущиеДанные;
	Если ТекущиеДанные = Неопределено Тогда
		Возврат;
	КонецЕсли;

	ПоказатьЗначение(, ТекущиеДанные.Номенклатура);

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

Если обработчик меняет записанные объекты, после серверного вызова обновите список: Элементы.Список.Обновить().

Команда в табличной части документа

У табличной части есть своя тонкость: строки живут в данных формы, а не в базе. Поэтому обработчик может менять их прямо на клиенте, без серверного вызова: ТекущиеДанные.Количество = 1. Документ при этом станет модифицированным, и 1С предложит его записать.

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

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

Программное добавление команды в контекстное меню

Иногда форму в Конфигураторе удобнее не трогать, а добавить пункт кодом. Например, когда команд несколько и их список зависит от настроек. Делается это в ПриСозданииНаСервере:

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

	НоваяКоманда = Команды.Добавить("СуммаВыделенных");
	НоваяКоманда.Заголовок = "Сумма выделенных";
	НоваяКоманда.Действие = "СуммаВыделенных";

	Кнопка = Элементы.Добавить("КнопкаСуммаВыделенных",
		Тип("КнопкаФормы"), Элементы.СписокКонтекстноеМеню);
	Кнопка.ИмяКоманды = "СуммаВыделенных";

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

Свойство Действие — это имя процедуры-обработчика. Процедура СуммаВыделенных(Команда) с директивой &НаКлиенте должна существовать в модуле формы, иначе при щелчке будет ошибка.

Чтобы поставить кнопку не в конец меню, а перед определённым пунктом, используйте Элементы.Вставить(...) — у него есть параметр «элемент, перед которым вставлять».

Видимость и доступность пункта меню

Пункт, который нельзя выполнить, лучше скрыть или сделать серым. Для этого есть четыре рычага.

РычагГде настроитьЧто даёт
Права ролиРоль → общая команда, право ПросмотрБез права команды в меню нет вообще
Функциональная опцияСвойство команды Функциональные опцииКоманда пропадает, если опция выключена
Код при открытииПриСозданииНаСервереСкрыть по условию: Элементы.КнопкаСуммаВыделенных.Видимость = Ложь
Код при смене строкиСобытие таблицы ПриАктивизацииСтрокиДелать пункт серым для неподходящих строк

Проверку роли в коде делают так:

Элементы.КнопкаСуммаВыделенных.Видимость = РольДоступна("ПолныеПрава");

Для доступности по текущей строке не нагружайте сервер. Событие ПриАктивизацииСтроки срабатывает при каждом движении курсора, поэтому проверку откладывают через обработчик ожидания:

&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
	ПодключитьОбработчикОжидания("ОбновитьДоступностьКоманд", 0.2, Истина);
КонецПроцедуры

&НаКлиенте
Процедура ОбновитьДоступностьКоманд()
	ТекущиеДанные = Элементы.Список.ТекущиеДанные;
	Элементы.КнопкаСуммаВыделенных.Доступность =
		ТекущиеДанные <> Неопределено И ТекущиеДанные.Проведен;
КонецПроцедуры

Поле Проведен должно быть в данных динамического списка. Если его нет среди колонок, отметьте его в настройке списка как используемое всегда.

Свойство кнопки Только во всех действиях прячет её в меню «Ещё» командной панели. Для контекстного меню оно не нужно, но полезно, если ту же команду вы вывели и на панель, а места там мало.

Команда не появилась или не работает: отладка

Запустите отладку из Конфигуратора (Отладка → Начать отладку), поставьте точку останова на первую строку обработчика клавишей F9 и вызовите команду. Если отладчик не остановился, проблема в размещении или правах, а не в коде.

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

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

Можно ли добавить свою команду в контекстное меню всех списков сразу?
Готовой настройки «во все формы» в платформе нет. Каждую форму дорабатывают отдельно — вручную или общим кодом, который вызывается из ПриСозданииНаСервере каждой формы.
Как вложить несколько команд в подменю?
Добавьте в контекстное меню группу вида «Подменю», задайте ей заголовок и разложите кнопки внутрь. Пользователь увидит один пункт со стрелкой.
Можно ли назначить команде горячую клавишу?
Да, в свойстве команды Сочетание клавиш. Не занимайте сочетания стандартных команд, например F2, F9 и Ins.
Будет ли команда работать в веб-клиенте?
Да. Веб-клиент перехватывает правую кнопку мыши и показывает меню 1С вместо меню браузера. Клиентский код должен обходиться без модальных окон — используйте ПоказатьПредупреждение и ПоказатьВопрос, а не Предупреждение и Вопрос.
Нужен ли монопольный режим, чтобы подключить расширение с командой?
Для добавления расширения монопольный доступ обычно не требуется. Но открытые сеансы увидят новую команду только после перезапуска.