К статье
Практический материал

Разработка и Конфигурация · 13 мин

Как программно добавить подменю командной панели в 1С

Разбираем, как программно создать подменю в командной панели формы 1С: работа с Элементы.Добавить, группы кнопок, команды, примеры кода, типичные ошибки и FAQ.

Подменю в командной панели формы 1С — это группа кнопок подчинённого уровня, которая помогает упорядочить команды и не перегружать интерфейс. Когда команд много, типовое решение — сгруппировать их: например, «Печать», «Отчёты», «Сервис». В конфигураторе это делается визуально, но в расширениях, динамических формах и при условной логике подменю приходится создавать программно — через свойство Элементы объекта УправляемаяФорма.

Программное добавление выполняется в три шага: сначала создаётся команда формы (объект в коллекции Команды), затем в командную панель добавляется группа вида ГруппаКнопок с типом Подменю, и в эту группу помещаются кнопки, связанные с командами. Порядок важен: нельзя сослаться на команду, которой ещё нет, и нельзя добавить кнопку в группу, которая не создана.

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

Где именно выполняется программное создание элементов

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

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

Шаг 1. Создание команд формы

Кнопка в подменю не содержит логики сама по себе — она лишь ссылается на команду формы. Поэтому первым делом в коллекцию ЭтаФорма.Команды добавляются команды с уникальными именами. Для каждой команды задаются заголовок (то, что увидит пользователь), действие (имя обработчика) и при необходимости картинка и подсказка.

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

&НаСервере

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

Команда = ЭтаФорма.Команды.Добавить("Преф_ПечатьАкта");

Команда.Заголовок = НСтр("ru = 'Акт'");

Команда.Действие = "Подключаемый_ВыполнитьКомандуПечати";

Команда.Картинка = БиблиотекаКартинок.Печать;

Команда.Отображение = ОтображениеКнопки.НадписьКартинка;

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

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

Шаг 2. Добавление подменю в командную панель

Подменю создаётся методом Элементы.Добавить с типом Тип("ГруппаФормы"). Вторым параметром передаётся родитель — командная панель формы, обычно Элементы.КоманднаяПанель (имя зависит от формы; у динамических списков и табличных частей командные панели свои). После добавления группе задаётся вид ВидГруппыФормы.Подменю и заголовок.

ГруппаПодменю = Элементы.Добавить("Преф_ПодменюПечать", Тип("ГруппаФормы"), Элементы.КоманднаяПанель);

ГруппаПодменю.Вид = ВидГруппыФормы.Подменю;

ГруппаПодменю.Заголовок = НСтр("ru = 'Печать'");

ГруппаПодменю.Картинка = БиблиотекаКартинок.Печать;

ГруппаПодменю.Отображение = ОтображениеКнопки.НадписьКартинка;

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

Шаг 3. Добавление кнопок внутрь подменю

Кнопки добавляются тем же методом Элементы.Добавить, но с типом Тип("КнопкаФормы") и родителем — созданной группой подменю. Каждой кнопке присваивается имя команды через свойство ИмяКоманды. Порядок добавления определяет порядок отображения пунктов в меню.

Кнопка = Элементы.Добавить("Преф_КнопкаПечатьАкта", Тип("КнопкаФормы"), ГруппаПодменю);

Кнопка.ИмяКоманды = "Преф_ПечатьАкта";

Кнопка2 = Элементы.Добавить("Преф_КнопкаПечатьСчета", Тип("КнопкаФормы"), ГруппаПодменю);

Кнопка2.ИмяКоманды = "Преф_ПечатьСчета";

Для визуального разделения пунктов внутри подменю можно добавить группу с видом ВидГруппыФормы.ГруппаКнопок — она отобразится как разделитель (горизонтальная линия) между блоками кнопок. Это удобно, когда в одном подменю смешаны, например, печатные формы и сервисные операции.

Порядок действий
  1. 1
    В ПриСозданииНаСервере добавьте команды в ЭтаФорма.Команды с уникальными именами и обработчиками
  2. 2
    Создайте группу: Элементы.Добавить с типом ГруппаФормы, родителем — командная панель
  3. 3
    Установите группе Вид = ВидГруппыФормы.Подменю, задайте заголовок и картинку
  4. 4
    Добавьте кнопки типа КнопкаФормы с родителем-подменю и заполните ИмяКоманды
  5. 5
    Создайте клиентский обработчик, указанный в свойстве Действие команды
  6. 6
    Откройте форму и проверьте, что подменю отображается и команды выполняются

Полный пример: подменю с несколькими командами

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

&НаСервере

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

Описания = Новый Массив;

Описания.Добавить(Новый Структура("Имя,Заголовок", "Преф_Заполнить", "Заполнить по умолчанию"));

Описания.Добавить(Новый Структура("Имя,Заголовок", "Преф_Очистить", "Очистить таблицу"));

Для Каждого Описание Из Описания Цикл

Команда = ЭтаФорма.Команды.Добавить(Описание.Имя);

Команда.Заголовок = Описание.Заголовок;

Команда.Действие = "Подключаемый_ВыполнитьКоманду";

КонецЦикла;

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

Подменю.Вид = ВидГруппыФормы.Подменю;

