Как программно добавить кнопку в начало командной панели и настроить ее обработчик для нескольких форм в 1С 8.3

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

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

Решение 1. Точное позиционирование кнопки с левого края панели

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

Синтаксис метода выглядит следующим образом:

Элементы.Переместить(<ЧтоПеремещаем>, <КудаПеремещаем>, <ПередКакимЭлементом>)

Разберем параметры подробнее:

  1. ЧтоПеремещаем — сам элемент формы (кнопка, группа, поле ввода), который мы хотим передвинуть.
  2. КудаПеремещаем — родительский элемент (в нашем случае командная панель), в который вложен перемещаемый элемент.
  3. ПередКакимЭлементом — элемент, перед которым должен встать наш перемещаемый объект. Если мы хотим сделать кнопку самой первой, нам нужно определить, какой элемент сейчас является первым в коллекции подчиненных элементов нашей панели, и указать его в качестве этого параметра. Если панель пуста, мы передаем Неопределено.

Рассмотрим практический пример кода. Реализуем процедуру, которая программно создает команду, кнопку на командной панели формы и сдвигает ее на первое место с левого края:


&НаСервере
Процедура ДобавитьИПозиционироватьКнопкуНаСервере()

    // 1. Создаем команду формы
    ИмяКоманды = "МояСпециальнаяКоманда";
    НоваяКоманда = Команды.Добавить(ИмяКоманды);
    НоваяКоманда.Заголовок = "Моя кнопка";
    НоваяКоманда.Действие  = "ОбработчикНажатияМоейКнопки"; // Имя клиентской процедуры в модуле этой формы

    // 2. Создаем элемент формы - кнопку и связываем ее с созданной командой
    ИмяКнопки = "КнопкаМояСпециальная";
    РодительПанель = Элементы.КоманднаяПанельФормы; // Укажите имя вашей командной панели
    НоваяКнопка = Элементы.Добавить(ИмяКнопки, Тип("КнопкаФормы"), РодительПанель);
    НоваяКнопка.ИмяКоманды = ИмяКоманды;

    // 3. Позиционируем кнопку в самое начало командной панели
    КоличествоПодчиненных = РодительПанель.ПодчиненныеЭлементы.Количество();
    
    Если КоличествоПодчиненных > 1 Тогда
        // Так как наша новая кнопка уже добавлена в конец коллекции, 
        // первым элементом (индекс 0) является старый "первый" элемент панели.
        // Перемещаем нашу кнопку так, чтобы она встала ПЕРЕД ним.
        ПервыйЭлементПанели = РодительПанель.ПодчиненныеЭлементы[0];
        Элементы.Переместить(НоваяКнопка, РодительПанель, ПервыйЭлементПанели);
    КонецЕсли;

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

Этот алгоритм гарантирует, что созданная кнопка всегда окажется на первой позиции, независимо от того, какие элементы уже присутствовали на панели до момента выполнения программного кода.

Решение 2. Обход ограничений обработчиков динамических команд

Часто разработчики задаются вопросом: "Как сделать так, чтобы обработчик динамически добавленной команды располагался не в модуле формы документа, а в какой-то одной общей форме или общем модуле?". Это особенно актуально, когда кнопку нужно добавить во множество различных документов конфигурации.

Здесь мы сталкиваемся с жестким платформенным ограничением 1С:Предприятия: свойство Действие объекта КомандаФормы может содержать только строковое имя клиентской процедуры, которая физически написана внутри модуля этой же самой формы (или расширения этой формы). Попытка напрямую назначить метод общего модуля (например, "ОбщийМодульКлиент.МойОбработчик") вызовет ошибку выполнения.

Тем не менее, существует стандартный паттерн обхода этого ограничения. Мы создаем в модуле формы простую процедуру-перехватчик (заглушку), которая транслирует вызов в общий модуль, передавая туда контекст формы:


// Код в модуле управляемой формы документа:

&НаКлиенте
Процедура ОбработчикНажатияМоейКнопки(Команда)
    
    // Перенаправляем выполнение в общий клиентский модуль, 
    // передавая форму в качестве параметра для возможности работы с ее реквизитами
    МойОбщийКлиентскийМодуль.ОбработатьНажатиеКнопкиНаФорме(ЭтаФорма, Команда);
    
КонецПроцедуры

В общем клиентском модуле МойОбщийКлиентскийМодуль (у которого в свойствах должны быть установлены флажки "Клиент (управляемое приложение)" и "Глобальный" или обычный вызов) мы пишем саму бизнес-логику:


// Код в общем модуле МойОбщийКлиентскийМодуль:

