Как правильно изменить процедуру в модуле формы через расширение в 1С?

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

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

Почему модуль заимствованной формы пустой

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

Способ 1. Использование директивы &Вместо и вызова исходного кода

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

  1. Полная замена процедуры: если логику метода нужно переписать кардинально или заменить строку глубоко в теле алгоритма (на старых режимах совместимости), нам придется скопировать все тело исходной процедуры в модуль расширения, объявив ее с директивой &Вместо("ИмяИсходнойПроцедуры"). В этом случае код основной конфигурации выполняться не будет вовсе — управление полностью переходит к процедуре расширения.
  2. Дополнение кода через системный метод ПродолжитьВызов(): если базовую логику необходимо сохранить, а собственное действие нужно выполнить в самом начале или в самом конце процедуры, нам не требуется дублировать типовой код. Достаточно вызвать метод ПродолжитьВызов(), который передаст управление оригинальному коду типовой конфигурации.

Посмотрим на пример перехвата процедуры ПриОткрытии с сохранением вызова исходного метода:


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

Способ 2. Использование директив &Перед и &После

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

  1. Метод с директивой &Перед выполняется в первую очередь. Если в сигнатуре метода есть параметр Отказ, и мы установим его в Истина, исходный метод и методы с директивой &После вызваны не будут.
  2. Метод с директивой &После выполнится строго после завершения работы стандартного обработчика.

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


&НаКлиенте
&После("ПриОткрытии")
Процедура Расш1_ПриОткрытии(Отказ)
    // Дополнительная логика, выполняемая после основного кода
    ТекущийЭлемент = Элементы.ПолеКомментарий;
КонецПроцедуры

Способ 3. Точечное изменение кода через &ИзменениеИКонтроль

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

  1. Мы копируем тело исходной процедуры в модуль расширения.
  2. Указываем для нее директиву &ИзменениеИКонтроль("ИмяИсходнойПроцедуры").
  3. С помощью специальных инструкций препроцессора #Вставить и #Удалить размечаем конкретную правку.

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

Посмотрим на пример точечной замены строки:


&НаКлиенте
&ИзменениеИКонтроль("ПриОткрытии")
Процедура Расш1_ПриОткрытии(Отказ)
    // Типовой код процедуры, оставшийся без изменений
    СтандартнаяОбработка = Истина;
    #Удалить
    Заголовок = "Старый заголовок формы";
    #КонецУдаления
    #Вставить
    Заголовок = "Новый заголовок из расширения";
    #КонецВставки
    ПодключитьОбработчикОжидания("ОбновитьДанные", 60);
КонецПроцедуры

Важные ограничения и правила перехвата методов

Работая с расширением модулей, необходимо помнить о ключевых технических ограничениях:

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

Таким образом, просто «вставить одну строчку» в пустой модуль невозможно. Для точечной замены одной строки в середине процедуры правильным стандартом является использование механизма &ИзменениеИКонтроль, либо переопределение метода через &Вместо с переносом всего окружения процедуры, если платформа не поддерживает контроль изменений.

← На главную