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

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

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

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

Почему нельзя программно добавить параметр в коллекцию "Параметры" внутри формы?

Для начала выясним причину платформенного ограничения. Коллекция Параметры управляемой формы имеет тип ДанныеФормыСтруктура. В отличие от обычной коллекции типа Структура, состав полей объекта ДанныеФормыСтруктура жестко фиксируется платформой 1С на этапе инициализации формы. Этот состав определяется:

  1. Стандартными параметрами расширения формы (такими как Ключ, ЗначениеЗаполнения, ЗакрыватьПриВыборе и др.).
  2. Пользовательскими параметрами, которые разработчик явным образом объявил на вкладке «Параметры» в редакторе формы в конфигураторе.

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

Способ 1. Передача параметра в месте открытия формы (Классический вариант)

Самый простой и очевидный способ — передать нужный параметр непосредственно в момент вызова функции открытия формы. Рассмотрим этот вариант подробнее.

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


ПараметрыОткрытия = Новый Структура;
ПараметрыОткрытия.Вставить("ИмяВашегоПараметра", ЗначениеПараметра);
ОткрытьФорму("Справочник.Номенклатура.Форма.ФормаВыбора", ПараметрыОткрытия);

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

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

Способ 2. Использование события "ОбработкаПолученияФормы" (Наиболее чистое решение)

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

Этот обработчик вызывается системой каждый раз, когда запрашивается форма объекта (справочника, документа и т.д.), но сама форма еще не создана. Самое главное для нас — параметр Параметры, передаваемый в эту процедуру, является стандартной коллекцией типа Структура! А значит, мы можем свободно манипулировать ее свойствами.

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

  1. Заимствуем в свое расширение Модуль менеджера того объекта, форму которого требуется открыть (например, справочника Номенклатура или документа РеализацияТоваровУслуг).
  2. Создаем в нем обработчик предопределенной процедуры ОбработкаПолученияФормы с директивой &Перед.
  3. Внедряем наш параметр непосредственно в структуру параметров:

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

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

Способ 3. Программное добавление реквизита формы в "ПриСозданииНаСервере"

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

Посмотрим на пример реализации такого подхода через расширение формы с использованием метода ИзменитьРеквизиты:


&Перед("ПриСозданииНаСервере")
Процедура Расш_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // Создаем массив для новых реквизитов
    ДобавляемыеРеквизиты = Новый Массив;
    
    // Описываем новый реквизит
    ИмяРеквизита = "Расш_ДополнительноеСвойство";
    ТипРеквизита = Новый ОписаниеТипов("Булево");
    НовыйРеквизит = Новый РеквизитФормы(ИмяРеквизита, ТипРеквизита, , "Доп. Свойство");
    
    ДобавляемыеРеквизиты.Добавить(НовыйРеквизит);
    
    // Применяем изменения к форме
    ЭтотОбъект.ИзменитьРеквизиты(ДобавляемыеРеквизиты);
    
    // Теперь мы можем программно устанавливать и читать значение этого реквизита
    ЭтотОбъект[ИмяРеквизита] = Истина;
КонецПроцедуры

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

Жизненный цикл параметров: Обычные vs Ключевые

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

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

← На главную