Процедура ОбработатьНажатиеКнопкиНаФорме(ФормаИсточник, Команда) Экспорт
    
    // Пример работы с контекстом формы:
    ОбъектДокумента = ФормаИсточник.Объект;
    
    ПоказатьПредупреждение(, "Нажата кнопка в документе: " + ОбъектДокумента.Ссылка);
    
    // Здесь мы можем вызывать серверные процедуры, открывать другие формы и т.д.
    
КонецПроцедуры

Этот подход позволяет минимизировать объем кода в самих формах, оставляя там лишь одну строчку вызова общего функционала.

Решение 3. Использование Общих команд (альтернатива динамическому коду)

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

Платформа 1С предоставляет великолепный инструмент декларативного решения этой задачи — Общие команды. Этот способ вообще не требует написания кода внутри форм документов!

Рассмотрим процесс настройки общих команд по шагам:

  1. В дереве метаданных конфигуратора перейдем в ветку Общие -> Общие команды и создадим новую команду (назовем ее, например, МояСпециальнаяКоманда).
  2. В палитре свойств созданной команды найдем свойство Тип параметра команды. Нажмем кнопку выбора и отметим галочками все те 20 документов, в формах которых должна появиться наша кнопка.
  3. В свойстве Группа укажем место, где платформа должна автоматически отрисовать кнопку. Для командной панели формы отлично подойдет значение Командная панель формы.Важное или Командная панель формы.Обычное.
  4. Перейдем в модуль команды (нажав кнопку "Модуль команды" в палитре свойств или через контекстное меню) и напишем обработчик события нажатия:

&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
    
    // ПараметрКоманды содержит ссылку на документ, из формы которого была нажата кнопка.
    // ПараметрыВыполненияКоманды.Источник содержит контекст самой управляемой формы.
    
    Если ЗначениеЗаполнено(ПараметрКоманды) Тогда
        ПоказатьПредупреждение(, "Вызвана команда для документа: " + СокрЛП(ПараметрКоманды));
    КонецЕсли;
    
КонецПроцедуры

Преимущества использования общих команд:

Решение 4. Использование механизмов БСП (Подключаемые команды)

Если вы ведете разработку в современной конфигурации, основанной на Библиотеке стандартных подсистем (БСП) (например, 1С:ERP, 1С:Комплексная автоматизация, 1С:Управление торговлей или 1С:Бухгалтерия), то самым правильным и архитектурно верным решением будет использование подсистемы БСП "Подключаемые команды".

Этот механизм позволяет регистрировать новые команды через специализированные переопределяемые модули. Платформа и подсистемы БСП самостоятельно инициализируют интерфейс, выводят кнопки в меню "Печать", "Заполнить" или в командную панель формы и обеспечивают вызов общего программного кода.

Для интеграции своей команды через БСП обычно требуется:

  1. Описать команду в общем модуле ПодключаемыеКомандыПереопределяемый.ПриОпределенииКомандПодключенныхКОбъекту.
  2. Прописать логику выполнения команды в модуле объекта или специализированном общем модуле интеграции.

Использование БСП избавляет от необходимости писать какой-либо низкоуровневый код по манипуляции элементами форм и обеспечивает стандартный, привычный пользователям интерфейс системы.

Решение 5. Быстрое получение программного кода кнопок через конфигуратор

Иногда программное создание сложных элементов формы (например, кнопок с меню, подменю, специфическими картинками и подсказками) вручную в коде отнимает много времени. Чтобы не писать строки добавления элементов "вслепую", можно воспользоваться комбинированным методом проектирования:

  1. Откройте любую тестовую управляемую форму в конфигураторе.
  2. Интерактивно (мышкой) соберите нужную кнопку, настройте ее свойства, добавьте картинку, задайте оформление, подсказки и привяжите команду.
  3. Воспользуйтесь специализированными внешними обработками декомпиляции управляемых форм (доступными на профильных ресурсах, таких как Инфостарт). Такие инструменты умеют анализировать интерактивный элемент формы и генерировать готовый программный код на встроенном языке 1С для его точного воссоздания.
  4. Скопируйте сгенерированный код, удалите интерактивную кнопку из тестовой формы и вставьте код в модуль нужного общего механизма динамического построения интерфейса.

Этот подход экономит массу времени и позволяет избежать досадных опечаток при ручном написании свойств элементов формы.

Важный нюанс: Динамическое добавление и производительность системы

В завершение проанализируем важный аспект работы платформы 1С, связанный с кэшированием управляемых форм.

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

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

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

← На главную