Получить всех родителей элемента
Теги: 1С,Запрос,Запросы,Справочник,Желтый Чайник 1С

Возвращает всех родителей элемента, согласно рекомендациям на ИТС:
"Получение всех родителей элемента" (https://its.1c.ru/db/metod8dev/content/2659/hdoc)

# Код реализации

```1c
// Возвращает всех родителей элемента, согласно рекомендациям на ИТС:
// см. https://its.1c.ru/db/metod8dev/content/2659/hdoc
// Источник: https://github.com/SeiOkami/CollectionMethodsOneS/issues/14
//
// Параметры:
//  Ссылка  - СправочникСсылка, ПланВидовХарактеристикСсылка - Ссылка на элемент, родителей которого нужно найти
//  КоличествоВыбираемыхЗаПорцию  - Число - Количество выбираемых родителей за одно выполнение запроса.
//		Используется минимальное число из переданного и ограничения количества уровней в конфигураторе
//
// Возвращаемое значение:
//   Массив из СправочникСсылка, ПланВидовХарактеристикСсылка - массив с родителями элемента
//
// Пример:
//
//   Результат = РодителиЭлемента(ЭлементБазы);
//   //Результат - массив с ссылками на родителей элемента
//
Функция РодителиЭлемента(Знач Ссылка, Знач КоличествоВыбираемыхЗаПорцию = 5) Экспорт

	РодителиЭлемента = Новый Массив; // Массив из см. РодителиЭлемента.Ссылка
	Если НЕ ЗначениеЗаполнено(Ссылка) Тогда
		Возврат РодителиЭлемента;
	КонецЕсли;

	МетаданныеЭлемента = Ссылка.Метаданные();
	Если МетаданныеЭлемента.ОграничиватьКоличествоУровней Тогда
		КоличествоВыбираемыхЗаПорцию = Мин(КоличествоВыбираемыхЗаПорцию, МетаданныеЭлемента.КоличествоУровней);
	КонецЕсли;

	ВыбираемыеПоля = Новый Массив; // Массив из Строка
	ВыбираемоеПоле = "Родитель";
	Для НомерРодителя = 1 По КоличествоВыбираемыхЗаПорцию Цикл
		ВыбираемыеПоля.Добавить(ВыбираемоеПоле);
		ВыбираемоеПоле = ВыбираемоеПоле + ".Родитель";
	КонецЦикла;

	ТекстЗапроса = "ВЫБРАТЬ %1 ИЗ %2 ГДЕ Ссылка = &ТекущийЭлемент";
	ТекстЗапроса = СтрШаблон(ТекстЗапроса, СтрСоединить(ВыбираемыеПоля, ","), МетаданныеЭлемента.ПолноеИмя());
	Запрос = Новый Запрос(ТекстЗапроса);

	ТекущийЭлемент = Ссылка;
	Пока ЗначениеЗаполнено(ТекущийЭлемент) Цикл

		Запрос.УстановитьПараметр("ТекущийЭлемент", ТекущийЭлемент);
		Результат = Запрос.Выполнить(); //@skip-check query-in-loop
		Если Результат.Пустой() Тогда
			Прервать;
		КонецЕсли;

		Выборка = Результат.Выбрать();
		Выборка.Следующий();
		Для НомерКолонки = 0 По Результат.Колонки.Количество() - 1 Цикл
			ТекущийЭлемент = Выборка[НомерКолонки]; // см. РодителиЭлемента.Ссылка
			Если ЗначениеЗаполнено(ТекущийЭлемент) Тогда
				РодителиЭлемента.Добавить(ТекущийЭлемент);
			Иначе
				Прервать;
			КонецЕсли;
		КонецЦикла;

	КонецЦикла;

	Возврат РодителиЭлемента;

КонецФункции
```

# Примечания

- А если количество уровней не ограничено и надо выбрать всех родителей?
ИМХО рекурсией будет универсальнее

- (1) Константин Аванесов, в чём проблема?
*Количество выбираемых родителей за одно выполнение запроса. *
Зачем здесь нужна рекурсия и чем именно это будет "универсальнее" ?
Данный метод и так универсален.

- (2) SeiOkami, проще же можно:
&НаСервереБезКонтекста
Функция РодителиЭлемента(Знач СсылкаНаЭлемент)
		
		РодителиЭлемента = Новый Массив;

		Пока ЗначениеЗаполнено(СсылкаНаЭлемент.Родитель) Цикл
			РодителиЭлемента.Вставить(0, СсылкаНаЭлемент.Родитель);
			СсылкаНаЭлемент = СсылкаНаЭлемент.Родитель;
		КонецЦикла;
		
		Возврат РодителиЭлемента;
		
КонецФункции;

- (3) alah, Представьте ситуацию, у вас есть справочник "Номенклатура" в элементы/группы которого, добавлена картинка в высоком разрешении и теперь представьте, сколько будет выполнятся функция получения всех родителей элемента?

- (3) alah, это проще, но хуже
https://its.1c.ru/db/metod8dev/content/2659/hdoc