Восстановление развернутых строк ДереваЗначений после его обновления (управляемая форма)

16.10.15

Разработка - Механизмы платформы 1С

ДеревоЗначений - достаточно простой для работы объект в 1С:Предприятии. И проблем при работе с ним обычно не возникает. Но те приемы, которые используются в обычном приложении, часто перестают работать после перехода на управляемое. В частности, возникла проблема восстановления состояния развернутых ветвей после обновления дерева. Оно целиком сворачивалось, и пользователь терялся. Эта статья будет посвящена вопросу восстановления состояния строк дерева. В качестве "подопытного" использую справочник Номенклатура лишь потому, что он присутствует почти во всех конфигурациях, и почти всегда имеет иерархический вид. Добро пожаловать под кат.

Скачать файлы

Наименование Файл Версия Размер
Восстановление развернутых строк дерева
.epf 9,50Kb
12
.epf 9,50Kb 12 Скачать

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

Анализ задачи привел к следующим выводам:

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

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

&НаКлиенте
Перем СоответствиеИдентификаторовРазвернутыхСтрокДерева;

&НаКлиенте
Процедура ПриОткрытии(Отказ)
	
    // Это соответствие будет хранить идентификаторы строк дерева
    СоответствиеИдентификаторовРазвернутыхСтрокДерева = Новый Соответствие;
	
КонецПроцедуры

У таблицы управляемой формы, связанной с ДеревомЗначений, появляются два события - ПередРазворачиванием() и ПередСворачиваением(). В эти события помещаем алгоритмы добавления/удаления данных по разворачиваемой/сворачиваемой строке дерева.

&НаКлиенте
Процедура ДеревоЗначенийПередРазворачиванием(Элемент, Строка, Отказ)
	
    // Запоминаем идентификатор строки развернутого узла
    ТекущаяСтрока = ДеревоЗначений.НайтиПоИдентификатору(Строка);
    Если ТекущаяСтрока <> Неопределено Тогда
        НайденноеЗначение = СоответствиеИдентификаторовРазвернутыхСтрокДерева.Получить(ТекущаяСтрока.Ссылка);
		
        Если НайденноеЗначение = Неопределено Тогда
            СоответствиеИдентификаторовРазвернутыхСтрокДерева.Вставить(ТекущаяСтрока.Ссылка, Строка);
        КонецЕсли;
    КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ДеревоЗначенийПередСворачиванием(Элемент, Строка, Отказ)
	
    // Если узел свернут, хранить его состояние нам уже не требуется
    ТекущаяСтрока = ДеревоЗначений.НайтиПоИдентификатору(Строка);
    Если ТекущаяСтрока <> Неопределено Тогда
        СоответствиеИдентификаторовРазвернутыхСтрокДерева.Удалить(ТекущаяСтрока.Ссылка);
    КонецЕсли;
	
КонецПроцедуры

При открытии формы дерево заполняется автоматически в событии ПриСозданииНаСервере() и находится с свернутом состоянии.

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	
    // Обновляем дерево значений
    ОбновитьДеревоЗначенийНаСервере();
	
КонецПроцедуры

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

&НаКлиенте
Процедура ОбновитьДеревоЗначений(Команда)

    // Запоминаем текущий выделенный элемент дерева
    ТекущиеДанные = Элементы.ДеревоЗначений.ТекущиеДанные;
    Если ТекущиеДанные <> Неопределено Тогда
        ТекущаяСтрока = ТекущиеДанные.Ссылка;
    Иначе
        ТекущаяСтрока = Неопределено;
    КонецЕсли;
    
    // Для экономии памяти очищаем содержимое дерева на форме
    ДеревоЗначений.ПолучитьЭлементы().Очистить();
    
    // Выполняем обновление дерева иерархии
    ОбновитьДеревоЗначенийНаСервере(СоответствиеИдентификаторовРазвернутыхСтрокДерева, ТекущаяСтрока);
    
    // Пробегаемся по списку и восстанавливаем развернутые узлы
    Для Каждого ЭлементСоответствия Из СоответствиеИдентификаторовРазвернутыхСтрокДерева Цикл
        Элементы.ДеревоЗначений.Развернуть(ЭлементСоответствия.Значение);
    КонецЦикла;
    
    // Выделяем ранее запомненный элемент
    Если ТекущаяСтрока <> Неопределено И ТекущаяСтрока > -1 Тогда
        Элементы.ДеревоЗначений.ТекущаяСтрока = ТекущаяСтрока;
    КонецЕсли;    
    
КонецПроцедуры

Обновление данных дерева выполняем на сервере.

&НаСервере
Процедура ОбновитьДеревоЗначенийНаСервере(СоответствиеИдентификаторовСтрок = Неопределено, ТекущаяСтрока = Неопределено)

    // Определим значение пустой ссылки
    ПустаяСсылка = XMLЗначение(Тип("СправочникСсылка.Номенклатура"), "00000000-0000-0000-0000-000000000000");
    
    // Создадим дерево, значения которого в последующем выгрузим в реквизит формы
    ДеревоОбъект = Новый ДеревоЗначений;
    ДеревоОбъект.Колонки.Добавить("Картинка",     Новый ОписаниеТипов("Картинка"));
    ДеревоОбъект.Колонки.Добавить("Ссылка",       Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
    ДеревоОбъект.Колонки.Добавить("Наименование", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(100, ДопустимаяДлина.Переменная)));
    
    // Выполняем запрос и заполняем дерево
    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    Номенклатура.Ссылка КАК Ссылка,
    |    Номенклатура.Родитель КАК Родитель,
    |    Номенклатура.Наименование КАК Наименование
    |ИЗ
    |    Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |    НЕ Номенклатура.ПометкаУдаления
    |
    |УПОРЯДОЧИТЬ ПО
    |    Номенклатура.ЭтоГруппа,
    |    Номенклатура.Наименование
    |ИТОГИ ПО
    |    Ссылка ИЕРАРХИЯ";
    
    СоответствиеНоменклатурыИСтрокДерева = Новый Соответствие;
    
    Выборка = Запрос.Выполнить().Выбрать();
    Пока Выборка.Следующий() Цикл
        Ссылка           = Выборка.Ссылка;
        СсылкаНаРодителя = Выборка.Родитель;
        
        // Отсеиваем самый верхний уровень и дубли
        Если Ссылка = ПустаяСсылка ИЛИ СоответствиеНоменклатурыИСтрокДерева.Получить(Ссылка) <> Неопределено Тогда 
            Продолжить; 
        КонецЕсли;
        
        // Определяем строку дерева, куда поместим новый элемент
        Если СсылкаНаРодителя <> ПустаяСсылка Тогда 
            Родитель = СоответствиеНоменклатурыИСтрокДерева.Получить(СсылкаНаРодителя); 
        Иначе 
            Родитель = ДеревоОбъект; 
        КонецЕсли;
        
        НовыйЭлемент = Родитель.Строки.Добавить();
        НовыйЭлемент.Наименование = Выборка.Наименование;
        НовыйЭлемент.Ссылка       = Ссылка;
        
        СоответствиеНоменклатурыИСтрокДерева.Вставить(Ссылка, НовыйЭлемент);
    КонецЦикла;
    
    // Если это не первое формирование дерева, то нужно искать развернутые узлы
    Если СоответствиеИдентификаторовСтрок <> Неопределено Тогда
        
        // Создаем таблицу, которая будет хранить информацию по строкам с иерархией
        ТаблицаРазвернутыхСтрокДерева = Новый ТаблицаЗначений;
        ТаблицаРазвернутыхСтрокДерева.Колонки.Добавить("Идентификатор", Новый ОписаниеТипов("Неопределено,Число", Новый КвалификаторыЧисла(10)));
        ТаблицаРазвернутыхСтрокДерева.Колонки.Добавить("Ссылка", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
        ТаблицаРазвернутыхСтрокДерева.Колонки.Добавить("Развернут", Новый ОписаниеТипов("Булево"));
        
        // Добавим индекс для колонок "Ссылка" и "Идентификатор", т.к. по ним идет поиск
        ТаблицаРазвернутыхСтрокДерева.Индексы.Добавить("Ссылка");
        ТаблицаРазвернутыхСтрокДерева.Индексы.Добавить("Идентификатор");
        
        // Перебираем записи соответствия. Если у элемента есть подчиненные, проверяем
        // его на вхождение в соответствие развернутых строк. Если есть совпадение,
        // добавляем в таблицу строк дерева.
        СтруктураОтбора = Новый Структура("Ссылка", Неопределено);
        Для Каждого ЭлементСоответствия Из СоответствиеНоменклатурыИСтрокДерева Цикл
            
            Если ЭлементСоответствия.Значение.Строки.Количество() > 0 Тогда
                Ссылка = ЭлементСоответствия.Ключ;
                
                // Ищем в развернутых узлах
                Идентификатор = СоответствиеИдентификаторовСтрок.Получить(Ссылка);
                Если Идентификатор <> Неопределено Тогда
                    
                    // Исключаем дубли в таблице
                    НайденнаяСтрока = ТаблицаРазвернутыхСтрокДерева.Найти(Ссылка, "Ссылка");
                    Если НайденнаяСтрока = Неопределено Тогда
                        НоваяСтрока = ТаблицаРазвернутыхСтрокДерева.Добавить();
                        НоваяСтрока.Ссылка        = Ссылка;
                        НоваяСтрока.Развернут     = Истина;
                        НоваяСтрока.Идентификатор = Неопределено;
                    КонецЕсли;
                    
                КонецЕсли;
                
            КонецЕсли;
            
        КонецЦикла;        
        
    КонецЕсли;
    
    // Очищаем за ненадобностью соответствие
    СоответствиеНоменклатурыИСтрокДерева.Очистить();
    
    // Сортируем по колонке Наименование и удалем ее за ненадобностью
    ДеревоОбъект.Строки.Сортировать("Наименование", Истина);
    ДеревоОбъект.Колонки.Удалить(ДеревоОбъект.Колонки.Наименование);
    
    // Записываем дерево в реквизит формы
    ЗначениеВРеквизитФормы(ДеревоОбъект, "ДеревоЗначений");
    
    // Очищаем за ненадобностью дерево
    ДеревоОбъект.Строки.Очистить();
    
    Если СоответствиеИдентификаторовСтрок <> Неопределено ТОгда
        // Пробегаемся по дереву формы, чтобы получить индексы строк
        ОбновитьТаблицуИдентификаторовСтрокДереваНаСервере(ТаблицаРазвернутыхСтрокДерева, ДеревоЗначений, ТекущаяСтрока);
    
        // Далее мы обновляем идентификаторы развернутых строк дерева, чтобы потом 
        // использовать для восстановления состояния дерева. Эта процедура
        // необходима из-за того, что после каждого перестроения дерева индексы
        // строк изменяются.
        СоответствиеИдентификаторовСтрок.Очистить();
        
        Для Каждого СтрокаТаблицы Из ТаблицаРазвернутыхСтрокДерева Цикл
            СоответствиеИдентификаторовСтрок.Вставить(СтрокаТаблицы.Ссылка, СтрокаТаблицы.Идентификатор);
        КонецЦикла;
        
    КонецЕсли;
    
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ОбновитьТаблицуИдентификаторовСтрокДереваНаСервере(ТаблицаРазвернутыхСтрокДерева, ДеревоЗначений, ТекущаяСтрока = Неопределено)
    
    // Получаем все элементы строки дерева значений
    СтрокаДереваЗначений = ДеревоЗначений.ПолучитьЭлементы();
    
    Если СтрокаДереваЗначений.Количество() = 0 Тогда Возврат; КонецЕсли;
    
    // Определяем, нужно ли искать выделенный на форме элемент
    ИскатьТекущуюСтроку = (ТекущаяСтрока <> Неопределено И ТипЗнч(ТекущаяСтрока) = Тип("СправочникСсылка.Номенклатура"));
    
    СтруктураОтбора = Новый Структура("Идентификатор", Неопределено);
    
    Для Каждого ЭлементСтрокиДерева Из СтрокаДереваЗначений Цикл
        // Обновляем идентификаторы строк
        НайденнаяСтрока = ТаблицаРазвернутыхСтрокДерева.Найти(ЭлементСтрокиДерева.Ссылка, "Ссылка");
        Если НайденнаяСтрока <> Неопределено Тогда 
            НайденнаяСтрока.Идентификатор = ЭлементСтрокиДерева.ПолучитьИдентификатор(); 
        КонецЕсли; 
        
        Если ИскатьТекущуюСтроку Тогда
            // Ищем новый индекс выделенной в элементе строки
            Если ЭлементСтрокиДерева.Ссылка = ТекущаяСтрока Тогда
                ТекущаяСтрока = ЭлементСтрокиДерева.ПолучитьИдентификатор();
            КонецЕсли;
        КонецЕсли;
        
        // Чтобы исключить ситуацию, когда все индексы найдены, а перебор дерева
        // еще идет, проверим строки со значением Неопределено.
        Если НЕ ИскатьТекущуюСтроку И ТаблицаРазвернутыхСтрокДерева.НайтиСтроки(СтруктураОтбора).Количество() = 0 Тогда
            Прервать;
        КонецЕсли;        
        
        ОбновитьТаблицуИдентификаторовСтрокДереваНаСервере(ТаблицаРазвернутыхСтрокДерева, ЭлементСтрокиДерева, ТекущаяСтрока); 
    КонецЦикла;    
    
КонецПроцедуры

Кратко опишу, что происходит. Запросом формируем иерархию справочника Номенклатура и строим дерево. Чтобы исключить повторное добавление в дерево уже имеющихся элементов, отсекаем, используя СоответствиеНоменклатурыИСтрокДерева. Также попутно из этого соответствия получаем строку-родитель дерева для нового элемента.

После того, как дерево построено, формируем таблицу с данными развернутых строк. Эта часть актуальна для перестроения дерева. При первом построении она пропускается, поскольку у нас нету развернутых узлов.

Когда таблица создана, перегружаем дерево в реквизит формы ДеревоЗначений. Затем методом ОбновитьТаблицуИдентификаторовСтрокДереваНаСервере() перебираем данные реквизита ДеревоЗначений (он имеет тип ДанныеФормыДерево) и ищем номенклатуру из дерева в таблице ТаблицаРазвернутыхСтрокДерева. Если совпадения находятся, изменяем идентификаторы в строках ТаблицыРазвернутыхСтрокДерева. Если у пользователя была выделена строка, также ищем новый идентификатор этой строки и запоминаем его. В методе ОбновитьТаблицуИдентификаторовСтрокДереваНаСервере() установлено ограничение, которое срабатывает, если обновлены идентификаторы всех развернутых строк.

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

Сам алгоритм достаточно простой, несмотря на немаленький объем кода. Использовать его можно в любом дереве. Достаточно определить уникальное значение для каждой строки дерева.

Работает код тоже быстро. В частности, через веб-клиента на компьютере средней производительности дерево из 400 тыс. строк строится примерно за 2 минуты, перестраивается за 40 секунд.

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

ДеревоЗначений ДанныеФормыДерево строки дерево восстановление статья обработка управляемое приложение управляемая форма

См. также

Поинтегрируем: сервисы интеграции – новый стандарт или просто коннектор?

Обмен между базами 1C Администрирование СУБД Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

В платформе 8.3.17 появился замечательный механизм «Сервисы интеграции». Многие считают, что это просто коннектор 1С:Шины. Так ли это?

11.03.2024    4512    dsdred    53    

71

Как готовить и есть массивы

Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

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

24.01.2024    5289    YA_418728146    25    

63

Планы обмена VS История данных

Обмен между базами 1C Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Вы все еще регистрируете изменения только на Планах обмена и Регистрах сведений?

11.12.2023    6408    dsdred    36    

111

1С-ная магия

Механизмы платформы 1С Бесплатно (free)

Язык программирования 1С содержит много нюансов и особенностей, которые могут приводить к неожиданным для разработчика результатам. Сталкиваясь с ними, программист начинает лучше понимать логику платформы, а значит, быстрее выявлять ошибки и видеть потенциальные узкие места своего кода там, где позже можно было бы ещё долго медитировать с отладчиком в поисках источника проблемы. Мы рассмотрим разные примеры поведения кода 1С. Разберём результаты выполнения и ответим на вопросы «Почему?», «Как же так?» и «Зачем нам это знать?». 

06.10.2023    18473    SeiOkami    46    

118

Дефрагментация и реиндексация после перехода на платформу 8.3.22

Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Начиная с версии платформы 8.3.22 1С снимает стандартные блокировки БД на уровне страниц. Делаем рабочий скрипт, как раньше.

14.09.2023    12087    human_new    27    

74

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

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

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

28.08.2023    8819    YA_418728146    6    

141

Внешние компоненты Native API на языке Rust - Просто!

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

Внешние компоненты для 1С можно разработывать очень просто, пользуясь всеми преимуществами языка Rust - от безопасности и кроссплатформенности до удобного менеджера библиотек.

20.08.2023    6279    sebekerga    54    

94

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

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

Рассмотрим новую возможность 8.3.24 и как её можно эффективно использовать

27.06.2023    15984    SeiOkami    31    

103
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. dj_serega 390 16.10.15 17:35 Сейчас в теме
А если это в документе и документ перезаписать "СоответствиеИдентификаторовРазвернутыхСтрокДерева" не очищается? Малоли :)
2. azhilichev 213 17.10.15 02:42 Сейчас в теме
(1) Просто берете и адаптируете под документ. Ничего сложного в такой адаптации нету. То, что описано в статье можно определить как шаблон.
3. Yashazz 4709 21.10.15 19:07 Сейчас в теме
Достаточно тривиальная задача из области "текучки". Не очень понимаю, зачем её как публикацию выкладывать.
4. olbu 26.10.15 09:28 Сейчас в теме
А каково отличие конструкции:
ПустаяСсылка = XMLЗначение(Тип("СправочникСсылка.Номенклатура"), "00000000-0000-0000-0000-000000000000")
от
ПустаяСсылка = Справочники.Номенклатура.ПустаяСсылка()?
5. azhilichev 213 26.10.15 13:13 Сейчас в теме
(4) olbu, никакого. Результат один.
6. Andryza 38 31.05.21 09:17 Сейчас в теме
Спасибо пример помог, только у меня дерево посложнее. Но я сделал проще, меньше кода.
Взял соответствие, его заполнение. Процедуры при свертке/развертке.
и написал свою, вот такую, которая вызывается после обработки дерева. в моем случае, там колонки рассчитываются и обновляется дерево. Все этого достаточно, что бы дерево разворачивалось, без лишних промежуточных структур/соответствий и таблиц значений.

&НаКЛиенте
Процедура РазвернутьДерево()
	
	МассивИдентификаторов = Новый МАссив;
	
	ЭлементыДерева = ДеревоЦен.ПолучитьЭлементы();
	
	Для каждого ЭлементДерева Из ЭлементыДерева Цикл
		
		Подчиненные = ЭлементДерева.ПолучитьЭлементы();
		
		Для каждого Подчиненный Из Подчиненные Цикл
			
			Если НЕ СоответствиеИдентификаторовРазвернутыхСтрокДерева.Получить(Подчиненный.Наименование) = Неопределено Тогда
				
				Если МассивИдентификаторов.Найти(ЭлементДерева.ПолучитьИдентификатор()) = Неопределено Тогда
					
					МассивИдентификаторов.Добавить(ЭлементДерева.ПолучитьИдентификатор());
					
				КонецЕсли;
				
				МассивИдентификаторов.Добавить(Подчиненный.ПолучитьИдентификатор());				
				
			КонецЕсли;
			
		КонецЦикла;
		
	КонецЦикла;
		
		
	Для каждого Ид из МассивИдентификаторов Цикл
		
		Элементы.ДеревоЦен.Развернуть(Ид,Ложь);
		
	КонецЦикла;	
	
	
КонецПроцедуры
Показать
vladimir-89; welder; +2 Ответить
7. Mahon83 13 26.08.22 11:41 Сейчас в теме
(6)
&НаКЛиенте
Процедура РазвернутьДерево()

МассивИдентификаторов = Новый МАссив;

ЭлементыДерева = ДеревоЦен.ПолучитьЭлементы();

Для каждого ЭлементДерева Из ЭлементыДерева Цикл

Подчиненные = ЭлементДерева.ПолучитьЭлементы();

Для каждого Подчиненный Из Подчиненные Цикл

Если НЕ СоответствиеИдентификаторовРазвернутыхСтрокДерева.Получить(Подчиненный.Наименование) = Неопределено Тогда

Если МассивИдентификаторов.Найти(ЭлементДерева.ПолучитьИдентификатор()) = Неопределено Тогда

МассивИдентификаторов.Добавить(ЭлементДерева.ПолучитьИдентификатор());

КонецЕсли;

МассивИдентификаторов.Добавить(Подчиненный.ПолучитьИдентификатор());

КонецЕсли;

КонецЦикла;

КонецЦикла;


Для каждого Ид из МассивИдентификаторов Цикл

Элементы.ДеревоЦен.Развернуть(Ид,Ложь);

КонецЦикла;


КонецПроцедуры
Показать


В вашем алгоритме есть существенный минус, это всего 3 уровня, а если дерево ещё глубже?
Взял ваш алгоритм за основу и немного усовершенствовал.

РазвернутьДеревоРекурсивно(ДеревоТовары);


