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

02.08.14

Разработка - Универсальные функции

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

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

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

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

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

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

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

Вступайте в нашу телеграмм-группу Инфостарт

Рекурсия Дерево

См. также

Загрузка и выгрузка в Excel Универсальные функции Программист 1С:Предприятие 8 Россия Бесплатно (free)

Описанный ниже подход позволяет в три шага заполнять формулы в Excel файлы, вне зависимости от ОС сервера (MS Windows Server или Linux). Подход подразумевает отказ от работы с COM-объектом в пользу работы через "объектную модель документа" (DOM).

30.10.2025    3458    Abysswalker    8    

45

Универсальные функции Работа с интерфейсом Программист 1С:Предприятие 8 Бесплатно (free)

Порой необходимо временно отключить расширение 1С, не удаляя его, чтобы не потерять данные. Но в этом случае при каждом запуске всем будет лезть уведомление о неактивном расширении, хотя очевидно, это техническая информация, которой не стоит лишний раз пугать пользователей.

14.05.2025    6400    DeerCven    15    

57

Универсальные функции Программист 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

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

21.05.2024    48857    dimanich70    83    

170

Универсальные функции Программист 1С:Предприятие 8 1C:Бухгалтерия Абонемент ($m)

Задача: вставить картинку из буфера обмена на форму средствами платформы 1С.

1 стартмани

18.03.2024    7317    6    John_d    13    

59

Универсальные функции Программист Стажер 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

Пришлось помучиться с GUID-ами немного, решил поделиться опытом, мало ли кому пригодится.

12.02.2024    61096    atdonya    31    

69

Универсальные функции Программист 1С:Предприятие 8 Бесплатно (free)

На заключительных этапах, когда идет отладка или доработка интерфейса, необходимо много раз переоткрыть внешний объект. Вот один из способов автоматизации этого.

30.11.2023    9114    ke.92@mail.ru    17    

68
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Yashazz 4891 05.08.14 10:11 Сейчас в теме
1. Зачем такой изврат, была конкретная нужда?
2. Учите русский, ибо "лесИнка" это перебор;
3. Круче Ильдаровича в этой теме никого нету.
yandextesting; +1 Ответить
2. makc2k 108 06.08.14 00:01 Сейчас в теме
(1) Yashazz, ЛесИнка потому что лесина - лесить жердины (по малоросски, а по белорусски дробына соответственно дробить), а если серьезно, то не хочу модераторов беспокоить пустяком. Данный алгоритм придумал сам без чьей либо помощи, а статья для закрепления в памяти.
ben19791010; +1 Ответить
5. DAnry 9 06.08.14 15:37 Сейчас в теме
(2) что такое "по малоросски", это диалект какой-то? Может вы имели ввиду все же "по украински".
4. Makushimo 160 06.08.14 08:39 Сейчас в теме
(1) Yashazz,
Ildarovich крут, не спорю

но это, однако же, не бред
забираю, спасибо автору
3. gaglo 06.08.14 08:11 Сейчас в теме
А можно все-таки поподробнее, что это за документ, у которого в табличной части дерево, откуда оно туда попало и т.п.?
6. makc2k 108 06.08.14 21:42 Сейчас в теме
Кому как приятнее. Я бы сказал на одном из диалектов группы славянских языков.

Аз - человек воплощенный на земле (в Сербском так и пишут АЗ - я), бога ведает, бога ведая, глаголит добро, есть живой .... Ну и так далее по азбуке.

Дерево в документ я соорудил сам, это для удобства просмотра.
7. Патриот 465 30.09.14 15:13 Сейчас в теме
А "радительского" это от слова "ра", что по Задорновски означало "Солнце" у древних славян? =)
8. makc2k 108 30.09.14 23:29 Сейчас в теме
Родительского - от слова род, а радость - это ра в достатке. Задорнов не икона, не он это придумал. Все это еще 100 лет назад употребимо было.
Для отправки сообщения требуется регистрация/авторизация