Использование универсальной коллекции "Дерево значений"

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

      Запрос = Новый Запрос; 
      Запрос.Текст = "
             ВЫБРАТЬ 
             | Номенклатура.Код, 
             | Номенклатура.Наименование КАК Наименование, 
             | Номенклатура.БазоваяЕдиницаИзмерения 
             |ИЗ 
             | Справочник.Номенклатура КАК Номенклатура 
             | 
             |УПОРЯДОЧИТЬ ПО 
             | Наименование ИЕРАРХИЯ"; 
      Результат = Запрос.Выполнить(); 
      Дерево = Результат.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
      ЭлементыФормы.Дерево.ГоризонтальныеЛинии = Истина;ЭлементыФормы.Дерево.ВертикальныеЛинии = Истина;
      ЭлементыФормы.Дерево.СоздатьКолонки();

Результат приведен на рис.1.

Рис. 1

С деревом значений также можно работать и как с промежуточным объектом для накопления данных и посредством обхода коллекции значений выводить данные в отчет. Обход коллекции значений можно осуществлять как по строкам, так и по колонкам дерева значений, обход осуществляется посредством оператора Для каждого … Из … Цикл. Возможно обращение к элементу коллекции посредством оператора [...]. Для обращения к строке: Дерево.Строки[0], в качестве аргумента передается индекс строки (нумерация строк начинается с 0). Для обращения к колонке: Дерево.Колонки[0], в качестве аргумента также передается индекс колонки (нумерация колонок начинается с 0). Также возможно обращение к конкретной ячейке, т.е. к полю в конкретной строке конкретной колонки. Например, если СтрокаДЗ = Дерево.Строки[0] (СтрокаДЗ содержит первую строку дерева значений). Необходимо обратиться к значению в этой строке колонки «Наименование» и присвоить новое значение, это можно сделать с помощью СтрокаДЗ["Наименование"] = "Сырье и материалы".

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

     Функция ВыводДереваЗначений (СтрокаДереваЗначений,Уровень=0)
            Для Каждого стр Из СтрокаДереваЗначений.Строки Цикл
                …………………….…………………………………..
                ВыводДереваЗначений (стр,Уровень+1);
            КонецЦикла;
     КонецФункции;

Также посредством метода дерева значений «ВыбратьСтроку возможна организация интерактивного диалога с пользователем, содержимое дерева значений показывается в отдельном окне для выбора конкретной строки. Например, ВыбраннаяСтрока = Дерево.ВыбратьСтроку("Выберите строку дерева значений").

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