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