Как программно добавить кнопку на все формы документов и справочников в обычном приложении 1С?

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

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

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

Выясняем причину: почему динамическая кнопка неактивна?

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

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


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

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

  1. Неверная сигнатура (количество параметров) обработчика события. Это самая распространенная ошибка. Процедура-обработчик для кнопки командной панели в обычных формах обязательно должна принимать ровно один параметр — саму нажатую кнопку (объект типа КнопкаКоманднойПанели). Если процедура объявлена без параметров (например, Процедура ВыполнитьДействиеНажатие()), платформа считает ее неподходящей для данного действия и автоматически блокирует кнопку.
  2. Область видимости обработчика действия. При создании объекта Новый Действие("ИмяПроцедуры") платформа ищет указанную процедуру строго в определенных модулях. Если процедура расположена в общем модуле, платформа не сможет ее вызвать напрямую через конструкцию вида Новый Действие("ОбщийМодуль.ИмяПроцедуры"). Такой вызов завершится ошибкой выполнения или сделает кнопку недоступной.

Решение задачи по шагам: как правильно настроить обработчик действия

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

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

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

Шаг 1. Объявление глобального обработчика. Откроем модуль обычного приложения вашей конфигурации и добавим туда экспортную процедуру с правильной сигнатурой:


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

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

Шаг 2. Динамическое добавление кнопки. Теперь нам нужно найти общую точку входа — процедуру, которая вызывается при открытии любого документа или справочника в системе. В типовых конфигурациях (например, УТ 10.3, УПП 1.3, КА 1.1) для этого идеально подходит общий модуль РаботаСДиалогами.

Найдем в модуле РаботаСДиалогами процедуру УстановитьЗаголовокФормыДокумента(Форма, ТекстЗаголовка = "") или аналогичную ей (например, УстановитьОформлениеЭкранныхЭлементов), которая гарантированно вызывается при инициализации интерфейса документов. Добавим в нее вызов нашей функции внедрения кнопки:


Процедура ДобавитьКнопкуНаПанельФормы(Форма) Экспорт
    // Проверяем наличие командной панели "ДействияФормы"
    ПанельДействий = Форма.ЭлементыФормы.Найти("ДействияФормы");
    Если ПанельДействий <> Неопределено И ТипЗнч(ПанельДействий) = Тип("КоманднаяПанель") Тогда
        
        // Проверим, не добавлена ли кнопка ранее, чтобы избежать дублирования
        ИмяКнопки = "КнопкаГлобальногоДействия";
        Если ПанельДействий.Кнопки.Найти(ИмяКнопки) = Неопределено Тогда
            
            // Создаем объект Действие, указывая имя глобальной процедуры из Модуля обычного приложения
            НовоеДействие = Новый Действие("ГлобальныйОбработчикНажатияКнопки");
            
            // Добавляем кнопку на панель
            ПанельДействий.Кнопки.Добавить(
                ИмяКнопки, 
                ТипКнопкиКоманднойПанели.Действие, 
                "Сервис", 
                НовоеДействие
            );
            
        КонецЕсли;
        
    КонецЕсли;
КонецПроцедуры

Аналогичным образом мы можем поступить и со справочниками. Достаточно вызвать разработанный метод из процедуры общего модуля РаботаСДиалогами.УстановитьЗаголовокФормыСправочника.

Почему подписки на события не подходят для решения этой задачи?

В процессе обсуждения на форумах часто возникает вопрос: «Можно ли решить эту задачу изящнее, например, через подписку на событие формы?». Ответ однозначный — в обычном приложении это сделать невозможно.

Разберем причины этого ограничения подробнее. Механизм подписок на события в платформе 1С ориентирован исключительно на работу с прикладными объектами базы данных (такими как ДокументОбъект, СправочникОбъект, РегистрНаборЗаписей). События, на которые можно подписаться (например, ПередЗаписью, ПриЗаписи, ОбработкаПроверкиЗаполнения), исполняются на уровне данных. На этом уровне у системы нет доступа к визуальным элементам интерфейса и формам.

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

Альтернативный бескодовый метод внедрения команд (для документов)

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

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

Этот способ имеет неоспоримое преимущество: конфигурация остается полностью типовой, что существенно облегчает процесс обновления, а вся сервисная логика выносится во внешний файл обработки (.epf).

← На главную