Идея заложена в неком контейнере, выпрямителе лесинки иерархических данных в двумерный массив. В моём варианте этим контейнером служит соответствие. Создаем контейнер, извлекаем данне запросом, сортируя по идентификатору. Если данные собирались в таблицу с помощью рекурсивной процедуры/функции, то узлы иерархии создаются раньше элемента, соответственно идентификатор элемента всегда старше родительского узла.
Дальше начинаем создавать дерево заполняя его свойство строки, новыми строками и параллельно вносим узлы в соответствие. Таким образом когда мы находимся на очередном элементе в соответствии можно найти родительскую строку дерева. В итоге выстраивается дерево.
// преобразует таблицу в дерево значений с помощью запроса (без рекурсии)
//
// Параметры
// Документ - ДокументСсылка - ссылка на документ табличную часть которого
// нужно преобразовать
// ИмяТабЧасти - Строка - Имя табличной части документа
//
// ИмяПоляСортировки - Строка - Имя поля табличной части документа по которому нужно сортировать данные
// сортировка нужна для того чтобы данные перебирались от корня дерева
//
// ИмяПризнакаКаталога - Строка - Имя поля табличной части документа в котором хранится флаг каталога (узла)
//
// ИмяРодительскгоПоля - Строка - Имя поля табличной части документа в котором хранится номер радительского каталога (узла)
//
// Возвращаемое значение:
// ДервеоЗначений - результат преобразования
//
Функция ЗапросТаблицыПреобразованиеВДерево( Документ,
ИмяТабЧасти,
ИмяПоляСортировки,
ИмяПризнакаКаталога,
ИмяРодительскгоПоля) Экспорт
//создаем соответствие куда будем складывать все строки признаком узла (ЭтоКаталог = Истина)
КонвертДляСтрок = Новый Соответствие;
//Создаем дерево и наполняем колонками
Древо = Новый ДеревоЗначений;
Для Каждого РеквизитТабЧасти Из Документ.Метаданные().ТабличныеЧасти[ИмяТабЧасти].Реквизиты Цикл
Древо.Колонки.Добавить(РеквизитТабЧасти.Имя, РеквизитТабЧасти.Тип);
КонецЦикла;
//извлекаем данные из табличной части документа
//сортировка задается по номеру строки, подразумевается, что узлы имеют более младший номер
//по сравнению с элементами. Именно в таком порядке рекурсивный опрос создает дерево, а мы работаем
//уже с готовым деревом
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| *
|ИЗ
| &Документ КАК Источник
|ГДЕ
| Источник.Ссылка = &Ссылка
|
|УПОРЯДОЧИТЬ ПО
| Источник." + ИмяПоляСортировки;
Запрос.УстановитьПараметр("Ссылка", Документ.Ссылка);
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&Документ", "Документ." + Документ.Метаданные().Имя + "." + ИмяТабЧасти);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
//определяем каталог или элемент и для него определяем ветвь служащую родителем для элемента
Если ВыборкаДетальныеЗаписи[ИмяРодительскгоПоля] = 0 Тогда
Ветвь = Древо;
Иначе
Ветвь = КонвертДляСтрок.Получить(ВыборкаДетальныеЗаписи[ИмяРодительскгоПоля]);
КонецЕсли;
НовСтрокаДерева = Ветвь.Строки.Добавить();
ЗаполнитьЗначенияСвойств(НовСтрокаДерева, ВыборкаДетальныеЗаписи);
//вносим строку с каталогом (узлом) в двумерный список (Соответствие)
Если ВыборкаДетальныеЗаписи[ИмяПризнакаКаталога] Тогда
КонвертДляСтрок.Вставить(ВыборкаДетальныеЗаписи[ИмяПоляСортировки], НовСтрокаДерева);
КонецЕсли;
КонецЦикла;
Возврат Древо;
КонецФункции // ЗапросТаблицыПреобразованиеВДерево()
Надеюсь данный алгоритм может вам пригодится или расширит ваш кругозор. Вступайте в нашу телеграмм-группу Инфостарт