Как программно заполнить дополнительные реквизиты в новом документе 1С

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

При разработке механизмов создания документов на основании (например, создание Заказа поставщику на основании Заказа клиента) программисты часто сталкиваются с необходимостью переноса не только типовых данных, но и дополнительных реквизитов. Распространенная ошибка заключается в попытке использовать стандартные процедуры БСП (Библиотеки стандартных подсистем) для записи свойств объекта, который еще фактически не существует в базе данных. Разберем детально, почему возникает ошибка «Элемент не выбран» и как правильно реализовать заполнение свойств для новых объектов.

Анализ проблемы: почему стандартные методы БСП не работают для новых объектов

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

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

Различие между дополнительными реквизитами и сведениями

Выясним важную деталь, которая определяет способ программной работы. В системе 1С существуют два типа свойств:

  1. Дополнительные реквизиты — они физически хранятся в табличной части самого объекта (документа или справочника), которая называется ДополнительныеРеквизиты.
  2. Дополнительные сведения — они хранятся в независимом регистре сведений ДополнительныеСведения и связаны с объектом только через его ссылку.

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

Решение №1: Прямое заполнение табличной части (Рекомендуемое)

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

Рассмотрим пример кода, который следует разместить в модуле объекта документа:


Процедура ЗаполнитьДопРеквизитыНаОсновании(ЗаказКлиента)
    
    // 1. Находим ссылки на нужные нам свойства (ПВХ ДополнительныеРеквизитыИСведения)
    // В реальной задаче лучше использовать поиск по имени или предопределенные данные
    СвойствоТипДоставки = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Тип доставки");
    
    // 2. Ищем, нет ли уже такого свойства в табличной части (чтобы не дублировать)
    ПараметрыПоиска = Новый Структура("Свойство", СвойствоТипДоставки);
    НайденныеСтроки = ДополнительныеРеквизиты.НайтиСтроки(ПараметрыПоиска);
    
    Если НайденныеСтроки.Количество() > 0 Тогда
        НоваяСтрока = НайденныеСтроки[0];
    Иначе
        НоваяСтрока = ДополнительныеРеквизиты.Добавить();
        НоваяСтрока.Свойство = СвойствоТипДоставки;
    КонецЕсли;
    
    // 3. Устанавливаем значение (оно должно соответствовать типу, заданному в ПВХ)
    НоваяСтрока.Значение = ЗаказКлиента.ТипДоставки;

КонецПроцедуры

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

Решение №2: Использование методов БСП для существующих объектов

Если перед нами стоит задача обновить дополнительные реквизиты в уже записанном документе, тогда метод УправлениеСвойствами.ЗаписатьСвойстваУОбъекта становится очень удобным. Он берет на себя всю рутину по проверке типов и записи в транзакции.

Проанализируем пример использования этого метода для существующей ссылки:


// Массив структур для передачи в БСП
МассивСвойств = Новый Массив;

СтруктураСвойства = Новый Структура;
СтруктураСвойства.Вставить("Свойство", СвойствоСсылка);
СтруктураСвойства.Вставить("Значение", НужноеЗначение);
МассивСвойств.Добавить(СтруктураСвойства);

// Вызов метода БСП для записи в базу без открытия формы
// ВладелецСвойств - это ССЫЛКА на документ
УправлениеСвойствами.ЗаписатьСвойстваУОбъекта(СсылкаНаДокумент, МассивСвойств);

Важный нюанс: этот метод сразу фиксирует изменения в базе данных. Если вы вызовете его для нового документа, возникнет та самая ошибка, с которой столкнулся автор темы.

Решение №3: Работа с «УстановитьСсылкуНового»

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

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


Процедура ПриЗаписи(Отказ)
    // К этому моменту Ссылка уже валидна
    Если ЭтоНовый Тогда
        МассивСведений = Новый Массив;
        // Заполняем структуру сведений...
        УправлениеСвойствами.ЗаписатьСвойстваУОбъекта(ЭтотОбъект.Ссылка, МассивСведений);
    КонецЕсли;
КонецПроцедуры

Особенности отображения на управляемых формах

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

В управляемых формах БСП дополнительные реквизиты — это динамические элементы. Они не создаются в конфигураторе, а отрисовываются программно при создании формы. Чтобы форма «увидела» программно добавленные в объект строки, в коде формы должны быть вызваны соответствующие стандартные процедуры:

Обычно в типовых конфигурациях (УТ 11, ERP, КА) эти вызовы уже присутствуют. Если вы добавили строки в табличную часть ДополнительныеРеквизиты правильно, они автоматически подтянутся в динамические поля на форме.

Итоги и рекомендации

Проанализировав проблему, мы можем сделать следующие выводы:

  1. Никогда не используйте методы записи свойств, требующие ссылку, для новых (незаписанных) объектов в ОбработкаЗаполнения.
  2. Для заполнения дополнительных реквизитов используйте прямое добавление строк в табличную часть ДополнительныеРеквизиты текущего объекта.
  3. Для поиска свойств в ПВХ используйте имя программного интерфейса или надежные способы поиска, избегая простого НайтиПоНаименованию, если это возможно.
  4. Если необходимо программно заполнить дополнительные сведения, делайте это только после того, как объект получил ссылку (событие ПриЗаписи).

Использование дополнительных реквизитов — это мощный инструмент, позволяющий не перегружать конфигурацию лишними полями. Несмотря на кажущуюся сложность механизмов БСП, работа с ними сводится к пониманию того, где именно хранятся данные: в самом объекте или во внешнем регистре.

← На главную