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

Дерево значений 1С – это универсальная коллекция значений, в которой данные можно расположить в иерархическом порядке в виде дерева. По сути, дерево значений в 1С 8.3 — это таблица значений, где у строк могут быть подчиненные строки. Одна строка дерева значений может иметь несколько подчиненных строк, но в тоже время она может иметь только одну строку, которой подчинена, строку-родителя, или не иметь родителя вообще. Строка без родителя – это строка верхнего уровня, или первая строка.

В программном модуле дерево значений создается при помощи конструктора Новый.

ДеревоРегионов = Новый ДеревоЗначений;

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

То есть, такой код, при выполнении на тонком клиенте, работать не будет:

&НаКлиенте
Процедура СоздатьДерево(Команда)
   ДеревоРегионов = Новый ДеревоЗначений;
КонецПроцедуры

Поэтому, желательно, деревья значений создавать в методах, которые работают в серверном контексте.

&НаСервере
Процедура СоздатьДеревоНаСервере()
	ДеревоРегионов = Новый ДеревоЗначений;
КонецПроцедуры

&НаКлиенте
Процедура СоздатьДерево(Команда)
	СоздатьДеревоНаСервере();
КонецПроцедуры

Колонки дерева значений 1С

Само по себе дерево значений не имеет смысла, для того, чтобы можно было с ним работать у этого дерева нужно создать колонки. Для этого, нужно использовать свойство дерева значений Колонки,  которое имеет тип КоллекцияКолонокДереваЗначений, у объекта данного типа имеется ряд методов, с которыми вы можете познакомиться в синтакс-помощнике, а нас конкретно интересует метод Добавить. Этот метод добавляет новые колонки в дерево значений.  Он имеет следующий синтаксис:

Добавить(<Имя>, <Тип>, <Заголовок>, <Ширина>)

Где Имя – это имя колонки (уникальное в рамках этого дерева); Тип – в этом параметре описывают возможные типы колонки, делается при помощи объекта ОписаниеТипов; Заголовок – название колонки и Ширина  — ширина колонки в символах.

Например, добавим нашему дереву регионов три колонки:

ТипСтрока = Новый ОписаниеТипов("Строка");
ТипЧисло  = Новый ОписаниеТипов("Число");

ДеревоРегионов.Колонки.Добавить("Регион",ТипСтрока);
ДеревоРегионов.Колонки.Добавить("РуководительРегиона",ТипСтрока,"Руководитель региона");
ДеревоРегионов.Колонки.Добавить("Бюджет",ТипЧисло);

Мы добавили три колонки, две из которых имеют тип строка, а одна имеет тип число.

Строки дерева значений 1С

Строки дерева значений 1С бывают двух видов. Это строки верхнего (или первого) уровня. Те строки, у которых нет ни каких родителей, и которые ни кому не подчинены.  И подчиненные строки – это строки более низких уровней. У подчиненных строк заполнено свойство Родитель, в котором указывается родительская строка, т.е. та строка, которой подчинена эта текущая строка (у строк верхнего уровня свойство Родитель пустое). Для того, чтобы создать строку верхнего (или первого) уровня, нужно воспользоваться свойством Строки дерева значений. Это свойство имеет тип КоллекцияСтрокДереваЗначений. И у объекта этого типа есть метод Добавить, который создает новую строку верхнего (первого) уровня. Причем, этот метод является функцией, которая возвращает строку дерева значений. А у этой строки мы, как к свойствам, можем обращаться к колонкам дерева значений.

СтрокаВерхнего = ДеревоРегионов.Строки.Добавить();
СтрокаВерхнего.Регион = "Приволжский округ";
СтрокаВерхнего.РуководительРегиона = "Петров";
СтрокаВерхнего.Бюджет = 1000000;

СтрокаВерхнего = ДеревоРегионов.Строки.Добавить();
СтрокаВерхнего.Регион = "Сибирский округ";
СтрокаВерхнего.РуководительРегиона = "Борисов";
СтрокаВерхнего.Бюджет = 1000000;

В этом коде добавлено две строки верхнего уровня дерева регионов.

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

Например, так мы создаем две строки второго уровня:

СтрокаВторогоОдин = СтрокаВерхнего.Строки.Добавить();
СтрокаВторогоОдин.Регион = "Удмуртия";
СтрокаВторогоОдин.РуководительРегиона = "Бречалов";
СтрокаВторогоОдин.Бюджет = 500000;

