1С 8.3 Получение родителей элемента
Данные > Примеры кода 1С > 1С 8.3 Справочники
Перейти в раздел примеры кода 1С 8.3:
- 1С 8.3 Планы видов характеристик

Обновлено 04.08.2025:
Функция ТекстЗапросаДляПолученияРодителейВсехУровнейИерархии генерирует запрос для получения всех родителей в иерархической структуре справочника в 1С. Полезна для сложных аналитических запросов, где нужно учитывать всю иерархию элементов, а не только непосредственных родителей. Пруф кода автора.
Создает запрос, который:
- Находит все родительские элементы для каждого элемента справочника
- Учитывает все уровни иерархии
- Может работать как с обычными элементами, так и с группами
- Поддерживает различные варианты вывода результатов
Логика работы:
- Сначала создается "пролог" запроса, который формирует начальные связи (дуги длиной 1) между элементами и их непосредственными родителями.
- Затем многократно применяется "рефрен", который находит связи большей длины путем соединения уже найденных связей.
- В конце формируется "эпилог", который выводит итоговый результат в нужном формате.
- Все шаблонные строки заменяются на реальные значения параметров.
Особенности:
- Использует алгоритм нахождения транзитивного замыкания для иерархии
- Поддерживает параметризацию имен таблиц и колонок
- Позволяет ограничивать набор элементов, для которых ищутся родители
- Может выводить результат как во временную таблицу
Пример использования:
Запрос = ТекстЗапросаДляПолученияРодителейВсехУровнейИерархии("Номенклатура",10,"Родитель",Истина,"ВТРодителиНоменклатуры");
Функция генерирует запрос для получения всех родителей в иерархии справочника с учетом всех уровней вложенности в 1С 8.3:
// Транзитивное замыкание иерархии
//
// Параметры:
// ИмяСправочника - строка - Имя справочника (обязательный)
// МаксимальнаяДлинаПути - число - Макс. уровней вложенности (по умолчанию 8)
// ИмяРеквизитаИерархии - строка - Реквизит иерархии (по умолчанию "Родитель")
// ПолучитьРодителейГрупп - булево - Включать группы (по умолчанию Ложь)
// ИмяВременнойТаблицы - строка - Имя ВТ для результата (необязательный)
// ИмяПараметраСЭлементами - строка - Ограничение по элементам (необязательный)
// ИмяКолонкиЭлемент - строка - Имя колонки элемента (по умолчанию "Ссылка")
// ИмяКолонкиРодитель - строка - Имя колонки родителя (по умолчанию "Родитель")
//
// Возвращаемое значение:
// Строка - текст запроса для получения иерархии
//
&НаКлиентеНаСервереБезКонтекста
Функция ТекстЗапросаДляПолученияРодителейВсехУровнейИерархии(
Знач ИмяСправочника,
Знач МаксимальнаяДлинаПути = 8,
Знач ИмяРеквизитаИерархии = "Родитель",
Знач ПолучитьРодителейГрупп = Ложь,
Знач ИмяВременнойТаблицы = "",
Знач ИмяПараметраСЭлементами = "",
Знач ИмяКолонкиЭлемент = "Ссылка",
Знач ИмяКолонкиРодитель = "Родитель")
// ========== ПОДГОТОВКА ЧАСТЕЙ ЗАПРОСА ==========
// 1. Пролог запроса - создаем начальные связи (дуги длиной 1)
Пролог =
"ВЫБРАТЬ
| #ИмяРеквизитаИерархии КАК НачалоДуги,
| Ссылка КАК КонецДуги
|ПОМЕСТИТЬ ЗамыканияДлины1
|ИЗ Справочник.#ИмяСправочника
|ГДЕ #ИмяРеквизитаИерархии <> Значение(Справочник.#ИмяСправочника.ПустаяСсылка)
|ОБЪЕДИНИТЬ
|ВЫБРАТЬ
| Ссылка,
| Ссылка
|ИЗ Справочник.#ИмяСправочника
|#СтрУсловия;";
// Формируем условия выборки
СтрУсловия = "";
// Если задан параметр с элементами - добавляем условие IN
Если Не ПустаяСтрока(ИмяПараметраСЭлементами) Тогда
СтрУсловия = "ГДЕ Ссылка В(&" + ИмяПараметраСЭлементами + ")";
КонецЕсли;
// Если не нужно включать группы - добавляем соответствующее условие
Если Не ПолучитьРодителейГрупп Тогда
Если Не ПустаяСтрока(СтрУсловия) Тогда
СтрУсловия = СтрУсловия + " И ЭтоГруппа = Ложь";
Иначе
СтрУсловия = "ГДЕ ЭтоГруппа = Ложь";
КонецЕсли;
КонецЕсли;
// Вставляем условия в пролог
Пролог = СтрЗаменить(Пролог, "#СтрУсловия", СтрУсловия);
// 2. Рефрен запроса - рекурсивно находим связи большей длины
Рефрен =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| ПерваяДуга.НачалоДуги,
| ВтораяДуга.КонецДуги
|ПОМЕСТИТЬ ЗамыканияДлины#2
|ИЗ ЗамыканияДлины#1 КАК ПерваяДуга
|ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЗамыканияДлины#1 КАК ВтораяДуга
| ПО ПерваяДуга.КонецДуги = ВтораяДуга.НачалоДуги;
|УНИЧТОЖИТЬ ЗамыканияДлины#1;";
// 3. Эпилог запроса - формируем итоговый результат
Эпилог =
"ВЫБРАТЬ
| НачалоДуги КАК #ИмяКолонкиРодитель,
| КонецДуги КАК #ИмяКолонкиЭлемент" +
?(ПустаяСтрока(ИмяВременнойТаблицы), "", " ПОМЕСТИТЬ " + ИмяВременнойТаблицы) +
" ИЗ ЗамыканияДлины#2
|ГДЕ НачалоДуги <> КонецДуги"
// ========== ФОРМИРОВАНИЕ ТЕКСТА ЗАПРОСА ==========
ТекстЗапроса = Пролог;
ТекущаяДлинаЗамыканий = 1;
// Рекурсивно находим все связи, удваивая длину на каждом шаге
Пока ТекущаяДлинаЗамыканий < МаксимальнаяДлинаПути Цикл
НоваяДлина = 2 * ТекущаяДлинаЗамыканий;
// Добавляем очередную часть запроса
ТекстЗапроса = ТекстЗапроса + СтрЗаменить(СтрЗаменить(Рефрен,
"#1", Формат(ТекущаяДлинаЗамыканий, "ЧГ=0")),
"#2", Формат(НоваяДлина, "ЧГ=0"));
ТекущаяДлинаЗамыканий = НоваяДлина;
КонецЦикла;
// Добавляем эпилог и очистку временных таблиц
ТекстЗапроса = ТекстЗапроса +
СтрЗаменить(Эпилог, "#2", Формат(ТекущаяДлинаЗамыканий, "ЧГ=0")) +
"; УНИЧТОЖИТЬ ЗамыканияДлины" + Формат(ТекущаяДлинаЗамыканий, "ЧГ=0");
// ========== ЗАМЕНА ПЛЕЙСХОЛДЕРОВ НА РЕАЛЬНЫЕ ЗНАЧЕНИЯ ==========
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ИмяСправочника", ИмяСправочника);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ИмяРеквизитаИерархии", ИмяРеквизитаИерархии);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ИмяКолонкиЭлемент", ИмяКолонкиЭлемент);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ИмяКолонкиРодитель", ИмяКолонкиРодитель);
Возврат ТекстЗапроса;
КонецФункции
//
// Параметры:
// ИмяСправочника - строка - Имя справочника (обязательный)
// МаксимальнаяДлинаПути - число - Макс. уровней вложенности (по умолчанию 8)
// ИмяРеквизитаИерархии - строка - Реквизит иерархии (по умолчанию "Родитель")
// ПолучитьРодителейГрупп - булево - Включать группы (по умолчанию Ложь)
// ИмяВременнойТаблицы - строка - Имя ВТ для результата (необязательный)
// ИмяПараметраСЭлементами - строка - Ограничение по элементам (необязательный)
// ИмяКолонкиЭлемент - строка - Имя колонки элемента (по умолчанию "Ссылка")
// ИмяКолонкиРодитель - строка - Имя колонки родителя (по умолчанию "Родитель")
//
// Возвращаемое значение:
// Строка - текст запроса для получения иерархии
//
&НаКлиентеНаСервереБезКонтекста
Функция ТекстЗапросаДляПолученияРодителейВсехУровнейИерархии(
Знач ИмяСправочника,
Знач МаксимальнаяДлинаПути = 8,
Знач ИмяРеквизитаИерархии = "Родитель",
Знач ПолучитьРодителейГрупп = Ложь,
Знач ИмяВременнойТаблицы = "",
Знач ИмяПараметраСЭлементами = "",
Знач ИмяКолонкиЭлемент = "Ссылка",
Знач ИмяКолонкиРодитель = "Родитель")
// ========== ПОДГОТОВКА ЧАСТЕЙ ЗАПРОСА ==========
// 1. Пролог запроса - создаем начальные связи (дуги длиной 1)
Пролог =
"ВЫБРАТЬ
| #ИмяРеквизитаИерархии КАК НачалоДуги,
| Ссылка КАК КонецДуги
|ПОМЕСТИТЬ ЗамыканияДлины1
|ИЗ Справочник.#ИмяСправочника
|ГДЕ #ИмяРеквизитаИерархии <> Значение(Справочник.#ИмяСправочника.ПустаяСсылка)
|ОБЪЕДИНИТЬ
|ВЫБРАТЬ
| Ссылка,
| Ссылка
|ИЗ Справочник.#ИмяСправочника
|#СтрУсловия;";
// Формируем условия выборки
СтрУсловия = "";
// Если задан параметр с элементами - добавляем условие IN
Если Не ПустаяСтрока(ИмяПараметраСЭлементами) Тогда
СтрУсловия = "ГДЕ Ссылка В(&" + ИмяПараметраСЭлементами + ")";
КонецЕсли;
// Если не нужно включать группы - добавляем соответствующее условие
Если Не ПолучитьРодителейГрупп Тогда
Если Не ПустаяСтрока(СтрУсловия) Тогда
СтрУсловия = СтрУсловия + " И ЭтоГруппа = Ложь";
Иначе
СтрУсловия = "ГДЕ ЭтоГруппа = Ложь";
КонецЕсли;
КонецЕсли;
// Вставляем условия в пролог
Пролог = СтрЗаменить(Пролог, "#СтрУсловия", СтрУсловия);
// 2. Рефрен запроса - рекурсивно находим связи большей длины
Рефрен =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| ПерваяДуга.НачалоДуги,
| ВтораяДуга.КонецДуги
|ПОМЕСТИТЬ ЗамыканияДлины#2
|ИЗ ЗамыканияДлины#1 КАК ПерваяДуга
|ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЗамыканияДлины#1 КАК ВтораяДуга
| ПО ПерваяДуга.КонецДуги = ВтораяДуга.НачалоДуги;
|УНИЧТОЖИТЬ ЗамыканияДлины#1;";
// 3. Эпилог запроса - формируем итоговый результат
Эпилог =
"ВЫБРАТЬ
| НачалоДуги КАК #ИмяКолонкиРодитель,
| КонецДуги КАК #ИмяКолонкиЭлемент" +
?(ПустаяСтрока(ИмяВременнойТаблицы), "", " ПОМЕСТИТЬ " + ИмяВременнойТаблицы) +
" ИЗ ЗамыканияДлины#2
|ГДЕ НачалоДуги <> КонецДуги"
// ========== ФОРМИРОВАНИЕ ТЕКСТА ЗАПРОСА ==========
ТекстЗапроса = Пролог;
ТекущаяДлинаЗамыканий = 1;
// Рекурсивно находим все связи, удваивая длину на каждом шаге
Пока ТекущаяДлинаЗамыканий < МаксимальнаяДлинаПути Цикл
НоваяДлина = 2 * ТекущаяДлинаЗамыканий;
// Добавляем очередную часть запроса
ТекстЗапроса = ТекстЗапроса + СтрЗаменить(СтрЗаменить(Рефрен,
"#1", Формат(ТекущаяДлинаЗамыканий, "ЧГ=0")),
"#2", Формат(НоваяДлина, "ЧГ=0"));
ТекущаяДлинаЗамыканий = НоваяДлина;
КонецЦикла;
// Добавляем эпилог и очистку временных таблиц
ТекстЗапроса = ТекстЗапроса +
СтрЗаменить(Эпилог, "#2", Формат(ТекущаяДлинаЗамыканий, "ЧГ=0")) +
"; УНИЧТОЖИТЬ ЗамыканияДлины" + Формат(ТекущаяДлинаЗамыканий, "ЧГ=0");
// ========== ЗАМЕНА ПЛЕЙСХОЛДЕРОВ НА РЕАЛЬНЫЕ ЗНАЧЕНИЯ ==========
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ИмяСправочника", ИмяСправочника);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ИмяРеквизитаИерархии", ИмяРеквизитаИерархии);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ИмяКолонкиЭлемент", ИмяКолонкиЭлемент);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ИмяКолонкиРодитель", ИмяКолонкиРодитель);
Возврат ТекстЗапроса;
КонецФункции
Обновлено 2023-2024:
Получение родителей элемента Справочника или Плана видов характеристик в 1С 8.3:
&НаСервере
Функция ПолучениеВсехРодителейЭлемента(ЭлементСсылка, Знач КолВыбЗаОперацию = 10)
// ЭлементСсылка - СправочникСсылка, ПланВидовХарактеристикСсылка - Ссылка на элемент, родителей которого нужно найти
// КолВыбЗаОперацию - Количество выбираемых родителей за одно выполнение функции запроса
РодителиЭлемента = Новый Массив;
Если НЕ ЗначениеЗаполнено(ЭлементСсылка) Тогда
Возврат РодителиЭлемента;
КонецЕсли;
МетаданныеЭл = ЭлементСсылка.Метаданные();
Если МетаданныеЭл.ОграничиватьКоличествоУровней Тогда
// Минимальное количество или из переданного или из ограничения количества уровней метаданных
КолВыбЗаОперацию = Мин(КолВыбЗаОперацию, МетаданныеЭл.КоличествоУровней);
КонецЕсли;
МассивПолей = Новый Массив;
ВыбПоле = "Родитель";
Для НомерРодителя = 1 По КолВыбЗаОперацию Цикл
МассивПолей.Добавить(ВыбПоле);
ВыбПоле = ВыбПоле + ".Родитель";
КонецЦикла;
ТекстЗапроса = "ВЫБРАТЬ %1 ИЗ %2 ГДЕ Ссылка = &ТекЭлемент";
ТекстЗапроса = СтрШаблон(ТекстЗапроса, СтрСоединить(МассивПолей, ","), МетаданныеЭл.ПолноеИмя());
Запрос = Новый Запрос(ТекстЗапроса);
ТекЭлемент = ЭлементСсылка;
Пока ЗначениеЗаполнено(ТекЭлемент) Цикл
Запрос.УстановитьПараметр("ТекЭлемент", ТекЭлемент);
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Прервать;
КонецЕсли;
Выборка = Результат.Выбрать();
Выборка.Следующий();
Для НомерКолонки = 0 По Результат.Колонки.Количество() - 1 Цикл
ТекЭлемент = Выборка[НомерКолонки];
Если ЗначениеЗаполнено(ТекЭлемент) Тогда
РодителиЭлемента.Добавить(ТекЭлемент);
Иначе
Прервать;
КонецЕсли;
КонецЦикла;
КонецЦикла;
// Возвращаем Массив[СправочникСсылка, ПланВидовХарактеристикСсылка] со всеми родителями элемента
Возврат РодителиЭлемента;
КонецФункции
Функция ПолучениеВсехРодителейЭлемента(ЭлементСсылка, Знач КолВыбЗаОперацию = 10)
// ЭлементСсылка - СправочникСсылка, ПланВидовХарактеристикСсылка - Ссылка на элемент, родителей которого нужно найти
// КолВыбЗаОперацию - Количество выбираемых родителей за одно выполнение функции запроса
РодителиЭлемента = Новый Массив;
Если НЕ ЗначениеЗаполнено(ЭлементСсылка) Тогда
Возврат РодителиЭлемента;
КонецЕсли;
МетаданныеЭл = ЭлементСсылка.Метаданные();
Если МетаданныеЭл.ОграничиватьКоличествоУровней Тогда
// Минимальное количество или из переданного или из ограничения количества уровней метаданных
КолВыбЗаОперацию = Мин(КолВыбЗаОперацию, МетаданныеЭл.КоличествоУровней);
КонецЕсли;
МассивПолей = Новый Массив;
ВыбПоле = "Родитель";
Для НомерРодителя = 1 По КолВыбЗаОперацию Цикл
МассивПолей.Добавить(ВыбПоле);
ВыбПоле = ВыбПоле + ".Родитель";
КонецЦикла;
ТекстЗапроса = "ВЫБРАТЬ %1 ИЗ %2 ГДЕ Ссылка = &ТекЭлемент";
ТекстЗапроса = СтрШаблон(ТекстЗапроса, СтрСоединить(МассивПолей, ","), МетаданныеЭл.ПолноеИмя());
Запрос = Новый Запрос(ТекстЗапроса);
ТекЭлемент = ЭлементСсылка;
Пока ЗначениеЗаполнено(ТекЭлемент) Цикл
Запрос.УстановитьПараметр("ТекЭлемент", ТекЭлемент);
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Прервать;
КонецЕсли;
Выборка = Результат.Выбрать();
Выборка.Следующий();
Для НомерКолонки = 0 По Результат.Колонки.Количество() - 1 Цикл
ТекЭлемент = Выборка[НомерКолонки];
Если ЗначениеЗаполнено(ТекЭлемент) Тогда
РодителиЭлемента.Добавить(ТекЭлемент);
Иначе
Прервать;
КонецЕсли;
КонецЦикла;
КонецЦикла;
// Возвращаем Массив[СправочникСсылка, ПланВидовХарактеристикСсылка] со всеми родителями элемента
Возврат РодителиЭлемента;
КонецФункции
Получение запросом родителей элемента справочника в 1С 8.3:
&НаСервере
Процедура ПолучениеЗапросомРодителейЭлементаСправочника(СсылкаНаКонтрагента)
КонтрагентСсылка=СсылкаНаКонтрагента;
// Специальных средств для получения родителей элементов справочника в запросе нет,
// поэтому целесообразно родителей перебирать в цикле
// На примере справочника контрагентов с макс.глубиной 10 вложений
Запрос = Новый Запрос("ВЫБРАТЬ
| Контрагент.Родитель,
| Контрагент.Родитель.Родитель,
| Контрагент.Родитель.Родитель.Родитель,
| Контрагент.Родитель.Родитель.Родитель.Родитель,
| Контрагент.Родитель.Родитель.Родитель.Родитель.Родитель,
| Контрагент.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель,
| Контрагент.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель,
| Контрагент.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель,
| Контрагент.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель,
| Контрагент.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель,
|ИЗ
| Справочник.Контрагенты КАК Контрагент
|ГДЕ
| Контрагент.Ссылка = &КонтрагентСсылка");
Пока Истина Цикл
Запрос.УстановитьПараметр("КонтрагентСсылка", КонтрагентСсылка);
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Прервать;
КонецЕсли;
Выборка = Результат.Выбрать();
Выборка.Следующий();
Для НомерКолонки = 0 По Результат.Колонки.Количество() - 1 Цикл
КонтрагентСсылка = Выборка[НомерКолонки];
Если КонтрагентСсылка = Справочники.Контрагенты.ПустаяСсылка() Тогда
Прервать;
Иначе
Сообщить("Родитель элемента "+КонтрагентСсылка);
КонецЕсли;
КонецЦикла;
Если КонтрагентСсылка = Справочники.Контрагенты.ПустаяСсылка() Тогда
Прервать;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ПолучениеЗапросомРодителейЭлементаСправочника(СсылкаНаКонтрагента)
КонтрагентСсылка=СсылкаНаКонтрагента;
// Специальных средств для получения родителей элементов справочника в запросе нет,
// поэтому целесообразно родителей перебирать в цикле
// На примере справочника контрагентов с макс.глубиной 10 вложений
Запрос = Новый Запрос("ВЫБРАТЬ
| Контрагент.Родитель,
| Контрагент.Родитель.Родитель,
| Контрагент.Родитель.Родитель.Родитель,
| Контрагент.Родитель.Родитель.Родитель.Родитель,
| Контрагент.Родитель.Родитель.Родитель.Родитель.Родитель,
| Контрагент.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель,
| Контрагент.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель,
| Контрагент.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель,
| Контрагент.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель,
| Контрагент.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель,
|ИЗ
| Справочник.Контрагенты КАК Контрагент
|ГДЕ
| Контрагент.Ссылка = &КонтрагентСсылка");
Пока Истина Цикл
Запрос.УстановитьПараметр("КонтрагентСсылка", КонтрагентСсылка);
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Прервать;
КонецЕсли;
Выборка = Результат.Выбрать();
Выборка.Следующий();
Для НомерКолонки = 0 По Результат.Колонки.Количество() - 1 Цикл
КонтрагентСсылка = Выборка[НомерКолонки];
Если КонтрагентСсылка = Справочники.Контрагенты.ПустаяСсылка() Тогда
Прервать;
Иначе
Сообщить("Родитель элемента "+КонтрагентСсылка);
КонецЕсли;
КонецЦикла;
Если КонтрагентСсылка = Справочники.Контрагенты.ПустаяСсылка() Тогда
Прервать;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Получить всех родителей элемента (Экспортная) в 1С 8.3:
// Возвращает всех родителей элемента, согласно рекомендациям на ИТС:
// см. 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 Цикл
ТекущийЭлемент = Выборка[НомерКолонки]; // см. РодителиЭлемента.Ссылка
Если ЗначениеЗаполнено(ТекущийЭлемент) Тогда
РодителиЭлемента.Добавить(ТекущийЭлемент);
Иначе
Прервать;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Возврат РодителиЭлемента;
КонецФункции
// MIT License
// Copyright (c) 2024 SeiOkami
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// см. 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 Цикл
ТекущийЭлемент = Выборка[НомерКолонки]; // см. РодителиЭлемента.Ссылка
Если ЗначениеЗаполнено(ТекущийЭлемент) Тогда
РодителиЭлемента.Добавить(ТекущийЭлемент);
Иначе
Прервать;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Возврат РодителиЭлемента;
КонецФункции
// MIT License
// Copyright (c) 2024 SeiOkami
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
Обновлено 2021:
Получить родителей элемента прямой работой с объектом в 1С 8.3:
// Процедура выводит в сообщения всех родителей элемента в иерархии
//
// Параметры:
// Элемент - СправочникОбъект, ДокументОбъект или другой объект с иерархией - элемент, для которого нужно вывести родителей
//
Процедура ВывестиРодительскуюИерархию(Элемент) Экспорт
// Проверяем, что переданный объект существует
Если Элемент = Неопределено Тогда
ВызватьИсключение "Не передан элемент для вывода иерархии!";
КонецЕсли;
// Получаем родителя текущего элемента
Родитель = Элемент.Родитель;
// Если родитель существует (иерархия не закончилась)
Если Родитель <> Неопределено И НЕ Родитель.Пустая() Тогда
// Выводим текущий элемент
Сообщить(Элемент);
// Рекурсивно вызываем эту же функцию для родителя
ВывестиРодительскуюИерархию(Родитель);
Иначе
// Выводим последний элемент в цепочке (корневой)
Сообщить(Элемент);
КонецЕсли;
КонецПроцедуры
//
// Параметры:
// Элемент - СправочникОбъект, ДокументОбъект или другой объект с иерархией - элемент, для которого нужно вывести родителей
//
Процедура ВывестиРодительскуюИерархию(Элемент) Экспорт
// Проверяем, что переданный объект существует
Если Элемент = Неопределено Тогда
ВызватьИсключение "Не передан элемент для вывода иерархии!";
КонецЕсли;
// Получаем родителя текущего элемента
Родитель = Элемент.Родитель;
// Если родитель существует (иерархия не закончилась)
Если Родитель <> Неопределено И НЕ Родитель.Пустая() Тогда
// Выводим текущий элемент
Сообщить(Элемент);
// Рекурсивно вызываем эту же функцию для родителя
ВывестиРодительскуюИерархию(Родитель);
Иначе
// Выводим последний элемент в цепочке (корневой)
Сообщить(Элемент);
КонецЕсли;
КонецПроцедуры
0
комментарии
____________________
Перепечатка текста и фотографий разрешена при наличии прямой ссылки на источник