- Обход дерева значений на клиенте
- Работа с деревом значений в 1С
- Дерево значений
- Дерево значений на форме
- Заполнение дерева значений
- Обход дерева значений
- Как свернуть и развернуть дерево значений
- Как удалить строку и очистить дерево значений
- Запрос и дерево значений
- Дерево значений в таблицу значений и обратно
- Отбор в дереве значений
Обход дерева значений на клиенте
Подскажите, пожалуйста, как обойти дерево значений на клиенте.
У меня в серверной процедуре обсчитываются итоги. После этого я используя метод ЗначениеВРеквизитФормы(Дерево, «ДеревоЗначений») заполняю дерево на форме. При этом оно становится свернутым.
А я не хочу, чтоб оно сворачивалось. Я пробывал обойти его на клиенте после это и развернуть, но так не получается(нет подходящих методов)
ЭлементыДерева = Дерево.ПолучитьЭлементы(); Для Каждого ЭлементДерева Из ЭлементыДерева Цикл Элементы.Дерево.Развернуть(ЭлементДерева.ПолучитьИдентификатор(), Истина); КонецЦикла;
Спасибо, но это не то. У меня многоуровненовое дерево.
То есть .получитьэлементы() возвращает только корневую коллекцию строк. А в дочерние я попасть не могу.
ЭлементыДерева = Дерево.ПолучитьЭлементы(); Для Каждого ЭлементДерева Из ЭлементыДерева Цикл Элементы.Дерево.Развернуть(ЭлементДерева.ПолучитьИдентификатор(), Истина); ЭлементыУр2 = ЭлементДерева.ПолучитьЭлементы(); Для Каждого ЭлементУр2 Из ЭлементыУр2 Цикл Элементы.Дерево.Развернуть(ЭлементДерева.ПолучитьИдентификатор(), Истина); ЭлементыУр3 = ЭлементДерева.ПолучитьЭлементы(); . КонецЦикла; КонецЦикла;
Спасибо большое. Получилось, написал в итоге рекурсивные процедуры. Одна запоминает какие развернуты были узлы, потом на сервере процедура пересчитывает итоги, и третья раскрывает узлы, какие были раскрыты до пересчета. Может кому пригодится код:
&НаКлиенте Процедура ДеревоЗначенийСуммаПриИзменении(Элемент) соотвКолонок = Новый Соответствие; соотвКолонок.Вставить("Сумма"); РазвернутыеСтроки = Новый Соответствие(); КоличествоСтрок = 0; ПроверитьСвернутостьДерева(ДеревоЗначений, РазвернутыеСтроки, КоличествоСтрок); ПосчитатьНаСервере(соотвКолонок); УстановитьРазвернутостьДерева(ДеревоЗначений, РазвернутыеСтроки, КоличествоСтрок); КонецПроцедуры &НаКлиенте Процедура ПроверитьСвернутостьДерева(пДеревоЗначений, РазвернутыеСтроки, КоличествоСтрок) ЭлементыДерева = пДеревоЗначений.ПолучитьЭлементы(); КоличествоСтрок = КоличествоСтрок + 1; Если ЭлементыДерева.Количество() = 0 Тогда Возврат КонецЕсли; Для Каждого ЭлементДерева Из ЭлементыДерева Цикл Идентификатор = ЭлементДерева.ПолучитьИдентификатор(); РазвернутыеСтроки.Вставить(Идентификатор, Элементы.ДеревоЗначений.Развернут(Идентификатор)); ПроверитьСвернутостьДерева(ЭлементДерева, РазвернутыеСтроки, КоличествоСтрок); КонецЦикла; КонецПроцедуры &НаКлиенте Процедура УстановитьРазвернутостьДерева(пДеревоЗначений, РазвернутыеСтроки, КоличествоСтрок) ЭлементыДерева = пДеревоЗначений.ПолучитьЭлементы(); Если ЭлементыДерева.Количество() = 0 Тогда Возврат КонецЕсли; Для Каждого ЭлементДерева Из ЭлементыДерева Цикл Идентификатор = ЭлементДерева.ПолучитьИдентификатор(); Если РазвернутыеСтроки.Получить(Идентификатор - КоличествоСтрок + 1) = Истина Тогда Элементы.ДеревоЗначений.Развернуть(Идентификатор); КонецЕсли; УстановитьРазвернутостьДерева(ЭлементДерева, РазвернутыеСтроки, КоличествоСтрок); КонецЦикла; КонецПроцедуры
Однако если вы хотите, что бы состояние развернутости запоминалось до пересчета итогов, и восстанавливалось после, то это уже совсем другая задача, которую можно решить примерно так, как вы написали в (5). Но только не совсем так, потому что так как вы написали, будет работать не всегда. Например, если пользователь будет сначала интерактивно заполнять дерево в хаотичном порядке, т.е. добавлять элементы, то в одну группу то в другую, а потом запустится процедура пересчета итогов, то дерево у вас раскроется не правильно, т.е. не так как было до пересчета. Произойдет это потому, что при хаотичном порядке заполнения дерева, идентификаторы строк будут присвоены в порядке их добавления, а после того, как будет выполнен метод ЗначениеВРеквизитФормы, идентификаторы строк присвоятся заново. И помимо того, что их нумерация увеличится на количество элементов в дереве, она еще будет заново упорядочена. И в этом случае никакое «Идентификатор — КоличествоСтрок + 1», уже не поможет. Т.к. например, строке с идентификатором «3» при количестве строк равным 10, не обязательно будет присвоен идентификатор «12», ей вполне может быть присвоен идентификатор с другим номером, например «15». Можете проверить.
Конечно, если у вас не происходит интерактивной работы пользователя с деревом, к примеру, если оно у вас заполняется программно и всегда по порядку, или изначально заполняется методом ЗначениеВРеквизитФормы, то тогда описанный вами способ будет работать.
(7) VBod, да все верно. Я тоже заметил такую особенность, поэтому и пришлось говнокодить как «Идентификатор — КоличествоСтрок + 1». Но другого способа не нашел.
а что делать в этом случае?
Например, если пользователь будет сначала интерактивно заполнять дерево в хаотичном порядке, т.е. добавлять элементы, то в одну группу то в другую, а потом запустится процедура пересчета итогов, то дерево у вас раскроется не правильно, т.е. не так как было до пересчета
Пользователи захотели сами править дерево 🙂
(9) mr_virtus, придется запоминать все развернутые строки, но только делать это не по идентификатору т.к. он меняется, а по значениям каких-либо ключевых полей (уникальных для каждой строки дерева). Потом выполняем процедуру на сервере, а затем снова разворачиваем строки. Для этого после загрузки дерева обратно на клиента, ищем нужную строку в дереве на сервере, и получаем ее индекс (не идентификатор). Затем по этому индексу, т.к. они одинаковые и на сервере и на клиенте, через метод
ДеревоНаКлиенте.Получить(ИндексСтрокиНаСервере)
получаем строку в дереве на клиенте, и разворачиваем ее. Только не забудьте, что индекс уникален только в пределах одного уровня дерева, поэтому получение строки на клиенте по индексу, нужно производить, находясь на соответствующем уровне дерева.
Источник
Работа с деревом значений в 1С
В последнее время аномально часто мне в работе попадалось дерево значений, поэтому решил написать на эту тему статью.
Попробую рассмотреть способы решения основных задач связанных с деревом значений, при этом постараюсь писать «без воды».
Дерево значений
Из названия объекта понятно, что дерево значений служит для хранения/отображения какой-либо иерархической информации. Каждая строка дерева значений может иметь какое-то количество подчиненных строк, при этом такие операции как поиск, сортировка, подсчет итогов можно проводит с учетом уровня иерархии и подчиненных строк.
Кроме этого, каждая строка дерева значений имеет свойства «Родитель» и «Строки».
Дерево значений на форме
Визуальное представление дерева значений обеспечивает элемент «Табличное поле».
Заполнение дерева значений
При заполнении дерева значений нужно помнить, что сам объект «ДеревоЗначений» и все его строки имеют свойство «Строки»и добавление новых строк на любом уровне дерева осуществляется через это свойство.
Сам же объект «ДеревоЗначений» имеет еще и свойство «Колонки», которое ничем не отличается от аналогичного свойства у таблицы значений.
Небольшой пример программного заполнения таблицы значений для управляемых форм:
Обход дерева значений
Обход всех строк дерева значений делается при помощи рекурсии, вот так будет выглядеть код для обхода дерева созданного в примере выше:
Как свернуть и развернуть дерево значений
Сворачивается и разворачивается дерево значений очень просто.
Привел три примера: для сворачивания текущей строки, для сворачивания строк верхнего уровня, для сворачивания вообще всех строк (рекурсия).
Два примера: для разворачивания текущей строки и для разворачивания всех строк. У метода «Развернуть» есть дополнительный параметр, который позволяет указать нужно ли разворачивать подчиненные строки.
Как удалить строку и очистить дерево значений
Тут опять же все просто, нужно помнить, что при удалении/очистке строки, все подчиненные строки удаляются.
Точно также можно очистить от подчиненных элементов другую другую строку.
Удалить строку дерева значений не сложнее — нужно только знать ее индекс:
Запрос и дерево значений
Результат выполнения запроса очень легко преобразовать в дерево значений, для этого нужно воспользоваться методом «Выгрузить» и указать параметр «ТипОбхода» отличным от того, что стоит по умолчанию, т.е. «ПоГруппировкам» или «ПоГруппировкамСИерархией».
Если на форме имеется реквизит «ДеревоЗначений» и связанный с ним визуальный элемент, то можно сделать примерно так:
Причем полного совпадения колонок и типов не требуется — лишние колонки будут просто отброшены, а колонки с различными типами будут заполнены пустыми значениями.
Дерево значений в таблицу значений и обратно
Преобразовать дерево значений в таблицу значений и наоборот достаточно просто, ведь дерево значений это та же таблица значений, но с дополнительной колонкой — «Родитель». У меня есть отдельная статья о том как преобразовать дерево значений в таблицу значений и обратно.
Отбор в дереве значений
Стандартного отбора в дереве значений не предусмотрено. Так получилось потому, что непонятно как разрешать ситуацию, когда родительский элемент не удовлетворяет условию отбора, а подчиненные ему элементы удовлетворяют.
Таким образом, если Вам нужно реализовать отбор в дереве значений, то начать нужно с решения именно этой проблемы. А уже после этого можно придумать несколько способов реализовать задуманное.
Первый способ — накладывать отбор до вывода дерева значений (в запросе например). Это не классический отбор, но в тех случаях когда этот способ применим, то следует применять именно его, так как это почти всегда быстрее и правильнее чем что-либо другое.
Второй способ — перебор всех строк дерева значений. Описывать здесь особенно нечего, нужно просто взять обход дерева значений, проверять каждую строку на соответствие условию отбора и удалять лишние строки.
Еще один способ заключается в том, чтобы преобразовать дерево значений в таблицу значений, сделать отбор в таблице значений, проконтролировать результат (почистить «хвосты» — строки, родитель которых не удовлетворил условию отбора) и выполнить обратное преобразование в дерево значений.
На этом все, рассказал все, что знал, надеюсь мне удалось сэкономить Вам немного времени.
Если Вы нашли ошибку или неточность, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.
(оценок: 36, средняя оценка: 4,64 из 5)
Источник