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

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

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

Причина проблемы: различие между объектом и ссылкой

Проанализируем типовую ошибку, которая часто возникает в коде создания элементов. Если функция создания группы возвращает сам экземпляр СправочникОбъект (созданный через СоздатьГруппу()), а не полученную после записи ссылку, присвоение реквизиту завершится некорректно:


// Ошибочный вариант:
НовыйОбъект = Справочники.ВидыНоменклатуры.СоздатьГруппу();
НовыйОбъект.Наименование = "Поставщик";
НовыйОбъект.Записать();
Возврат НовыйОбъект; // Возвращается СправочникОбъект, а не ссылка!

Реквизит Родитель любого иерархического справочника в 1С строго типизирован и принимает исключительно значение типа СправочникСсылка.<ИмяСправочника> (либо пустую ссылку того же типа). Если попытаться записать в него объектную переменную типа СправочникОбъект, платформа не сможет выполнить неявное приведение типов, и поле Родитель останется незаполненным.

Для корректной работы функции создания родительской группы необходимо возвращать свойство Ссылка уже записанного объекта:


// Корректный вариант:
Возврат НовыйОбъект.Ссылка;

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

Рассмотрим комплексное решение задачи: создание нового элемента с предварительным поиском группы-родителя и ее автоматическим созданием в случае отсутствия.

  1. Поиск существующей группы: проверяем наличие группы по наименованию с помощью точного соответствия или запроса.
  2. Создание группы при отсутствии: если ссылка пустая, создаем новую группу через СоздатьГруппу(), записываем ее и получаем ссылку.
  3. Создание подчиненного элемента: создаем новый элемент через СоздатьЭлемент(), устанавливаем реквизит Родитель и выполняем запись.

Посмотрим на практическую реализацию с использованием встроенного метода поиска НайтиПоНаименованию():


&НаСервере
Процедура СоздатьЭлементВГруппе()
    
    СсылкаНаРодителя = ПолучитьИлиСоздатьГруппу("Поставщик");
    
    НовыйЭлемент = Справочники.ВидыНоменклатуры.СоздатьЭлемент();
    НовыйЭлемент.Наименование = "Мебель";
    НовыйЭлемент.Родитель     = СсылкаНаРодителя;
    
    // При необходимости заполняем обязательные реквизиты конфигурации
    НовыйЭлемент.Записать();
    
КонецПроцедуры

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

Поиск группы с помощью запроса

Использование метода НайтиПоНаименованию() не гарантирует, что найденный элемент является именно группой (папкой), а не обычным элементом справочника с таким же именем. Чтобы исключить неоднозначность, рекомендуется выполнять поиск с помощью запроса с отбором по полю ЭтоГруппа:


&НаСервере
Функция НайтиГруппуПоНаименованию(ИмяГруппы)
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 1
        |	Спр.Ссылка КАК Ссылка
        |ИЗ
        |	Справочник.ВидыНоменклатуры КАК Спр
        |ГДЕ
        |	Спр.ЭтоГруппа = ИСТИНА
        |	И Спр.Наименование = &Наименование";
    
    Запрос.УстановитьПараметр("Наименование", ИмяГруппы);
    
    Выборка = Запрос.Выполнить().Выбрать();
    Если Выборка.Следующий() Тогда
        Возврат Выборка.Ссылка;
    КонецЕсли;
    
    // Если группа не найдена, создаем новую
    НоваяГруппа = Справочники.ВидыНоменклатуры.СоздатьГруппу();
    НоваяГруппа.Наименование = ИмяГруппы;
    НоваяГруппа.Записать();
    
    Возврат НоваяГруппа.Ссылка;
    
КонецФункции

Важные особенности и возможные ошибки

Разберем дополнительные нюансы платформы и типовых конфигураций (таких как 1С:Управление торговлей 11, 1С:ERP или 1С:Комплексная автоматизация):

  1. Вид иерархии в метаданных: если для справочника установлен вид «Иерархия элементов» (а не «Иерархия групп и элементов»), метод СоздатьГруппу() вызовет исключение. В таком случае и группы, и элементы создаются через СоздатьЭлемент().
  2. Ограничение уровней иерархии: если в свойствах справочника задано ограничение по количеству уровней, попытка записать элемент глубже разрешенного уровня приведет к ошибке платформы.
  3. Контроль обязательных реквизитов: в типовых решениях модуль объекта проверяет заполнение обязательных полей (например, ТипНоменклатуры для справочника «Виды номенклатуры»). Если они не заполнены, запись завершится ошибкой. При пакетной загрузке данных без типовых проверок можно использовать флаг Объект.ОбменДанными.Загрузка = Истина.
  4. Точное соответствие при поиске: метод НайтиПоНаименованию() по умолчанию ищет по вхождению с начала строки (ТочноеСоответствие = Ложь). Чтобы избежать нахождения посторонних элементов (например, «Поставщики оборудования» вместо «Поставщик»), всегда явно указывайте второй параметр: НайтиПоНаименованию("Поставщик", Истина).
← На главную