Как в расширении централизованно доработать формы через событие ПриСозданииНаСервере в 1С:БП 3.0?

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

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

Рассмотрим ситуацию: программист хочет программно создавать реквизиты на формах документов в расширении для «1С:Бухгалтерия 3.0». Для этого он пытается перехватить событие ПриСозданииНаСервере в переопределяемом модуле ПрослеживаемостьСобытияФормПереопределяемый. Но отладчик не останавливается в его процедуре, и код не выполняется. Давайте разберемся, почему так происходит и как правильно решить эту задачу.

Почему не работает перехват в модуле `ПрослеживаемостьСобытияФормПереопределяемый`?

Ключ к разгадке кроется в самом названии модуля. Проанализируем его по частям и выясним причину такого поведения системы.

1. Что такое «Переопределяемый» модуль?

В типовых конфигурациях 1С существуют общие модули с суффиксом «Переопределяемый». Это не анахронизм, оставшийся со времен до появления расширений, а специальный и очень полезный механизм. Разработчики конфигурации сознательно создают в таких модулях пустые экспортные процедуры-«заглушки». Затем, в ключевых точках алгоритмов основной конфигурации, они размещают вызовы этих пустых процедур.

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

2. Контекст имеет значение: слово «Прослеживаемость»

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

Это означает, что процедуры из этого модуля (включая ПриСозданииНаСервере) вызываются только из форм тех объектов, которые непосредственно связаны с прослеживаемостью. Например, это могут быть документы «Счет-фактура полученный», «Реализация (акт, накладная)» или «Поступление (акт, накладная)», но только в том случае, если в них присутствуют товары, подлежащие прослеживаемости. Если вы открываете форму документа, который не имеет отношения к этой подсистеме (например, «Авансовый отчет» без прослеживаемых товаров), вызов процедуры из этого модуля просто не будет выполнен кодом основной конфигурации. Поэтому ваша точка останова никогда не сработает.

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

Правильный архитектурный подход для централизации доработок форм

Стремление собрать всю логику по доработке форм в одном месте — абсолютно верное. Это упрощает поддержку, отладку и развитие расширения. Раз универсального «перехватчика» нет, воспользуемся другим, более надежным и гибким методом. Разберем его по шагам.

  1. Создание общего модуля в расширении

    Первым делом в своем расширении создайте новый общий модуль. Назовем его, например, Расш_МодификацияФормСервер. Установите для него флаги «Сервер» и «Вызов сервера», так как работа с данными и элементами формы при ее создании происходит на сервере.

  2. Описание логики доработки в общем модуле

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

    Посмотрим на пример. Допустим, мы хотим добавлять на форму новую группу и информационную надпись.

    
    // Общий модуль Расш_МодификацияФормСервер
    
    Процедура ДополнитьФормуПриСозданииНаСервере(Форма) Экспорт
        
        // Проверяем, что на форме еще нет наших элементов,
        // чтобы избежать ошибок при повторном открытии
        Если Форма.Элементы.Найти("Расш_ГруппаДопИнформация") = Неопределено Тогда
            
            // Создаем новую группу
            НоваяГруппа = Форма.Элементы.Добавить("Расш_ГруппаДопИнформация", Тип("ГруппаФормы"));
            НоваяГруппа.Вид = ВидГруппыФормы.ОбычнаяГруппа;
            НоваяГруппа.Заголовок = "Дополнительная информация (расширение)";
            НоваяГруппа.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Вертикальная;
            
            // Создаем новую декорацию-надпись
            НоваяДекорация = Форма.Элементы.Добавить("Расш_ИнфоНадпись", Тип("ДекорацияФормы"), НоваяГруппа);
            НоваяДекорация.Вид = ВидДекорацииФормы.Надпись;
            НоваяДекорация.Заголовок = "Эта форма была доработана централизованно через расширение.";
            
        КонецЕсли;
        
    КонецПроцедуры
    
  3. Заимствование нужных форм в расширение

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

  4. Вызов общей процедуры из заимствованных форм

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

    Пример для формы документа «ЗаказПокупателя»:

    
    // Модуль формы документа "ЗаказПокупателя" в расширении
    
    &После("ПриСозданииНаСервере")
    Процедура Расш_ПриСозданииНаСервере(Форма, Отказ, СтандартнаяОбработка)
        
        // Вызываем нашу централизованную процедуру
        Расш_МодификацияФормСервер.ДополнитьФормуПриСозданииНаСервере(Форма);
        
    КонецПроцедуры
    

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

Преимущества такого подхода:

Таким образом, мы не только решили исходную проблему, но и выстроили правильную и поддерживаемую архитектуру доработок в расширении.

← На главную