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

02.08.14

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

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

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

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

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

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

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

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

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

См. также

Вставляем картинку из буфера обмена (платформа 1С 8.3.24)

Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

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

1 стартмани

18.03.2024    2854    1    John_d    9    

56

GUID в 1С 8.3 - как с ними быть

Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

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

12.02.2024    4991    atdonya    22    

51

Переоткрытие внешних обработок

Универсальные функции Платформа 1С v8.3 Бесплатно (free)

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

30.11.2023    4091    ke.92@mail.ru    16    

62

Валидация JSON через XDTO (включая массивы)

WEB-интеграция Универсальные функции Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    9324    YA_418728146    6    

143

Печать непроведенных документов для УТ, КА, ERP. Настройка печати по пользователям, документам и печатным формам

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    2197    24    progmaster    7    

3

Расширение: Быстрые отборы через буфер [Alt+C] Копировать список, [Alt+V] Вставить список, [Ctrl+C] Копировать из файлов

Инструментарий разработчика Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

Копирует в буфер значения из списков, из ячеек отчетов, таблиц, настроек списков, других отборов и вставляет в выбранную настройку отбора. Работает с Объект не найден. Работает как в одной так и между разными базами 1С. Использует комбинации [Alt+C] Копировать список, [Alt+V] Вставить список. Также для копирования данных используется стандартная [Ctrl+C] (например из открытого xls, mxl, doc и т.п. файла скопировать список наименований)

1 стартмани

13.10.2022    16327    142    sapervodichka    112    

130

Система контроля ведения учета [БСП]

Универсальные функции Механизмы типовых конфигураций БСП (Библиотека стандартных подсистем) Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

В данном материале рассмотрим типовой алгоритм подсистемы контроля учета БСП в конфигурациях на примерах.

18.07.2022    7343    quazare    8    

110
Комментарии
Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. Yashazz 4722 05.08.14 10:11 Сейчас в теме
1. Зачем такой изврат, была конкретная нужда?
2. Учите русский, ибо "лесИнка" это перебор;
3. Круче Ильдаровича в этой теме никого нету.
yandextesting; +1 Ответить
2. makc2k 107 06.08.14 00:01 Сейчас в теме
(1) Yashazz, ЛесИнка потому что лесина - лесить жердины (по малоросски, а по белорусски дробына соответственно дробить), а если серьезно, то не хочу модераторов беспокоить пустяком. Данный алгоритм придумал сам без чьей либо помощи, а статья для закрепления в памяти.
ben19791010; +1 Ответить
5. DAnry 8 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 107 06.08.14 21:42 Сейчас в теме
Кому как приятнее. Я бы сказал на одном из диалектов группы славянских языков.

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

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