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