В типовых конфигурациях 1С, таких как Управление торговлей 11, ERP 2 или Комплексная автоматизация 2, часто встречается специфический фрагмент кода, который вызывает вопросы у начинающих (и даже опытных) разработчиков. Речь идет о связке методов РеквизитФормыВЗначение, УстановитьСсылкуНового и ЗначениеВДанныеФормы. На первый взгляд может показаться, что этот код не выполняет никакой полезной работы, однако за ним стоит важная логика платформы 1С:Предприятие 8.3.
В данной статье мы подробно разберем, зачем нужна эта конструкция, как она работает «под капотом» и можно ли применить аналогичный подход к произвольным реквизитам формы, например, к ссылкам на другие документы.
Рассмотрим классический пример кода, который часто встречается в модулях форм типовых решений:
Значение = РеквизитФормыВЗначение("Объект", Тип("ДокументОбъект.ЧекККМ"));
Значение.УстановитьСсылкуНового(Документы.ЧекККМ.ПолучитьСсылку());
ЗначениеВДанныеФормы(Значение, Объект);
Проанализируем ситуацию по шагам. Что здесь происходит?
РеквизитФормыВЗначение мы превращаем данные управляемой формы (которые имеют тип ДанныеФормыСтруктура) в полноценный объект типа ДокументОбъект. Это необходимо, так как метод УстановитьСсылкуНового доступен только для объектов, но не для данных формы.Документы.ЧекККМ.ПолучитьСсылку() создает новую пустую ссылку (уникальный идентификатор — GUID), которая еще не записана в базе данных.УстановитьСсылкуНового мы говорим системе: «Когда этот конкретный объект будет записываться в базу, не создавай для него новый GUID, а используй именно этот зарезервированный идентификатор».ЗначениеВДанныеФормы переносит состояние объекта (включая информацию о зарезервированной ссылке) обратно в реквизит управляемой формы Объект.Выясним причину, по которой разработчики 1С используют такой подход. Основная цель — получение ссылки на объект до его физической записи в базу данных. Это критически важно в следующих сценариях:
Посмотрим на вопрос автора темы: можно ли провернуть то же самое с реквизитом, имеющим тип ДокументСсылка.РеализацияТоваровУслуг? Здесь кроется важное техническое ограничение платформы.
Метод РеквизитФормыВЗначение работает только с объектами. Если ваш реквизит формы является просто ссылкой (ДокументСсылка), то он неизменяем по своей сути. Вы не можете «установить ссылку нового» для уже существующей ссылки. Ссылка — это просто указатель на место в памяти базы данных.
Однако, если ваш дополнительный реквизит формы добавлен как Объект (то есть вы вручную добавили реквизит с типом ДокументОбъект... в список реквизитов формы), то к нему можно применить этот код. Но в 99% случаев реквизиты, не являющиеся основным объектом формы, создаются как ссылочные типы, поэтому для них этот фокус не сработает.
В обсуждении на форуме высказывались мнения, что этот код ничего не делает, так как при конвертации ЗначениеВДанныеФормы ссылка нового якобы теряется. Давайте проанализируем ситуацию глубже:
Технический факт: Метод ЗначениеВДанныеФормы действительно сохраняет информацию о ссылке нового внутри структуры данных формы. Хотя визуально в поле «Ссылка» в отладчике вы все равно будете видеть <...> (объект не записан), платформа запоминает установленный GUID. При последующей интерактивной записи или вызове Записать() на сервере, система подставит именно тот идентификатор, который вы зарезервировали.
Побочные эффекты: Стоит помнить, что вызов РеквизитФормыВЗначение — это ресурсозатратная операция (сериализация). Если ваша цель — просто получить ссылку для заполнения какого-то поля на форме, убедитесь, что это действительно необходимо. В современных версиях платформы (8.3.10+) появились альтернативные методы работы со ссылками, но в коде БСП (Библиотеки стандартных подсистем) данный метод остается «золотым стандартом» для обеспечения совместимости.
Рассмотрим ключевые выводы нашего анализа:
ДокументОбъект, СправочникОбъект). Для простых ссылочных реквизитов (ДокументСсылка) это неприменимо.Таким образом, если вам нужно «провернуть» подобное с реквизитом, который является ссылкой на другой документ — сначала убедитесь, что этот документ действительно является «новым» в текущем контексте и что вы работаете с его объектным представлением в памяти, а не просто с указателем в базе данных.