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

