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