Почему не получается прочитать ДополнительныеСвойства в форме объекта и как это исправить

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

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

Разбор проблемы: почему ДополнительныеСвойства очищаются

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

Проанализируем ситуацию по шагам:

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

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

Решение 1: Использование параметров формы

Если вы инициируете копирование или создание объекта программно, самым правильным и «чистым» методом будет использование параметров формы. Рассмотрим пример, когда нам нужно передать значение в открываемую форму:


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

ОткрытьФорму("Справочник.ВашСправочник.ФормаОбъекта", ПараметрыОткрытия);

Затем в модуле формы мы можем легко перехватить эти данные:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Если Параметры.Свойство("НоваяСсылкаНаОбъект") Тогда
        // Используем переданное значение
        Сообщить(Параметры.НоваяСсылкаНаОбъект);
    КонецЕсли;
КонецПроцедуры

Решение 2: ОбработкаЗаполнения вместо ПриКопировании

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

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

Решение 3: Временное хранилище (универсальный «костыль»)

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

Суть метода заключается в следующем:

  1. В модуле объекта (в событии ПриКопировании) мы помещаем данные в хранилище.
  2. Для идентификации данных используем уникальный ключ (GUID).
  3. Передаем этот ключ в форму (через реквизит или параметр).
  4. В форме извлекаем данные.

Пример реализации в модуле объекта:


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

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

Почему РеквизитФормыВЗначение не решает задачу

Выясним причину заблуждения относительно функции РеквизитФормыВЗначение. Эта функция предназначена для преобразования данных, которые уже находятся в форме (в реквизите Объект), в объектную сущность 1С (например, СправочникОбъект), чтобы вызвать его методы (например, Записать()).

Когда вы вызываете РеквизитФормыВЗначение("Объект"), платформа:

  1. Создает новый пустой экземпляр объекта.
  2. Заполняет его реквизиты значениями из формы.

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

Рекомендации и итоги

Подводя итог нашему разбору, выделим основные правила работы с данными при создании/копировании объектов:

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

← На главную