СтрокаВторогоДва = СтрокаВерхнего.Строки.Добавить();
СтрокаВторогоДва.Регион = "Татарстан";
СтрокаВторогоДва.РуководительРегиона = "Шаймиев";
СтрокаВторогоДва.Бюджет = 500000;

А так, мы создаем строки третьего уровня (две для Удмуртии и одну для Татарстана):

СтрокаТретьегоОдин = СтрокаВторогоОдин.Строки.Добавить();

СтрокаТретьегоОдин.Регион = "Завьяловский район";
СтрокаТретьегоОдин.РуководительРегиона = "Иванов";
СтрокаТретьегоОдин.Бюджет = 100000;

СтрокаТретьегоДва = СтрокаВторогоОдин.Строки.Добавить();

СтрокаТретьегоДва.Регион = "Ярский район";
СтрокаТретьегоДва.РуководительРегиона = "Сидоров";
СтрокаТретьегоДва.Бюджет = 100000;


СтрокаТретьегоТри  = СтрокаВторогоДва.Строки.Добавить();

СтрокаТретьегоТри.Регион = "Мензилинский район";
СтрокаТретьегоТри.РуководительРегиона = "Шайхметов";
СтрокаТретьегоТри.Бюджет = 100000;

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

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

Для Каждого СтрПервогоУровня из ДеревоРегионов.Строки Цикл 
	Сообщить(СтрПервогоУровня.Регион + "/" + СтрПервогоУровня.Руководитель);
КонецЦикла;

Поскольку свойство Строки дерева значений является коллекцией, то к ней применим цикл Для Каждого Цикл. Где в значении очередного элемента коллекции находится строка верхнего уровня (первого) дерева значений, у этой строки можно обращаться к колонкам как к свойствам.

Если нам нужно обойти строку следующего уровня, то в этот раз следует уже циклом Для каждого Цикл обходить свойство Строки текущей строки дерева значений.

Для Каждого СтрПервогоУровня из ДеревоРегионов.Строки Цикл 
	Сообщить(СтрПервогоУровня.Регион + "/" + СтрПервогоУровня.Руководитель);
	Для Каждого стрВторогоУровня из СтрПервогоУровня.Строки Цикл 
		Сообщить(стрВторогоУровня.Регион + "/" + стрВторогоУровня.Руководитель);
	КонецЦикла;	
КонецЦикла;	

Проблема в том,  что мы не можем знать настоящую вложенность дерева значений 1С, поэтому для обхода деревьев лучше применять рекурсивный вызов метода.

&НаСервере
Процедура ВывестиДерево(СтрокиДерева)
	
	Для Каждого стрДерева из СтрокиДерева Цикл 
		
		Сообщить(стрДерева.Регион + "/" + стрДерева.РуководительРегиона + "/");
		Если стрДерева.Строки.Количество() <> 0 Тогда 
			ВывестиДерево(стрДерева.Строки);
		КонецЕсли;	
	КонецЦикла;	
	
КонецПроцедуры

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

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

ВывестиДерево(ДеревоРегионов.Строки);
Дерево значений 1С

Ну и для того, чтобы наш список выглядел более наглядно, будем при выводе строк второго и третьего уровня добавлять тире.  Для этого создадим функцию, которая добавляет тире, количество которых зависит от уровня вложенности. А узнать уровень вложенности строки можно при помощи метода строки дерева значений Уровень(), который возвращает уровень вложенности строки начиная с 0.

&НаСервере
Процедура ВывестиДерево(СтрокиДерева)
	
	Для Каждого стрДерева из СтрокиДерева Цикл 
		Пробелы = СформироватьТире(стрДерева.Уровень());
		
		Сообщить(Пробелы + стрДерева.Регион + "/" + стрДерева.РуководительРегиона + "/");
		Если стрДерева.Строки.Количество() <> 0 Тогда 
			ВывестиДерево(стрДерева.Строки);
		КонецЕсли;	
	КонецЦикла;	
	
КонецПроцедуры	

Функция  СформироватьТире(Уровень)
	
	Если Уровень = 0 Тогда 
		Возврат "";
	КонецЕсли;	
	
	Пробелы = "";
	Для н = 1 по Уровень Цикл 
		Пробелы = Пробелы + " - ";
	КонецЦикла;	
	
	Возврат Пробелы;
	
