Каталог решений - Заполнение дерева из табличных данных без рекурсии

Заполнение дерева из табличных данных без рекурсии

Заполнение дерева из табличных данных без рекурсии

В наличии

Предлагаю вашему вниманию альтернативный алгоритм построения дерева из данных документа или регистра. Этот способ позволяет без рекурсии построить иерархическую структуру данных. Для правильной работы у элемента данных должен быть ключ связи (родитель) и идентификатор элемента с где каталоги (узлы) младше элементов (файлов).

Категория:

Описание

Идея заложена в неком контейнере, выпрямителе лесинки иерархических
данных в двумерный массив. В моём варианте этим контейнером служит
соответствие. Создаем контейнер, извлекаем данне запросом, сортируя по
идентификатору. Если данные собирались в таблицу с помощью рекурсивной
процедуры/функции, то узлы иерархии создаются раньше элемента,
соответственно идентификатор элемента всегда старше родительского узла.

Дальше начинаем создавать дерево заполняя его свойство строки, новыми
строками и параллельно вносим узлы в соответствие. Таким образом когда
мы находимся на очередном элементе в соответствии можно найти
родительскую строку дерева. В итоге выстраивается дерево.

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

        Запрос.УстановитьПараметр("Ссылка", Документ.Ссылка);
        Запрос.Текст = СтрЗаменить(Запрос.Текст, "&Документ", "Документ." + Документ.Метаданные().Имя + "." + ИмяТабЧасти);
    
        Результат = Запрос.Выполнить();

        ВыборкаДетальныеЗаписи = Результат.Выбрать();

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

Надеюсь данный алгоритм может вам пригодится или расширит ваш кругозор.

has been added to your cart:
Оформление заказа