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

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

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

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

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

В чем сложность визуального заимствования форм?

Когда мы заимствуем форму в расширение стандартным визуальным способом (перетаскиванием), платформа запоминает состояние формы на момент заимствования. При работе в режиме предприятия происходит динамическое объединение («микро-патчинг») оригинальной формы и изменений из расширения.

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

Способ 1. Использование переопределяемых модулей БСП (Самый чистый метод)

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

Рассмотрим по шагам, как реализовать этот подход:

  1. Создаем расширение (или используем существующее).
  2. Заимствуем в расширение общий модуль МодификацияКонфигурацииПереопределяемый.
  3. В модуле находим процедуру ПриСозданииНаСервере и добавляем к ней аннотацию &После.

Проанализируем пример кода, который выполняет проверку открываемой формы и программно создает на ней элементы управления:


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

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

Важный нюанс: Реквизиты объекта vs Реквизиты формы

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

Если вы добавили новый реквизит непосредственно в сам документ через расширение, то этот реквизит уже существует в структуре базы данных и доступен в форме через основную схему компоновки данных формы (в свойстве Объект). В этом случае вызывать тяжелый метод ИзменитьРеквизиты() на сервере не требуется! Достаточно просто связать элемент через свойство ПутьКДанным = "Объект.ИмяВашегоРеквизита", как показано в примере выше.

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


// 1. Создаем массив добавляемых реквизитов формы
МассивРеквизитов = Новый Массив;
ТипДанных = Новый ОписаниеТипов("Булево");
НовыйРеквизитФормы = Новый РеквизитФормы("Расш1_ВременныйФлаг", ТипДанных, , "Доп. флаг", Истина);
МассивРеквизитов.Добавить(НовыйРеквизитФормы);

// 2. Добавляем реквизит на форму (метод выполняется на сервере)
Форма.ИзменитьРеквизиты(МассивРеквизитов);

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

Способ 2. Заимствование только модуля формы для обработки событий

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

Платформа требует, чтобы обработчик события физически находился в модуле этой самой формы. Метод УстановитьДействие("ПриИзменении", "ИмяПроцедуры") выдаст ошибку, если процедура ИмяПроцедуры не объявлена в модуле формы как экспортная.

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

  1. Заимствуем форму в расширение, но не открываем её визуальный редактор.
  2. Переходим в модуль формы в расширении (он будет пустым).
  3. В модуле пишем наши клиентские процедуры-обработчики.

Посмотрим на пример реализации такого подхода. В пустом модуле формы расширения пишем клиентский метод:


&НаКлиенте
Процедура Расш1_НовоеПолеПриИзменении(Элемент)
    
    // Описываем логику, которая должна сработать при изменении поля
    ПоказатьПредупреждение(, "Значение успешно изменено!");
    
КонецПроцедуры

А при создании элементов программно (например, через переопределяемый модуль или в процедуре ПриСозданииНаСервере самой формы в расширении) мы привязываем это событие:

НовыйЭлемент.УстановитьДействие("ПриИзменении", "Расш1_НовоеПолеПриИзменении");

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

Уникальность имен — залог стабильной работы

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

Чтобы избежать конфликтов имен (которые приведут к ошибкам при открытии формы), всегда используйте уникальные префиксы вашего расширения для программно создаваемых реквизитов и элементов интерфейса: ИмяПрефикса_ИмяЭлемента (например, АЛ_СтатусДоставки, Расш1_СуммаСкидки).

Альтернатива без программирования: Дополнительные реквизиты БСП

Прежде чем приступать к написанию программного кода для вывода новых полей, проанализируем ситуацию на предмет использования штатного функционала БСП. В современных типовых конфигурациях (ERP, Комплексная автоматизация, Управление торговлей, Управление нашей фирмой, Бухгалтерия предприятия) присутствует мощный встроенный механизм — Дополнительные реквизиты и сведения.

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

  1. Перейдите в раздел Администрирование -> Общие настройки -> Дополнительные реквизиты и сведения.
  2. Выберите нужный документ или справочник и добавьте новый реквизит необходимого типа (число, строка, дата, ссылка на справочник).
  3. БСП автоматически выведет этот реквизит в специальную группу на форме (обычно это вкладка "Дополнительно" или динамическая группа внизу формы).

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

← На главную