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

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

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

Метод 1: Получение ссылки через Уникальный Идентификатор (GUID)

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

Рассмотрим пример кода, который создает новый заказ покупателя и пытается заполнить автора и хозяйственную операцию:


// Создаем новый объект документа
НовыйЗаказ = Документы.ЗаказПокупателя.СоздатьДокумент();

// Формируем уникальный идентификатор из строки
ИД_Автора = Новый УникальныйИдентификатор("d938890a-e7d0-11ec-9e54-001e67169891");

// Получаем ссылку на элемент справочника "Пользователи"
СсылкаНаАвтора = Справочники.Пользователи.ПолучитьСсылку(ИД_Автора);

// Присваиваем реквизиту
НовыйЗаказ.Автор = СсылкаНаАвтора;

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

Метод 2: Использование функции XMLЗначение

Проанализируем альтернативный и более компактный способ получения ссылки, который часто используют опытные разработчики. Этот метод удобен тем, что позволяет одной строкой преобразовать строковое представление GUID в полноценную ссылку нужного типа.


// Пример получения ссылки на вид цены
НовыйЗаказ.ВидЦен = XMLЗначение(Тип("СправочникСсылка.ВидыЦен"), "9825736f-5026-11d9-b586-000d6144255e");

Этот подход особенно хорош при написании универсальных механизмов загрузки, так как тип ссылки передается параметром в функцию Тип().

Почему реквизиты «затираются» при записи документа

Выясним причину ситуации, когда в отладчике мы видим заполненное поле, но после выполнения метода Записать() значение исчезает. В типовых конфигурациях (таких как УНФ, ERP или Бухгалтерия предприятия) заложена сложная бизнес-логика. Проанализируем основные причины очистки полей:

  1. Взаимозависимость реквизитов. В прикладных решениях 1С существуют «ведущие» реквизиты. Например, в документе «Заказ покупателя» реквизит ХозяйственнаяОперация жестко зависит от реквизита ВидОперации. Если вы программно заполнили только операцию, но оставили пустым вид операции, то при записи сработает стандартный обработчик ПередЗаписью, который увидит несоответствие и перезаполнит (или очистит) зависимое поле.
  2. Подписки на события. Помимо модуля самого документа, существуют глобальные подписки на события записи, которые могут содержать правила проверки и корректировки данных.
  3. Автоматическое заполнение по умолчанию. Программа может пытаться подставить значения на основании настроек текущего пользователя или параметров учетной политики, перекрывая ваши программно установленные данные.

Решение: Всегда заполняйте сначала ключевые реквизиты. Для документов УНФ это часто ВидОперации, Организация и Контрагент. Посмотрим на правильную последовательность заполнения:


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

// Теперь заполняем связанную хозяйственную операцию
НовыйЗаказ.ХозяйственнаяОперация = Справочники.ХозяйственныеОперации.НайтиПоНаименованию("Продажа");

// Только теперь записываем
НовыйЗаказ.Записать(РежимЗаписиДокумента.Запись);

Использование режима загрузки данных

Если ваша задача — перенести исторические данные или выполнить массовую загрузку без срабатывания лишних проверок и алгоритмов конфигурации, следует использовать специальный флаг ОбменДанными.Загрузка. Рассмотрим, как это работает.

Когда свойству ОбменДанными.Загрузка присваивается значение Истина, система понимает, что объект создается внешним механизмом. В этом случае:


НовыйЗаказ = Документы.ЗаказПокупателя.СоздатьДокумент();
НовыйЗаказ.ОбменДанными.Загрузка = Истина; 

// Заполнение всех реквизитов, включая ссылки через GUID
НовыйЗаказ.Автор = Справочники.Пользователи.ПолучитьСсылку(Новый УникальныйИдентификатор("..."));
НовыйЗаказ.ХозяйственнаяОперация = Справочники.ХозяйственныеОперации.ПолучитьСсылку(Новый УникальныйИдентификатор("..."));

// При Загрузка = Истина автоматическая нумерация может не сработать, 
// поэтому номер лучше задать явно или вызвать УстановитьНовыйНомер()
НовыйЗаказ.УстановитьНовыйНомер();
НовыйЗаказ.Записать();

Важное предупреждение: Использование ОбменДанными.Загрузка = Истина требует от разработчика полной ответственности за корректность данных. Система «доверится» вам и запишет даже противоречивые данные, которые впоследствии могут привести к ошибкам в отчетах или при проведении документа.

Проверка корректности ссылок

Чтобы избежать появления пустых значений в базе, перед присвоением ссылки рекомендуется проверить её существование. Рассмотрим, как это сделать правильно:


Идентификатор = Новый УникальныйИдентификатор(СтрокаGUID);
Ссылка = Справочники.Контрагенты.ПолучитьСсылку(Идентификатор);

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

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

← На главную