Как передать данные из управляемой формы документа в модуль проведения через ДополнительныеСвойства?

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

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

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

Почему данные пропадают и в чем сложность?

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

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

Шаг 1. Передача данных при открытии формы

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


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

ОткрытьФорму("Документ.ЗаказПокупателя.Форма.ФормаДокумента", ПараметрыОткрытия);

Шаг 2. Сохранение данных в контексте формы

Теперь в модуле формы документа нам нужно перехватить эти параметры. Поскольку параметры формы живут только в момент ее создания, мы должны сохранить их в реквизит формы.

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

Проанализируем код в модуле формы:


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

В данном примере АдресДополнительныхДанных — это скрытый реквизит объекта (или просто реквизит формы), который позволит нам «вспомнить», где лежат данные в момент записи.

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

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

Выясним, почему именно этот обработчик? В нем нам доступен параметр ТекущийОбъект. Это именно тот экземпляр объекта типа ДокументОбъект, который будет отправлен в базу. Все, что мы запишем в его ДополнительныеСвойства здесь, попадет прямиком в модуль объекта.


&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    
    // Проверяем, есть ли у нас адрес во временном хранилище
    Если ЗначениеЗаполнено(Объект.АдресДополнительныхДанных) Тогда
        
        ДопДанные = ПолучитьИзВременногоХранилища(Объект.АдресДополнительныхДанных);
        
        Если ДопДанные <> Неопределено Тогда
            // «Заряжаем» объект данными для модуля проведения
            ТекущийОбъект.ДополнительныеСвойства.Вставить("ДанныеДляРезервов", ДопДанные);
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Обратите внимание: Если вы попытаетесь использовать Объект.ДополнительныеСвойства (реквизит формы), это не сработает, так как коллекция ДополнительныеСвойства не существует у данных формы. Работаем строго с ТекущийОбъект.

Шаг 4. Обработка данных в модуле объекта

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


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

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

Резюме и рекомендации

Подведем итоги нашего разбора. Чтобы успешно пробросить данные через форму в проведение, придерживайтесь следующего алгоритма:

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

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

← На главную