Подменю.Заголовок = НСтр("ru = 'Дополнительно'");

Для Каждого Описание Из Описания Цикл

Кнопка = Элементы.Добавить("Кнопка_" + Описание.Имя, Тип("КнопкаФормы"), Подменю);

Кнопка.ИмяКоманды = Описание.Имя;

КонецЦикла;

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

&НаКлиенте

Процедура Подключаемый_ВыполнитьКоманду(Команда)

Если Команда.Имя = "Преф_Заполнить" Тогда

// логика заполнения

ИначеЕсли Команда.Имя = "Преф_Очистить" Тогда

// логика очистки

КонецЕсли;

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

Обратите внимание: один общий обработчик различает команды по свойству Команда.Имя. Это стандартный приём для динамически создаваемых команд — он избавляет от необходимости генерировать отдельные процедуры под каждую кнопку.

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

Ограничения и условия выбора подхода

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

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

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

Способы добавления подменю

В конфигураторе (визуально)

Подходит для статичного набора команд. Не требует кода, легко сопровождается, но не адаптируется к данным в runtime.

Программно в ПриСозданииНаСервере

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

Через расширение конфигурации

Подходит для доработки типовых форм без их изменения. Обязательны префиксы имён и проверка совместимости при обновлениях.

Типичные ошибки и как их диагностировать

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

Вторая типичная проблема — подменю создано, но не отображается. Причины: не установлено свойство Вид (группа выглядит как плоский ряд кнопок), неверно указан родитель (кнопки попали не в ту командную панель), либо у группы или командной панели снята видимость. Проверяйте свойства Видимость и Доступность всей цепочки родителей.

Третья группа ошибок связана с обработчиками: процедура, указанная в Действие, объявлена с директивой &НаСервере вместо &НаКлиенте, не принимает параметр команды или вообще отсутствует. В этом случае форма падает при открытии с сообщением о невозможности найти обработчик.

Типичные ошибки
01
Кнопка добавлена до создания команды — ошибка «Команда не найдена» при открытии формы
02
Не установлено свойство Вид у группы — вместо подменю отображается плоский ряд кнопок
03
Обработчик команды объявлен на сервере — команда недоступна на клиенте, ошибка при нажатии
04
Повторное выполнение кода без проверки Элементы.Найти — исключение из-за дублирования имён
05
Неверный родитель кнопки — пункт появляется не в подменю, а в основной командной панели
Контрольные точки

Как проверить результат

Отображение подменю
Норма

В командной панели виден пункт с заголовком, раскрывающий список кнопок

Тревожный признак

Пункт отсутствует или кнопки лежат прямо в командной панели

Работа команд
Норма

Нажатие кнопки вызывает обработчик, Команда.Имя содержит ожидаемое значение

Тревожный признак

Ошибка о ненайденном обработчике или пустое имя команды

Повторное открытие формы
Норма

Форма открывается без ошибок любое число раз

Тревожный признак

Исключение о дублировании имени элемента

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

FAQ: частые вопросы

Можно ли добавить подменю в командную панель табличной части?

Да. У таблицы формы есть собственная командная панель, доступная как Элементы.ИмяТаблицы.КоманднаяПанель. Её и нужно указать родителем при добавлении группы-подменю. Логика создания команд и кнопок полностью аналогична.

Как сделать вложенное подменю (подменю внутри подменю)?

Добавьте внутрь первого подменю ещё одну группу с видом ВидГруппыФормы.Подменю, указав первое подменю родителем. Платформа поддерживает вложенность, но злоупотреблять ей не стоит: глубокие меню неудобны пользователям.

Почему кнопка в подменю отображается без картинки?

Картинка задаётся у команды (свойство Картинка), а не у кнопки. Также проверьте свойство Отображение команды: при значении Надпись картинка скрыта, при НадписьКартинка или Картинка — отображается. В подменю картинки показываются слева от заголовка пункта.

Можно ли программно удалить или скрыть созданное подменю?

Удалить — да, методом Элементы.Удалить(Элемент), но только на сервере. Скрыть проще и безопаснее: установите Элементы.ИмяПодменю.Видимость = Ложь — это можно делать и на клиенте, что подходит для условного отображения без пересоздания элементов.

Работает ли этот подход в обычных формах?

Нет. Описанная модель (Элементы.Добавить, коллекция Команды) относится к управляемым формам. В обычных формах использовались другие объекты (КоманднаяПанель с коллекцией Кнопки), и такие формы в современных конфигурациях практически не встречаются.

Как добавить разделитель между пунктами подменю?

Создайте внутри подменю группу с типом ГруппаФормы и видом ВидГруппыФормы.ГруппаКнопок, не добавляя в неё кнопок. Она отобразится как горизонтальный разделитель. Заголовок такой группе задавать не нужно.

Итог

Что важно запомнить

Подменю создаётся программно в три шага: команды в ЭтаФорма.Команды, группа с видом ВидГруппыФормы.Подменю в командной панели, кнопки с ИмяКоманды внутри группы. Весь код — на сервере в ПриСозданииНаСервере, обработчики — на клиенте. Используйте уникальные имена с префиксом, проверяйте результат на копии базы и выбирайте программный подход только там, где состав команд действительно динамический.