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

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

При переходе с обычного приложения на управляемые формы многие разработчики сталкиваются с неприятным сюрпризом: переменные, объявленные в модуле объекта, внезапно «забывают» свои значения между открытием формы и записью документа. Особенно остро эта проблема встает в крупных типовых конфигурациях, таких как 1С:ERP, КА или УТ 11, где требуется передать технический параметр (например, флаг для записи в независимый регистр сведений), не создавая лишних реквизитов в самом объекте. Рассмотрим подробно, почему это происходит и как правильно реализовать передачу данных, следуя стандартам разработки.

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

Для начала проанализируем, почему глобальные переменные модуля объекта в управляемом приложении теряют актуальность. В отличие от версии 7.7 или обычных форм 8.2, управляемая форма работает по принципу отсутствия состояния (stateless) при взаимодействии клиента и сервера. Разберем жизненный цикл объекта по шагам:

  1. Серверный вызов при создании: Выполняется процедура ОбработкаЗаполнения. Платформа создает экземпляр ДокументОбъект, заполняет его и… тут же уничтожает его после того, как данные будут сконвертированы в тип ДанныеФормыСтруктура (реквизит Объект в форме).
  2. Жизнь на клиенте: Пользователь видит форму. В памяти клиента нет никакого «Объекта» в понимании сервера, есть только структура данных формы. Все переменные модуля объекта, которые вы заполнили на шаге 1, уже стерты.
  3. Запись объекта: Когда пользователь нажимает кнопку «Записать», происходит новый серверный вызов. Платформа создает совершенно новый экземпляр ДокументОбъект, «накатывает» на него данные из формы и вызывает обработчики записи.

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

Использование свойства ДополнительныеСвойства

Одним из самых эффективных инструментов является свойство ДополнительныеСвойства. Это структура, которая принадлежит объекту и предназначена именно для хранения временных данных, не сохраняемых в базе данных. Рассмотрим пример, как можно добавить значение в эту структуру:


// В модуле объекта
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
    ДополнительныеСвойства.Вставить("МойТехническийПараметр", "Значение");
КонецПроцедуры

Однако, как мы выяснили выше, при открытии формы это свойство очистится, так как объект будет пересоздан. Чтобы данные «выжили», мы должны использовать реквизиты формы как промежуточное хранилище.

Пошаговый алгоритм передачи данных

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

Шаг 1. Создание реквизита формы.

В редакторе формы документа создадим новый реквизит (не путать с реквизитом объекта!). Назовем его, например, ПараметрДляРегистра. Тип выберем соответствующий нашим данным. Если мы не хотим менять структуру формы в метаданных, мы можем создать его программно в процедуре ПриСозданииНаСервере.

Шаг 2. Захват данных при инициализации.

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


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

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

Шаг 3. Передача данных в объект перед записью.

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


&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    
    // Параметр ТекущийОбъект — это и есть наш ДокументОбъект, 
    // подготовленный к записи. Помещаем данные в его структуру.
    ТекущийОбъект.ДополнительныеСвойства.Вставить("ДанныеДляРегистра", ЭтаФорма.ПараметрДляРегистра);
    
КонецПроцедуры

Шаг 4. Использование данных в модуле объекта.

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


// В модуле объекта
Процедура ПриЗаписи(Отказ)
    
    Если ДополнительныеСвойства.Свойство("ДанныеДляРегистра") Тогда
        ЗначениеПараметра = ДополнительныеСвойства.ДанныеДляРегистра;
        // Вызываем менеджер регистра и записываем данные
        РегистрыСведений.МойНезависимыйРегистр.СоздатьЗапись(ЗначениеПараметра, ЭтотОбъект.Ссылка);
    КонецЕсли;
    
КонецПроцедуры

Почему не стоит использовать глобальные переменные модуля?

Выясним, почему старый подход с объявлением Перем МояПеременная Экспорт в начале модуля объекта считается плохим тоном в современной разработке. Во-первых, такие переменные не сериализуются автоматически. Во-вторых, они живут ровно столько, сколько живет конкретный серверный вызов. Если ваша логика предполагает цепочку «Клиент — Сервер — Клиент», данные будут потеряны. Использование ДополнительныеСвойства является «легальным» и штатным способом передачи контекста, который понятен любому другому разработчику, работающему с типовыми конфигурациями.

Альтернативные варианты для ERP

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

  1. Временное хранилище: Помещаем данные в хранилище, а в форму передаем только АдресХранилища (строку). Этот адрес сохраняем в реквизите формы и в момент записи извлекаем данные на сервере.
  2. Расширения конфигурации: Если конфигурация типовая, лучше добавить нужный реквизит прямо в объект через расширение. Это избавит от необходимости писать сложный код по «пробрасыванию» свойств, так как платформа сама обеспечит синхронизацию реквизита между формой и объектом.
  3. Дополнительные сведения (БСП): Если данные не нужны для проведения, а носят справочный характер, используйте механизм дополнительных сведений, который уже встроен в ERP.

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

← На главную