Дерево значений в управляемой форме
Дерево значений в 1С (тип значения «ДеревоЗначений») – это Универсальная коллекция значений в системе 1С, где Элементы упорядочены по Индексу (нумерация начинается с 0). Каждое значение Элемента содержит в себе Коллекцию подчиненных Строк, где у каждой Строки коллекции указывается Родитель – Элемент, находящийся на уровень выше. У корневого Элемента (элемент первого уровня) Родитель отсутствует. Доступ к Элементам осуществляется через Индекс, по номеру которого можно получить доступ к значению Элемента и коллекции подчиненных ему Строк. Описание из Синтакс-помощника: используется для доступа к свойствам и методам дерева значений 1С в целом. Объект, представляющий собой древовидную структуру, обладает сходной функциональностью с таблицей значений, а также обладает возможностью добавлять подчиненные строки к какой-либо строке дерева. Внимание! В толстом клиенте (обычное приложение) передача значений данного типа с клиента на сервер и обратно приводит к возникновению исключения. Доступность: сервер, толстый клиент, внешнее соединение, мобильное приложение (сервер), мобильный автономный сервер. Сериализуется: данный объект может быть сериализован в/из XDTO. Тип XDTO, соответствующий данному объекту, определяется в пространстве имен . Имя типа XDTO: ValueTree.
2. Как создать дерево значений в 1C 8.3
Так как Дерево значений в 1С 8.3 является усложненной конструкцией с точки зрения программной реализации, и достаточно ресурсоемкой, её не часто используют в разработках. Однако, она очень удобна для реализации нестандартных задач, в том числе, когда требуется отобразить множество значений с возможностью группировки по Родителю. Необходимо однозначно разделять Дерево значений как объявленную переменную (через конструктор «Новый ДеревоЗначений») и как Реквизит Формы 1С 8.3 (обратите внимание, что ДЗ нельзя выбрать как тип данных Реквизита Объекта). Если объявленное (далее – ОП) ДЗ можно читать НаКлиенте, передавать НаСервере для обработки и возвращать обратно, то ДЗ как Реквизит Формы 1С 8.3 (далее – РФ) будет читабельным только НаКлиенте. НаСервере даже при попытке чтения дерево выдаст Исключение, а изменять данные, конечно же, не позволит вообще. Далее рассмотрим поведение одинаковых действий при условии объявления переменной (в рамках одной процедуры/функции) и условиях добавленного реквизита формы 1С 8.3. Варианты работы с глобальными переменными, экспортными или не экспортными переменными модуля мы рассматривать не будем, так как применение зависит от контекста задачи и Вашей веры в объявление глобальных и внеконтекстных переменных. У ДЗ как РФ есть свое преимущество: вы можете задать колонки и тип данных в самом РФ и программно обращаться к данным из любой процедуры или функции модуля формы (не забывая о директивах компиляции). Для ДЗ как ОП требуется описать все необходимые колонки (для начинающих это может быть проблематично, если нет четкого представления того, что это за «зверь» такой), а также понимать, что по окончании процедуры/функции кончается и жизненный цикл переменной (конечно, если мы не объявили ее глобальной, но это уже совсем другая история). Пример описания ДЗ программе 1С Предприятие 8:
Как видно из примера, в ДЗ задаются колонки, где будут размещаться данные, но чтобы добавить это данные, необходимо обратиться к Коллекции Строк: ДеревоДанных.Строки.Добавить(). Таким образом добавляются строки первого уровня, после чего в строку первого уровня добавляем коллекцию строк и так далее. При этом, используя метод Добавить(), Родитель присваивается автоматически, но, конечно, его можно изменить. Так и строится дерево, однако не стоит забывать, что чем больше данных, тем больше потребление ресурсов. Пример ДЗ как РФ:
Добавление данных происходит, в сущности, таким же образом, как при описании, но есть программные различия. Опишем основные:
** Пример работы «преобразование-запись-преобразование»:
Развернутое дерево значений по своей сути напоминает Результат запроса с группировками, где чем больше группировок, тем больше совокупное количество строк. Поэтому если требуется результат запроса (где данные сгруппированы) загрузить в ДЗ, необходимо:
1. (необязательно) преобразовать из реквизита формы; 2. загрузить результат; 3. преобразовать в реквизит формы.
При необходимости загрузки данных в ДЗ из табличной части 1С можно воспользоваться несколькими способами:
1. Запись с помощью циклов: тут нужно помнить, что есть строки «корневые», и надо их каким-то образом найти, чтобы правильно построить связь Корень-Подчиненный.
2. Загрузить с помощью Запроса (и здесь есть два варианта):
a. выгрузить табличную часть 1С во временную переменную, передать ее как параметр, сформировать результат с использованием иерархии и загрузить результат в дерево;
b. сформировать запрос, в который передаем как параметр ссылку принятого к обработке документа в 1С 8.3, после чего формируем результат с использованием иерархии и загружаем его в дерево.
*Варианты 2а и 2b кажутся похожими. Однако разница между ними есть. Она заключается в производительности, которая зависит от контекста использования (количество данных, количество пользователей, нагрузка на сервер и другое). С одной стороны, при использовании директивы НаСервере у нас уже есть табличная часть 1С (конечно, на стороне сервера, но она уже загружена), которую мы можем без потерь и других действий передать в Запрос и выполнить его. С другой стороны, обращаясь по ссылке в результате выполнения Запроса, система повторно обратится к БД, но, возможно, сделает это быстрее, чем в первом случае. Этот момент требует исследования уже на конкретной БД. Для записи данных в табличную часть 1С или Таблицу значений потребуется построить цикл, который будет выполнять запись в Приемник по следующим правилам:
1. обход дерева выполняется от Корня к Подчиненным до последнего уровня вложенности;
2. если у Корня есть Подчиненные элементы, то количество результирующих строк в Таблице высчитывается по формуле: , где n – количество элементов на заданном уровне, m — количество уровней (глубина вложенности дерева);
3. рекомендуется записывать Корень – Подчиненный элемент, в связи с этим требуется запись рекурсивным методом. Пример рекурсивной записи из ДЗ в Табличную часть Товары:
Для чтения данных все немного проще: читать можно как НаКлиенте, так и НаСервере. Разница только в том, что для директивы НаКлиенте потребуется сначала вызвать метод ПолучитьЭлемент(), чего не требуется для серверной директивы. Внимание! Не забудьте, что чтение в процедуре/функции с директивой НаКлиентеНаСервереБезКонтекста компилируется одновременно на клиенте и на сервере, а это значит, что описав Чтение как для клиента при вызове исполнения из процедуры/функции с директивой сервера, программа выдаст исключение (и наоборот). При необходимости вызова чтения как НаКлиенте, так и НаСервере рекомендуется создавать обработчики с соответствующими директивами. Кроме всего прочего, ДЗ можно использовать в особо изощренном способе работы. Допустим, поставили задачу, что необходимо иметь на форме две таблицы, таблица слева – дерево, в котором есть все уровни, кроме последнего; справа – таблица, в которой отображаются данные последнего уровня вложенности. Таким образом активация строки в Дереве приведет к отображению всех подчиненных элементов.
Реализованный пример такой задачи:
*Естественно, текущие данные тестовые. Задачей предполагалось, что корневых уровней может быть до 15, второй уровень – примерно так же, а вот на последнем уровне может быть до 50 строк. В такой компоновке удобно видеть все элементы нижнего уровня, переключаясь между Родителями. Использование Дерева значений — это достаточно нетривиальный и филигранный способ, который имеет свои плюсы (особенно когда группы товаров можно сворачивать). Использовать его для больших таблиц (где более 100 строк) можно, но важно исследовать производительность в каждом конкретном случае.
Специалист компании ООО «Кодерлайн» Каплин Иван Александрович
Источник
СКД (Иерархия -> Дерево). Как узнать группировка по какому полю в каком узле дерева?
Делаю иерархическую выборку (ТипГруппировкиКомпоновкиДанных.Иерархия) с помощью СКД. Результат выгружаю в дерево значений.
Дерево получается, все хорошо. Но после мне это дерево необходимо перебрать по всем строкам и подчиненным строкам и я понял, что не хватает информации к какому полю группировки относится тот или иной «текущий» узел дерева.
Как-то можно в СКД пометить группировки?
(3)К примеру, я в каком то n-ом уровне группировки..
Те группировки, которые еще ниже (подчиненные) я узнаю по null. Которые уже выведены по НЕ ЗначениеПоля = Null.
А текущую то как узнать?
Если к примеру у меня полей 5 выводится и только 1 из них не равно Null? На какой я группировке сейчас из 4-х?
(5) неплохоб ы озвучить структуру в компоновке.. например..
Контрагент (иерархия) / Номенклатура (иерархия)
(6)Вот тут использовано 2 группировки по иерархии
Группа1
-Подгруппа1
—ПодПодГруппа1
—ПодПодПодгруппа1 | К приемру, я вот тут в дереве. Уровень() = 4
—-Группа2
——ПодГруппа2
——ПодПодГруппа2
Из примера выше видно, что уровень может быть и 4, а по сути группировка №2
(7)
Структура может быть разная. Группировок может быть как 2, так и 5 и 7. СКД строится программно в зависимости от заданных пользователем группировок. (Пользователь дерево натсраивает для формы для удобного просмотра справочника)
Если реквизит справочника участвующий в группировке, Иерархический, то выводится иерархически, как указано в (7). Если реквизит иного типа, то просто как реквизит, без иерархии
(9) пользователь задал группировки.. пользователь получил ДанныеФормыДерево соответствующими своим ожиданиям.. что еще требуется. дерево же уже отобразилось.. он увидел и успокоился..
(11) а потом он жмакнул по элементу дерева и получил соответствующий отбор в списке справа от дерева))
(16) пусть у нас в дереве «Контрагент (иерархия) / Номенклатура (иерархия)»
стоя на контрагенте, какой отбор должен быть справа.
(18) Более реальный пример давайте для справочника Номенклатура группировки: «Вид товара (Иерархия) / Номенклатурная группа (Иерархия)»
Стоя на элементе номенклатурной группы должен быть отбор по значению реквизита «Вид товара»(В ГРУППЕ или равно последнему раскрытому в дереве значению), «Номенклатурная группа» (В ГРУППЕ или равно последнему раскрытому в дереве значению)
если СКД строится программно, то в выбранные поля можно добавить поле которое будет специфично только для этой группировки. количество колонок конечно при этом увеличится
(20)увеличение кол-во колонок не страшно. Скажите что именно вы имеете ввиду? Я не знаю просто что можно добавить, чтобы и в иерархии это выводилось. Напрашиваются «итоги по иерархии» по какому-нибудь ресурсу, но пока не представляю как по значению этого ресурса в итоге идентифицировть а что же было выше в дереве?
Источник