Как найти максимальный уровень строк исходного дерева значений и вывести его на форму в реквизит "Уровень"?

1. sergqwert15 4 10.04.21 18:06 Сейчас в теме
Как найти максимальный уровень строк исходного дерева значений и вывести его на форму в реквизит "Уровень"? Во время отладки возникает ошибка Поле объекта не обнаружено (СтрокиДЗ)
{Обработка.Тест4.Форма.Форма.Форма(48)}: КоличествоУровней(ДеревоЗначений.СтрокиДЗ);
{Обработка.Тест4.Форма.Форма.Форма(42)}: ВыполнитьРезультатНаСервере();

Код ниже:

&НаСервере
Процедура ВыполнитьРезультатНаСервере()
    КоличествоУровней(ДеревоЗначений.СтрокиДЗ);
КонецПроцедуры

Функция КоличествоУровней(СтрокиДЗ)
    
    Если СтрокиДЗ.Количество() = 0 Тогда Возврат 0 КонецЕсли;
    
    КоличествоУровней = 0;
    Для Каждого СтрокаДЗ ИЗ СтрокиДЗ Цикл
        КоличествоУровней = Макс(КоличествоУровней(СтрокаДЗ.Строки), КоличествоУровней);
    КонецЦикла;
    
    Возврат КоличествоУровней + 1;
   
КонецФункции
Показать
Прикрепленные файлы:
Тест4.epf
По теме из базы знаний
Ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. nomad_irk 81 10.04.21 18:11 Сейчас в теме
(1) СтрокиДЗ есть Строки, а не строкиДЗ.

Если вы передаете строку в качестве параметра функции, должно быть

Для Каждого СтрокаДЗ ИЗ СтрокиДЗ.Строки Цикл
3. mity1982 10.04.21 18:57 Сейчас в теме
Я так понял там упр. формы, соответственно тип значения реквизита - ДанныеФормыДерево а не ДеревоЗначений.

ДеревоЗначений1 = РеквизитФормыВЗначение(ДеревоЗначений); //Получаем ДеревоЗначений
Далее обходите рекурсией как вы и делаете (только учтите первый комментарий, свойство "Строки" а не "СтрокиДЗ").
Можно обходить и само ДанныеФормыДерево (метод ПолучитьЭлементы()). Но это долго, гораздо дольше чем ДеревоЗначений.

Вообще обходить дерево - долго. Лучше при добавлении строк запомнить максимальный уровень.

С деревьями на форме работают обычно РеквизитФормыВЗначение -> ДеревоЗначений -> ЗначениеВРеквизитФормы. Но при этом теряются идентификаторы строк, и слетает текущая строка дерева после серверного вызова :(. Что бы восстановить текущую строку я бы перед серверным вызовом записал некий адрес текущей строки [1,2,3] и потом установил бы туда текущую строку. Как их то красивых решений этой проблемы не находил.
4. sergqwert15 4 11.04.21 19:50 Сейчас в теме
&НаСервере
Процедура ВыполнитьРезультатНаСервере()
    ДеревоЗначенийРек  = РеквизитФормыВЗначение("ДеревоЗначений");
    //ДеревоЗначенийРек.Строки.Очистить();
    КоличествоУровней(ДеревоЗначенийРек.Строки);
    ЗначениеВРеквизитФормы(ДеревоЗначенийРек, "ДеревоЗначений");
        
КонецПроцедуры

Функция КоличествоУровней(СтрокиДЗ)
    
Если СтрокиДЗ.Количество() = 0 Тогда Возврат 0 КонецЕсли;

   КоличествоУровней = 0;
   Для Каждого СтрокаДЗ ИЗ СтрокиДЗ Цикл
     КоличествоУровней = Макс(КоличествоУровней(СтрокаДЗ.Строки), КоличествоУровней);
   КонецЦикла;

   Возврат КоличествоУровней + 1;
   
КонецФункции

Показать


Получается максимальный уровень = 3, а нужно КоличествоУровней = 4 в итоге. Как быть?
5. user1572509 09.03.23 18:55 Сейчас в теме
(4) Уж не знаю, на сколько актуально (ну мало ли, вдруг кому-то пригодится), но я бы сделал так – увеличивал уровень после определения, есть ли подчиненные строки и перед их обходом:

&НаКлиенте
Процедура ВыполнитьРезультат(Команда)
    ВыполнитьРезультатНаСервере();
КонецПроцедуры

&НаСервере
Процедура ВыполнитьРезультатНаСервере()
    
    МаксимальныйУровень = 0;
    РеквизитДерево = РеквизитФормыВЗначение("ДеревоЗначений");
    
    СтрокиДереваЗначений = РеквизитДерево.Строки;
    Если СтрокиДереваЗначений.Количество() > 0 тогда
        ТекущийУровень = 1;
        ОбойтиСтрокиДерева(СтрокиДереваЗначений,ТекущийУровень,МаксимальныйУровень);
    КонецЕсли;
    
    Уровень = МаксимальныйУровень;
        
КонецПроцедуры

&НаСервере
Процедура ОбойтиСтрокиДерева(СтрокиДереваЗначений,ТекущийУровень,МаксимальныйУровень)
    
    Для каждого СтрокаДерева из СтрокиДереваЗначений цикл
        Если СтрокаДерева.Строки.Количество() > 0 тогда 
            //Если текущая строка дерева содержит подчиненные строки,
            //значит, получаем значение следующего уровня... 
            СледующийУровень = ТекущийУровень + 1;          
            //...и обходим его строки
            ОбойтиСтрокиДерева(СтрокаДерева.Строки,СледующийУровень,МаксимальныйУровень);
        Иначе
            //Если текущая строка дерева не содержит подчиненных строк,
            //то определим, является ли текущий уровень максимальным
            МаксимальныйУровень = Макс(ТекущийУровень,МаксимальныйУровень);
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры
Показать
6. Arxxximed 37 26.04.23 18:06 Сейчас в теме
 Функция МаксимальныйУровеньДЗ(ДеревоЗначений) 

    МаксУровень = 0;    
    КопияДЗ = ДеревоЗначений.Скопировать();
    КопияДЗ.Колонки.Добавить("ДляВыгрузки",Новый ОписаниеТипов("Число",
            Новый КвалификаторыЧисла(1, 0, ДопустимыйЗнак.Неотрицательный)));    
    МассивСтрок = КопияДЗ.Строки.НайтиСтроки(Новый Структура("ДляВыгрузки",0),Истина);
    Для Каждого СтрокаДЗ Из МассивСтрок Цикл
        МаксУровень = Макс(МаксУровень, СтрокаДЗ.Уровень());    
        
    КонецЦикла;
    Возврат МаксУровень;
КонецФункции 
Показать

Вроде быстрее работает, чем рекурсивный обход.
Риник; +1 Ответить
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот