Дереве значений обход дерева 1с

Обход дерева значений на клиенте

Подскажите, пожалуйста, как обойти дерево значений на клиенте.

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

А я не хочу, чтоб оно сворачивалось. Я пробывал обойти его на клиенте после это и развернуть, но так не получается(нет подходящих методов)

ЭлементыДерева = Дерево.ПолучитьЭлементы(); Для Каждого ЭлементДерева Из ЭлементыДерева Цикл Элементы.Дерево.Развернуть(ЭлементДерева.ПолучитьИдентификатор(), Истина); КонецЦикла;

Спасибо, но это не то. У меня многоуровненовое дерево.

То есть .получитьэлементы() возвращает только корневую коллекцию строк. А в дочерние я попасть не могу.

ЭлементыДерева = Дерево.ПолучитьЭлементы(); Для Каждого ЭлементДерева Из ЭлементыДерева Цикл Элементы.Дерево.Развернуть(ЭлементДерева.ПолучитьИдентификатор(), Истина); ЭлементыУр2 = ЭлементДерева.ПолучитьЭлементы(); Для Каждого ЭлементУр2 Из ЭлементыУр2 Цикл Элементы.Дерево.Развернуть(ЭлементДерева.ПолучитьИдентификатор(), Истина); ЭлементыУр3 = ЭлементДерева.ПолучитьЭлементы(); . КонецЦикла; КонецЦикла;

Спасибо большое. Получилось, написал в итоге рекурсивные процедуры. Одна запоминает какие развернуты были узлы, потом на сервере процедура пересчитывает итоги, и третья раскрывает узлы, какие были раскрыты до пересчета. Может кому пригодится код:

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

Однако если вы хотите, что бы состояние развернутости запоминалось до пересчета итогов, и восстанавливалось после, то это уже совсем другая задача, которую можно решить примерно так, как вы написали в (5). Но только не совсем так, потому что так как вы написали, будет работать не всегда. Например, если пользователь будет сначала интерактивно заполнять дерево в хаотичном порядке, т.е. добавлять элементы, то в одну группу то в другую, а потом запустится процедура пересчета итогов, то дерево у вас раскроется не правильно, т.е. не так как было до пересчета. Произойдет это потому, что при хаотичном порядке заполнения дерева, идентификаторы строк будут присвоены в порядке их добавления, а после того, как будет выполнен метод ЗначениеВРеквизитФормы, идентификаторы строк присвоятся заново. И помимо того, что их нумерация увеличится на количество элементов в дереве, она еще будет заново упорядочена. И в этом случае никакое «Идентификатор — КоличествоСтрок + 1», уже не поможет. Т.к. например, строке с идентификатором «3» при количестве строк равным 10, не обязательно будет присвоен идентификатор «12», ей вполне может быть присвоен идентификатор с другим номером, например «15». Можете проверить.
Конечно, если у вас не происходит интерактивной работы пользователя с деревом, к примеру, если оно у вас заполняется программно и всегда по порядку, или изначально заполняется методом ЗначениеВРеквизитФормы, то тогда описанный вами способ будет работать.

Читайте также:  Bmw e36 салон дерево

(7) VBod, да все верно. Я тоже заметил такую особенность, поэтому и пришлось говнокодить как «Идентификатор — КоличествоСтрок + 1». Но другого способа не нашел.

а что делать в этом случае?

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

Пользователи захотели сами править дерево 🙂

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

ДеревоНаКлиенте.Получить(ИндексСтрокиНаСервере)

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

Источник

Работа с деревом значений в 1С

В последнее время аномально часто мне в работе попадалось дерево значений, поэтому решил написать на эту тему статью.

Попробую рассмотреть способы решения основных задач связанных с деревом значений, при этом постараюсь писать «без воды».

Дерево значений

Из названия объекта понятно, что дерево значений служит для хранения/отображения какой-либо иерархической информации. Каждая строка дерева значений может иметь какое-то количество подчиненных строк, при этом такие операции как поиск, сортировка, подсчет итогов можно проводит с учетом уровня иерархии и подчиненных строк.

Читайте также:  Варкрафт 3 модель дерева

Кроме этого, каждая строка дерева значений имеет свойства «Родитель» и «Строки».

Дерево значений на форме

Визуальное представление дерева значений обеспечивает элемент «Табличное поле».

Заполнение дерева значений

При заполнении дерева значений нужно помнить, что сам объект «ДеревоЗначений» и все его строки имеют свойство «Строки»и добавление новых строк на любом уровне дерева осуществляется через это свойство.

Сам же объект «ДеревоЗначений» имеет еще и свойство «Колонки», которое ничем не отличается от аналогичного свойства у таблицы значений.

Небольшой пример программного заполнения таблицы значений для управляемых форм:

Обход дерева значений

Обход всех строк дерева значений делается при помощи рекурсии, вот так будет выглядеть код для обхода дерева созданного в примере выше:

Как свернуть и развернуть дерево значений

Сворачивается и разворачивается дерево значений очень просто.

Привел три примера: для сворачивания текущей строки, для сворачивания строк верхнего уровня, для сворачивания вообще всех строк (рекурсия).

Два примера: для разворачивания текущей строки и для разворачивания всех строк. У метода «Развернуть» есть дополнительный параметр, который позволяет указать нужно ли разворачивать подчиненные строки.

Как удалить строку и очистить дерево значений

Тут опять же все просто, нужно помнить, что при удалении/очистке строки, все подчиненные строки удаляются.

Точно также можно очистить от подчиненных элементов другую другую строку.

Удалить строку дерева значений не сложнее — нужно только знать ее индекс:

Запрос и дерево значений

Результат выполнения запроса очень легко преобразовать в дерево значений, для этого нужно воспользоваться методом «Выгрузить» и указать параметр «ТипОбхода» отличным от того, что стоит по умолчанию, т.е. «ПоГруппировкам» или «ПоГруппировкамСИерархией».

Если на форме имеется реквизит «ДеревоЗначений» и связанный с ним визуальный элемент, то можно сделать примерно так:

Читайте также:  Ромашки из дерева своими руками

Причем полного совпадения колонок и типов не требуется — лишние колонки будут просто отброшены, а колонки с различными типами будут заполнены пустыми значениями.

Дерево значений в таблицу значений и обратно

Преобразовать дерево значений в таблицу значений и наоборот достаточно просто, ведь дерево значений это та же таблица значений, но с дополнительной колонкой — «Родитель». У меня есть отдельная статья о том как преобразовать дерево значений в таблицу значений и обратно.

Отбор в дереве значений

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

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

Первый способ — накладывать отбор до вывода дерева значений (в запросе например). Это не классический отбор, но в тех случаях когда этот способ применим, то следует применять именно его, так как это почти всегда быстрее и правильнее чем что-либо другое.

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

Еще один способ заключается в том, чтобы преобразовать дерево значений в таблицу значений, сделать отбор в таблице значений, проконтролировать результат (почистить «хвосты» — строки, родитель которых не удовлетворил условию отбора) и выполнить обратное преобразование в дерево значений.

На этом все, рассказал все, что знал, надеюсь мне удалось сэкономить Вам немного времени.

Если Вы нашли ошибку или неточность, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

(оценок: 36, средняя оценка: 4,64 из 5)

Источник

Оцените статью