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

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

При разработке обработок регистрации в 1С часто возникает задача одновременного создания нескольких связанных объектов. Типичный пример: создание Контрагента и связанного с ним Пользователя. Основная сложность для начинающих разработчиков заключается в правильной передаче ссылки одного объекта в реквизит другого. Рассмотрим подробно, как это реализовать и какие нюансы платформы 1С:Предприятие 8 необходимо учитывать.

Разбор основной ошибки: Тип данных «Строка» против «Ссылки»

Проанализируем ситуацию, когда разработчик пытается присвоить реквизиту с типом СправочникСсылка.Контрагенты текстовое значение, например, Наименование. В 1С это приводит к тому, что система пытается выполнить неявное преобразование. Поскольку строка с ФИО не является уникальным идентификатором ссылки, в реквизит записывается ПустаяСсылка. Выясним причину: реквизит справочника ожидает объект типа «Ссылка», а не просто текст.

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

Шаг 1. Правильная последовательность создания объектов

Чтобы заполнить реквизит Клиент в справочнике Пользователи, нам уже нужно иметь созданного клиента. Следовательно, в коде создание Контрагента должно стоять выше создания Пользователя. Разберем пример кода, реализующий эту логику:


// Сначала создаем и записываем Контрагента
НовыйКлиент = Справочники.Контрагенты.СоздатьЭлемент();
НовыйКлиент.Наименование = Объект.ФИО;
НовыйКлиент.Телефон = Объект.Телефон;
// Обязательно записываем, чтобы получить ссылку
НовыйКлиент.Записать(); 

// Теперь создаем Пользователя
НовыйПользователь = Справочники.Пользователи.СоздатьЭлемент();
НовыйПользователь.Наименование = Объект.ФИО;
// Присваиваем именно ССЫЛКУ на только что созданного контрагента
НовыйПользователь.Клиент = НовыйКлиент.Ссылка; 
НовыйПользователь.Записать();

В этом примере мы используем свойство Ссылка объекта НовыйКлиент. Важно помнить, что до вызова метода Записать() ссылка у нового объекта может быть пустой (если не использован метод УстановитьСсылкуНового()), поэтому порядок вызовов критичен.

Шаг 2. Контекст исполнения (Клиент и Сервер)

Важно понимать, что работа с объектами (метод СоздатьЭлемент) в управляемом приложении возможна только в контексте &НаСервере. Если вы пишете код в модуле формы обработки, процедура должна выглядеть следующим образом:


&НаКлиенте
Процедура Зарегистрировать(Команда)
    ЗарегистрироватьНаСервере();
КонецПроцедуры

&НаСервере
Процедура ЗарегистрироватьНаСервере()
    // Логика создания объектов, описанная выше
КонецПроцедуры

Шаг 3. Обеспечение целостности данных через транзакции

Проанализируем ситуацию: что произойдет, если Контрагент создастся успешно, а при записи Пользователя возникнет ошибка (например, из-за нарушения уникальности логина)? В базе останется «сиротская» запись контрагента. Чтобы этого избежать, мы рекомендуем использовать транзакции. Рассмотрим подробнее реализацию:


НачатьТранзакцию();
Попытка
    // Создание контрагента
    НовыйКлиент = Справочники.Контрагенты.СоздатьЭлемент();
    НовыйКлиент.Наименование = ФИО;
    НовыйКлиент.Записать();

    // Создание пользователя
    НовыйПользователь = Справочники.Пользователи.СоздатьЭлемент();
    НовыйПользователь.Наименование = ФИО;
    НовыйПользователь.Клиент = НовыйКлиент.Ссылка;
    НовыйПользователь.Записать();

    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    Сообщить("Ошибка при регистрации: " + ОписаниеОшибки());
КонецПопытки;

Шаг 4. Поиск дублей перед созданием

Чтобы не плодить одинаковые записи при каждом нажатии кнопки, перед созданием следует выполнить поиск. Посмотрим на пример использования метода НайтиПоНаименованию:


СсылкаНаКлиента = Справочники.Контрагенты.НайтиПоНаименованию(ФИО);

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

// Теперь используем СсылкаНаКлиента для заполнения реквизита Пользователя

Дополнительные рекомендации

Для оптимизации кода и повышения его надежности следует придерживаться следующих правил:

  1. Использование ЗаполнитьЗначенияСвойств: Если реквизиты обработки называются так же, как в справочнике, используйте ЗаполнитьЗначенияСвойств(НовыйКлиент, Объект);. Это сократит количество строк кода.
  2. Режим загрузки данных: Если вы выполняете массовую регистрацию, установите свойство ОбменДанными.Загрузка = Истина; перед записью объекта. Это отключит лишние проверки в модуле объекта и ускорит работу.
  3. Проверка заполнения: Перед записью всегда проверяйте, заполнены ли обязательные поля, чтобы избежать системных ошибок записи.

Таким образом, мы выяснили, что для решения задачи необходимо соблюдать строгую типизацию данных (передавать ссылку, а не строку) и придерживаться правильной последовательности действий: Создание -> Запись -> Получение ссылки -> Использование ссылки в другом объекте.

← На главную