&НаКлиенте
Процедура РазвернутьДеревоРекурсивно(ТекущийУзел, МассивИдентификаторов = Неопределено, Знач ТекущийУровень = 0)
	
	Если МассивИдентификаторов = Неопределено Тогда
		МассивИдентификаторов = Новый Массив;
	КонецЕсли;
	
	ЭлементыДерева = ТекущийУзел.ПолучитьЭлементы();
	Для Каждого ЭлементДерева Из ЭлементыДерева Цикл
		
		Если НЕ СоответствиеИдентификаторовРазвернутыхСтрокДерева.Получить(ЭлементДерева.Номенклатура) = Неопределено Тогда
			Если МассивИдентификаторов.Найти(ЭлементДерева.ПолучитьИдентификатор()) = Неопределено Тогда    
				МассивИдентификаторов.Добавить(ЭлементДерева.ПолучитьИдентификатор());   
			КонецЕсли;                         
		КонецЕсли;
		
		РазвернутьДеревоРекурсивно(ЭлементДерева, МассивИдентификаторов, ТекущийУровень + 1)	
	КонецЦикла;
	
	Если ТекущийУровень = 0 Тогда
		Для Каждого Идентификатор из МассивИдентификаторов Цикл   
			Элементы.ДеревоТовары.Развернуть(Идентификатор, Ложь);    
		КонецЦикла;	
	КонецЕсли;
	
КонецПроцедуры
Показать
vladimir-89; +1 Ответить
Оставьте свое сообщение