При разработке в среде 1С:Предприятие 8.3, особенно при кастомизации типовых конфигураций с помощью расширений, программисты часто сталкиваются с необходимостью передать в открываемую форму дополнительные данные. Логичным и интуитивным решением кажется расширить коллекцию Параметры непосредственно внутри обработчика события ПриСозданииНаСервере. Однако при попытке сделать это напрямую разработчик неизбежно сталкивается с системными ограничениями платформы.
В этой статье мы подробно разберем, почему стандартный подход с добавлением новых ключей в коллекцию параметров внутри самой формы не работает, и проанализируем три элегантных и безопасных способа решения этой задачи с минимальным вмешательством в типовой код.
Для начала выясним причину платформенного ограничения. Коллекция Параметры управляемой формы имеет тип ДанныеФормыСтруктура. В отличие от обычной коллекции типа Структура, состав полей объекта ДанныеФормыСтруктура жестко фиксируется платформой 1С на этапе инициализации формы. Этот состав определяется:
Ключ, ЗначениеЗаполнения, ЗакрыватьПриВыборе и др.).Когда управление передается в серверную процедуру ПриСозданииНаСервере, состав полей коллекции Параметры уже окончательно сформирован и заблокирован для изменений. Попытка вызвать метод Вставить() для добавления нового ключа, который не был задекларирован в метаданных формы, вызовет критическую ошибку выполнения. Платформа просто не позволит динамически расширить структуру на данном этапе.
Самый простой и очевидный способ — передать нужный параметр непосредственно в момент вызова функции открытия формы. Рассмотрим этот вариант подробнее.
Если у нас есть возможность изменить вызывающий код (например, если форма открывается из нашей собственной обработки или нетипового модуля), мы можем передать параметр стандартным образом через структуру параметров открытия:
ПараметрыОткрытия = Новый Структура;
ПараметрыОткрытия.Вставить("ИмяВашегоПараметра", ЗначениеПараметра);
ОткрытьФорму("Справочник.Номенклатура.Форма.ФормаВыбора", ПараметрыОткрытия);
Важный нюанс: чтобы открываемая форма смогла прочитать этот параметр в процедуре ПриСозданииНаСервере, сам параметр должен быть заранее объявлен в свойствах этой формы. Для этого достаточно заимствовать целевую форму в расширение и на вкладке «Параметры» добавить новое свойство с типом данных, соответствующим передаваемому значению.
Однако, что делать, если вызов ОткрытьФорму происходит внутри объемного типового кода, который крайне нежелательно заимствовать в расширение ради одной строчки? Перейдем к более изящным методам.
Проанализируем ситуацию: нам нужно внедрить параметр «на лету» до того, как форма начнет инициализироваться, но при этом мы не хотим трогать модули, где написана команда открытия. В платформе 1С 8.3 для этого предусмотрен великолепный механизм — обработчик ОбработкаПолученияФормы в модуле менеджера объекта.
Этот обработчик вызывается системой каждый раз, когда запрашивается форма объекта (справочника, документа и т.д.), но сама форма еще не создана. Самое главное для нас — параметр Параметры, передаваемый в эту процедуру, является стандартной коллекцией типа Структура! А значит, мы можем свободно манипулировать ее свойствами.
Разберем по шагам, как это реализовать:
Номенклатура или документа РеализацияТоваровУслуг).ОбработкаПолученияФормы с директивой &Перед.
&Перед("ОбработкаПолученияФормы")
Процедура Расш_ОбработкаПолученияФормы(ВидФормы, Параметры, ВыбраннаяФорма, ДополнительнаяИнформация, СтандартнаяОбработка)
// Проверяем условия, при которых нужно добавить параметр
Если ВидФормы = "ФормаОбъекта" Тогда
Параметры.Вставить("Расш_МойДополнительныйПараметр", Истина);
КонецЕсли;
КонецПроцедуры
Поскольку эта процедура отрабатывает до создания контекста формы, добавленный ключ без проблем перекочует в итоговую коллекцию Параметры открываемой формы. Нам останется лишь заимствовать саму форму в расширение и добавить этот параметр на вкладку «Параметры» в конфигураторе, чтобы платформа не отбросила его при инициализации.
Бывают случаи, когда логика работы формы требует наличия дополнительного флага или переменной, но менять логику передачи параметров категорически неудобно или невозможно. В такой ситуации мы можем программно расширить саму форму, добавив в нее новый реквизит во время выполнения процедуры ПриСозданииНаСервере. Для добавления необходимых реквизитов без ручной разработки можно использовать инструмент для добавления реквизитов и элементов на управляемые формы.
Посмотрим на пример реализации такого подхода через расширение формы с использованием метода ИзменитьРеквизиты:
&Перед("ПриСозданииНаСервере")
Процедура Расш_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Создаем массив для новых реквизитов
ДобавляемыеРеквизиты = Новый Массив;
// Описываем новый реквизит
ИмяРеквизита = "Расш_ДополнительноеСвойство";
ТипРеквизита = Новый ОписаниеТипов("Булево");
НовыйРеквизит = Новый РеквизитФормы(ИмяРеквизита, ТипРеквизита, , "Доп. Свойство");
ДобавляемыеРеквизиты.Добавить(НовыйРеквизит);
// Применяем изменения к форме
ЭтотОбъект.ИзменитьРеквизиты(ДобавляемыеРеквизиты);
// Теперь мы можем программно устанавливать и читать значение этого реквизита
ЭтотОбъект[ИмяРеквизита] = Истина;
КонецПроцедуры
Важное предостережение: этот метод создает полноценный реквизит формы, доступный в контексте сервера и клиента. Однако помните, что если типовой алгоритм, выполняющийся в середине процедуры ПриСозданииНаСервере, жестко завязан на чтение именно из коллекции Параметры (например, Параметры.ВашПараметр), данный способ не сработает напрямую без перенаправления логики чтения на созданный реквизит формы.
При проектировании взаимодействия между формами крайне важно понимать внутреннюю кухню платформы 1С, связанную с жизненным циклом параметров. Все параметры формы делятся на две категории:
ПриСозданииНаСервере успешно завершает свою работу, платформа автоматически очищает коллекцию Параметры от обычных параметров в целях оптимизации потребления оперативной памяти. Если вам потребуется это значение в дальнейшем (например, на клиенте), обязательно запишите его в реквизит формы в процессе создания.Параметры на протяжении всего жизненного цикла формы, как на сервере, так и на клиенте.Используя предложенные методики, вы сможете гибко настраивать передачу данных между формами в расширениях 1С, сохраняя чистоту типовой конфигурации и обеспечивая простоту последующих обновлений системы. Для ускорения доработки форм кодом можно использовать текучий конструктор для программной модификации управляемых форм.