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

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

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

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

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

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

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

Способ 1. Паттерн «Форма-пустышка» и ручная очистка заимствованной формы

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

Выполним следующие шаги:

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

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

Способ 2. Программная модификация формы через общие модули (Метод БСП)

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

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

Проанализируем этот процесс на примере конфигурации с БСП:

  1. Заимствуем в расширение общий модуль МодификацияКонфигурацииПереопределяемый.
  2. В процедуре ПриСозданииНаСервере этого модуля ставим условие на перехват нужной нам формы.
  3. Используем метод ИзменитьРеквизиты() для динамического добавления новых реквизитов.
  4. Добавляем визуальные элементы через коллекцию Форма.Элементы.Добавить().
  5. Связываем новые элементы с процедурами-обработчиками с помощью метода УстановитьДействие().

Посмотрим на практический пример реализации такого кода в общем модуле расширения:


// Процедура-перехватчик в общем модуле МодификацияКонфигурацииПереопределяемый
Процедура ПриСозданииНаСервере(Форма, Отказ, СтандартнаяОбработка) Экспорт

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

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

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

Рассмотрим пример кода обработчика события в общем клиентском модуле:


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

Способ 3. Нетиповой обход через выгрузку конфигурации в файлы

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

Разберем данный алгоритм по шагам:

  1. Выгружаем расширение в файлы (команда Конфигурация -> Выгрузить конфигурацию в файлы...).
  2. Находим в выгруженных файлах xml-описание заимствованной формы.
  3. Вручную редактируем xml-файл структуры формы, удаляя из него все упоминания элементов, команд и реквизитов, оставляя только пустой каркас и секцию с кодом модуля формы.
  4. Загружаем измененные файлы обратно в расширение (команда Конфигурация -> Загрузить конфигурацию из файлов...).

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

Способ 4. Механизм подключаемых команд БСП

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

В БСП встроен мощный механизм подключаемых команд. Чтобы вывести вашу команду на форму документа или справочника, достаточно зарегистрировать ее через расширение переопределяемых модулей БСП (например, УправлениеПечатьюПереопределяемый или ЗаполнениеОбъектовПереопределяемый). Платформа сама найдет вашу команду и автоматически выведет кнопку в стандартные панели формы при ее открытии, а вызовы будут перенаправлены в указанный вами модуль менеджера или общий модуль.

Резюме: какой путь выбрать?

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

← На главную