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