КонецФункции
Дерево значений 1С

Дерево значений 1С на управляемой форме

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

Дерево значений на управляемой форме 1С

Само по себе такое дерево бессмысленно. Нужно добавить ему колонки.  Если мы хотим дереву значений на форме добавить колонку, то необходимо сначала выделить дерево на форме, а потом нажать на кнопку «Добавить колонку реквизита».

Дерево значений на управляемой форме 1С

Можно создать колонки с различными типами, и поместить дерево на форму в виде таблицы.

Дерево значений на управляемой форме 1С

В моей учебной конфигурации имеется справочник Регионы, который является иерархическим (иерархия элементов).

Иерархический справочник на управляемой форме 1С

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

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

Заполнить это дерево можно несколькими способами. В первом способе, мы в  рекурсивной процедуре  обходим выборку из запроса, и если у этой выборки имеется выборка вложенных записей, то вызываем эту же процедуру.

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

	ОписаниеРегиона = Новый ОписаниеТипов("СправочникСсылка.Регионы");
	ОписаниеВидаРегиона = Новый ОписаниеТипов("ПеречислениеСсылка.ВидРегиона");
	
	
	Дерево = Новый ДеревоЗначений;
	Дерево.Колонки.Добавить("Регион",ОписаниеРегиона);
	Дерево.Колонки.Добавить("ВидРегиона",ОписаниеВидаРегиона);
	
	Выборка = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
	
	ЗаполнитьДерево(Дерево.Строки, Выборка);
	
	ЗначениеВРеквизитФормы(Дерево,"ДеревоЗначений");
	
КонецПроцедуры

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

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

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

	ЗначениеВРеквизитФормы(Дерево,"ДеревоЗначений");
	
КонецПроцедуры

Как в результате первого способа и второго, у нас будет заполнена дерево значений на управляемой форме.

Дерево значений на управляемой форме 1С

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

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

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

&НаКлиенте
Процедура Очистить(Команда)
	ОбойтиИОчиститьДеревоНаФорме(Регионы.ПолучитьЭлементы());
КонецПроцедуры

Дерево значений на управляемой форме 1С

Статьи о других универсальных коллекциях значений в 1С

Соответствия в 1С

Массивы в 1С

Список значений в 1С

Структура в 1С

Более подробно о работе с другими интересными объектами языка программирования в 1С читайте в моей книге «Программировать в 1С за 11 шагов»

Книга «Программировать в 1С за 11 шагов»

Изучайте программирование в 1С в месте с моей книги «Программировать в 1С за 11 шагов»

  1. Книга написана понятным и простым языком — для новичка.
  2. Книга посылается на электронную почту в формате PDF. Можно открыть на любом устройстве!
  3. Научитесь понимать архитектуру 1С;
  4. Станете писать код на языке 1С;
  5. Освоите основные приемы программирования;
  6. Закрепите полученные знания при помощи задачника;

Книга «Основы разработки в 1С: Такси»

Отличное пособие по разработке в управляемом приложении 1С, как для начинающих разработчиков, так и для опытных программистов.

  1. Очень доступный и понятный язык изложения
  2. Книга посылается на электронную почту в формате PDF. Можно открыть на любом устройстве!
  3. Поймете идеологию управляемого приложения 1С
  4. Узнаете, как разрабатывать управляемое приложение;
  5. Научитесь разрабатывать управляемые формы 1С;
  6. Сможете работать с основными и нужными элементами управляемых форм
  7. Программирование под управляемым приложением станет понятным

Промо-код на скидку в 15% — 48PVXHeYu


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

можно оплатить вручную:

Яндекс.Деньги — 410012882996301

Вступайте в мои группы:

Вконтакте: https://vk.com/1c_prosto
Фейсбуке: https://www.facebook.com/groups/922972144448119/
ОК: http://ok.ru/group/52970839015518
Твиттер: https://twitter.com/signum2009

One Reply to “Дерево значений 1С”

  1. Спасибо за статью!
    Ваши примеры с Выборка.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией) помогли с печатью иерархического справочника. В интернетах везде громоздкие примеры с использованием итогов в запросе, а у вас очень простые и лаконичные примеры без лишних телодвижений.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *