- Преобразование дерева значений в таблицу значений и обратно
- Дерево значений в таблицу значений
- Таблица значений в дерево значений
- Дерево значений
- Программное создание дерева значений
- Заполнить табличное поле на форме
- Свернуть и развернуть строки дерева значений
- Удалить строку и очистить дерево значений
- Поиск в дереве значений
Преобразование дерева значений в таблицу значений и обратно
Задача по преобразованию дерева значений в таблицу значений встречается не так чтобы часто, но тем не менее встречается и я привожу в этой статье свое решение этой задачи.
Дерево значений в таблицу значений
Дано: дерево значений (2 колонки) и таблица значений (4 колонки). Две дополнительные колонки в таблице значений нужны для обратного преобразования, если оно не требуется то и колонки не нужны.
ПреобразоватьВТЗРекурсия(тДерево, тТаблица, Новый УникальныйИдентификатор(«00000000-0000-0000-0000-000000000000»));
В колонку «ГУИД» таблицы значений записывается уникальный идентификатор строки (он просто генерируется), а в колонку «Родитель» записывается уникальный идентификатор строки-родителя (для строк верхнего уровня — нулевой уникальный идентификатор).
Таблица значений в дерево значений
Обратное преобразование производится при помощи двух лишних колонок («ГУИД» и «Родитель») если из таблицы значений была удалена какая-то строка, то все подчиненные ей строки также будут удалены.
ПреобразоватьВДЗРекурсия(тДерево, тТаблица, Новый УникальныйИдентификатор(«00000000-0000-0000-0000-000000000000»));
Работу приведенного выше кода можно посмотреть в маленькой обработке.
На этом все, надеюсь статья Вам помогла.
Если Вы нашли ошибку или неточность, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.
(оценок: 18, средняя оценка: 4,44 из 5)
Источник
Дерево значений
Дерево значений представляет из себя некую структуру с иерархией. Каждая строка имеет свойства «Родитель» и «Строки». У каждой строки может быть сколько угодно подчиненных строк. При этом такие операции как поиск, сортировка, подсчет итогов можно проводить с учетом уровня иерархии и подчиненных строк.
Программное создание дерева значений
Как уже упоминалось выше, каждая строка имеет свойство Строки , которое содержит коллекцию дочерних строк. И сам объект ДеревоЗначений имеет свойство Строки , которое содержит коллекцию строк верхнего уровня.
&НаКлиенте Процедура СоздатьДеревоЗначений(Команда) СоздатьДеревоЗначенийНаСервере(); КонецПроцедуры &НаСервере Процедура СоздатьДеревоЗначенийНаСервере() // создаем объект ДеревоЗначений и добавляем колонки ДеревоЗначений = Новый ДеревоЗначений(); ДеревоЗначений.Колонки.Добавить("Код"); ДеревоЗначений.Колонки.Добавить("Наименование"); ДеревоЗначений.Колонки.Добавить("Количество"); // добавляем две строки верхнего уровня ГруппаТовары = ДеревоЗначений.Строки.Добавить(); ГруппаТовары.Код = "001"; ГруппаТовары.Наименование = "Товары"; ГруппаТовары.Количество = ""; ГруппаУслуги = ДеревоЗначений.Строки.Добавить(); ГруппаУслуги.Код = "002"; ГруппаУслуги.Наименование = "Услуги"; ГруппаУслуги.Количество = ""; // для первой строки верхнего уровня добавляем дочерние строки ПервыйТовар = ГруппаТовары.Строки.Добавить(); ПервыйТовар.Код = "003"; ПервыйТовар.Наименование = "Первый товар"; ПервыйТовар.Количество = 5; ПервыйТовар = ГруппаТовары.Строки.Добавить(); ПервыйТовар.Код = "004"; ПервыйТовар.Наименование = "Второй товар"; ПервыйТовар.Количество = 7; // для второй строки верхнего уровня добавляем дочерние строки ПерваяУслуга = ГруппаУслуги.Строки.Добавить(); ПерваяУслуга.Код = "005"; ПерваяУслуга.Наименование = "Первая услуга"; ПерваяУслуга.Количество = ""; ВтораяУслуга = ГруппаУслуги.Строки.Добавить(); ВтораяУслуга.Код = "006"; ВтораяУслуга.Наименование = "Вторая услуга"; ВтораяУслуга.Количество = ""; // цикл по строкам верхнего уровня Для Каждого ТекущаяГруппа Из ДеревоЗначений.Строки Цикл Сообщить("Код: " + ТекущаяГруппа.Код + ", Группа: " + ТекущаяГруппа.Наименование); // цикл по дочерним строкам текущей строки верхнего уровня Для Каждого ТекущийТоварИлиУслуга Из ТекущаяГруппа.Строки Цикл Сообщить( "Код: " + ТекущийТоварИлиУслуга.Код + ", Товар или услуга: " + ТекущийТоварИлиУслуга.Наименование ); КонецЦикла; КонецЦикла; КонецПроцедуры
Код: 001, Группа: Товары Код: 003, Товар или услуга: Первый товар Код: 004, Товар или услуга: Второй товар Код: 002, Группа: Услуги Код: 005, Товар или услуга: Первая услуга Код: 006, Товар или услуга: Вторая услуга
КоллекцияКолонокДереваЗначений.Добавить(Имя, Тип, Заголовок, Ширина)
- Добавляет колонку в конец коллекции колонок дерева значений.
- Возвращаемое значение: КолонкаДереваЗначений .
КоллекцияСтрокДереваЗначений.Добавить()
- Добавляет строку в конец коллекции строк данного уровня дерева значений.
- Возвращаемое значение: СтрокаДереваЗначений .
Заполнить табличное поле на форме
Визуальное представление дерева значений на форме обеспечивает элемент Таблица .
Пример программного заполнения дерева значений для управляемых форм:
&НаКлиенте Процедура ЗаполнитьТабличноеПоле(Команда) ЗаполнитьТабличноеПолеНаСервере(); КонецПроцедуры &НаСервере Процедура ЗаполнитьТабличноеПолеНаСервере() ДеревоЗначений = РеквизитФормыВЗначение("РеквизитДеревоЗначений"); // Добавляем строку в корень дерева ПерваяСтрока = ДеревоЗначений.Строки.Добавить(); ПерваяСтрока.ПерваяКолонка = "Первая строка, первая колонка"; ПерваяСтрока.ВтораяКолонка = "Первая строка, вторая колонка"; // Дочерняя строка первой строки ВтораяСтрока = ПерваяСтрока.Строки.Добавить(); ВтораяСтрока.ПерваяКолонка = "Вторая строка, первая колонка"; ВтораяСтрока.ВтораяКолонка = "Вторая строка, вторая колонка"; // Дочерняя строка второй строки ТретьяСтрока = ВтораяСтрока.Строки.Добавить(); ТретьяСтрока.ПерваяКолонка = "Третья строка, первая колонка"; ТретьяСтрока.ВтораяКолонка = "Третья строка, вторая колонка"; ЗначениеВРеквизитФормы(ДеревоЗначений, "РеквизитДеревоЗначений"); КонецПроцедуры
Результат выполнения запроса очень легко преобразовать в дерево значений, для этого нужно воспользоваться методом Выгрузить() и указать параметр ТипОбхода отличным от того, что стоит по умолчанию, т.е. ПоГруппировкам или ПоГруппировкамСИерархией .
&НаКлиенте Процедура ЗаполнитьТабличноеПоле(Команда) ЗаполнитьТабличноеПолеНаСервере(); КонецПроцедуры &НаСервере Процедура ЗаполнитьТабличноеПолеНаСервере() Запрос = Новый Запрос(); Запрос.Текст = "ВЫБРАТЬ | Номенклатура.Наименование КАК ПерваяКолонка, | Номенклатура.Код КАК ВтораяКолонка |ИЗ | Справочник.Номенклатура КАК Номенклатура |УПОРЯДОЧИТЬ ПО | ПерваяКолонка ИЕРАРХИЯ"; ДеревоЗначений = Запрос.Выполнить().Выгрузить( ОбходРезультатаЗапроса.ПоГруппировкамСИерархией ); ЗначениеВРеквизитФормы(ДеревоЗначений, "РеквизитДеревоЗначений"); КонецПроцедуры
Свернуть и развернуть строки дерева значений
Свернуть и развернуть дочерние строки элемента дерева значений можно с помощью методов Свернуть() и Развернуть() .
ВсеЭлементыФормы.ЭлементТаблицаФормы.Свернуть(ИдектификаторСтроки)
- Сворачивает узел в указанной строке дерева.
- ИдектификаторСтроки — идентификатор строки таблицы.
ВсеЭлементыФормы.ЭлементТаблицаФормы.Развернуть(ИдектификаторСтроки, СПодчиненными)
- Разворачивает узел в указанной строке дерева.
- ИдектификаторСтроки — идентификатор строки таблицы.
- СПодчиненными — определяет необходимость раскрытия подчиненных узлов.
&НаКлиенте Процедура СвернутьТекущуюСтрокуДерева(Команда) Элементы.ЭлементДеревоЗначений.Свернуть( Элементы.ЭлементДеревоЗначений.ТекущаяСтрока ); КонецПроцедуры &НаКлиенте Процедура СвернутьВерхниеСтрокиДерева(Команда) СтрокиДерева = РеквизитДеревоЗначений.ПолучитьЭлементы(); Для Каждого ТекущаяСтрока Из СтрокиДерева Цикл Элементы.ЭлементДеревоЗначений.Свернуть( ТекущаяСтрока.ПолучитьИдентификатор() ); КонецЦикла; КонецПроцедуры &НаКлиенте Процедура СвернутьВсеСтрокиДерева(Команда) СтрокиДерева = РеквизитДеревоЗначений.ПолучитьЭлементы(); СвернутьДочерниеСтрокиДерева(СтрокиДерева); КонецПроцедуры &НаКлиенте Процедура СвернутьДочерниеСтрокиДерева(СтрокиДерева) Для Каждого ТекущаяСтрока Из СтрокиДерева Цикл ДочерниеСтроки = ТекущаяСтрока.ПолучитьЭлементы(); // рекурсивный вызов процедуры СвернутьДочерниеСтрокиДерева() СвернутьДочерниеСтрокиДерева(ДочерниеСтроки); Элементы.ЭлементДеревоЗначений.Свернуть( ТекущаяСтрока.ПолучитьИдентификатор() ); КонецЦикла; КонецПроцедуры
&НаКлиенте Процедура РазвернутьТекущуюСтрокуДерева(Команда) Элементы.ЭлементДеревоЗначений.Развернуть( Элементы.ЭлементДеревоЗначений.ТекущаяСтрока, Истина ); КонецПроцедуры &НаКлиенте Процедура РазвернутьВсеСтрокиДерева(Команда) СтрокиДерева = РеквизитДеревоЗначений.ПолучитьЭлементы(); Для Каждого ТекущаяСтрока Из СтрокиДерева Цикл Элементы.ЭлементДеревоЗначений.Развернуть( ТекущаяСтрока.ПолучитьИдентификатор(), Истина ); КонецЦикла; КонецПроцедуры
ДанныеФормыДерево.ПолучитьЭлементы()
- Получает коллекцию элементов дерева верхнего уровня.
- Возвращаемое значение: ДанныеФормыКоллекцияЭлементовДерева .
ДанныеФормыЭлементДерева.ПолучитьЭлементы()
- Получает коллекцию дочерних элементов.
- Возвращаемое значение: ДанныеФормыКоллекцияЭлементовДерева .
Для представления в форме объектов конфигурации (справочники, документы и т.п.) существуют специальные типы данных:
- ДанныеФормыСтруктура — содержит набор свойств произвольного типа. Свойствами могут быть другие структуры, коллекции или структуры с коллекциями. Таким типом представляется, например, в форме СправочникОбъект .
- ДанныеФормыКоллекция — это список типизированных значений, похожий на массив. Доступ к элементу коллекции осуществляется по индексу или по идентификатору. Доступ по идентификатору может отсутствовать в некоторых случаях. Это обусловлено типом прикладного объекта, который представлен этой коллекцией. Идентификатором может быть любое целое число. Таким типом представляется, например, в форме табличная часть.
- ДанныеФормыСтруктураСКоллекцией — это объект, который представлен в виде структуры и коллекции одновременно. С ним можно обращаться как с любой из этих сущностей. Таким типом представляется, например, в форме набор записей.
- ДанныеФормыДерево — объект предназначен для хранения иерархических данных.
Прикладной объект представлен либо одним, либо несколькими элементами данных формы. Например, документ, содержащий табличную часть, будет представлен объектом типа ДанныеФормыСтруктура (собственно документ), которому подчинен объект типа ДанныеФормыКоллекция (табличная часть документа).
Удалить строку и очистить дерево значений
&НаКлиенте Процедура УдалитьСтрокуДереваЗначений(Команда) УдалитьСтрокуДереваЗначенийНаСервере(); КонецПроцедуры &НаСервере Процедура УдалитьСтрокуДереваЗначенийНаСервере() ДеревоЗначений = РеквизитФормыВЗначение("РеквизитДеревоЗначений"); // удаляем первую строку дерева значений ДеревоЗначений.Строки.Удалить(0); ЗначениеВРеквизитФормы(ДеревоЗначений, "РеквизитДеревоЗначений"); КонецПроцедуры
&НаКлиенте Процедура ОчиститьДеревоЗначений(Команда) ОчиститьДеревоЗначенийНаСервере(); КонецПроцедуры &НаСервере Процедура ОчиститьДеревоЗначенийНаСервере() ДеревоЗначений = РеквизитФормыВЗначение("РеквизитДеревоЗначений"); ДеревоЗначений.Строки.Очистить(); ЗначениеВРеквизитФормы(ДеревоЗначений, "РеквизитДеревоЗначений"); КонецПроцедуры
Поиск в дереве значений
Среди наиболее часто используемых методов стоит отметить метод Найти() коллекции строк дерева значений.
КоллекцияСтрокДереваЗначений.Найти(Значение, Колонки, ВключатьПодчиненные)
- Значение (обязательный, тип Произвольный ). Искомое значение.
- Колонки (необязательный, тип Строка ). Список имен колонок, в которых будет осуществляться поиск, разделенных запятыми. Если параметр не указан, поиск осуществляется по всем колонкам дерева. Значение по умолчанию — Пустая строка.
- ВключатьПодчиненные (необязательный, тип Булево ). Определяет, будут ли участвовать в поиске строки подчиненных коллекций (если таковые имеются). Если Истина — строки подчиненных коллекций участвуют в поиске. Значение по умолчанию — Ложь .
Метод осуществляет поиск значения в дереве в указанных колонках коллекции строк дерева значений. Возвращает строку (тип СтрокаДереваЗначений ), которая содержит искомое значение. Если значение не найдено, то возвращается значение Неопределено . Предназначен для поиска уникальных значений.
&НаКлиенте Процедура НайтиСтрокуДереваЗначений(Команда) ЗаполнитьТабличноеПолеНаСервере(); НайтиСтрокуДереваЗначенийНаСервере(); КонецПроцедуры &НаСервере Процедура НайтиСтрокуДереваЗначенийНаСервере() ДеревоЗначений = РеквизитФормыВЗначение("РеквизитДеревоЗначений"); РезультатПоиска = ДеревоЗначений.Строки.Найти( ИскомоеЗначение, "ПерваяКолонка,ВтораяКолонка", Истина ); Если РезультатПоиска > Неопределено Тогда Сообщить( "Первая колонка: " + РезультатПоиска.ПерваяКолонка + ", Вторая колонка: " + РезультатПоиска.ВтораяКолонка ); Иначе Сообщить("Ничего не найдено"); КонецЕсли; КонецПроцедуры &НаСервере Процедура ЗаполнитьТабличноеПолеНаСервере() Запрос = Новый Запрос(); Запрос.Текст = "ВЫБРАТЬ | Номенклатура.Наименование КАК ПерваяКолонка, | Номенклатура.Код КАК ВтораяКолонка |ИЗ | Справочник.Номенклатура КАК Номенклатура |УПОРЯДОЧИТЬ ПО | ПерваяКолонка ИЕРАРХИЯ"; ДеревоЗначений = Запрос.Выполнить().Выгрузить( ОбходРезультатаЗапроса.ПоГруппировкамСИерархией ); ЗначениеВРеквизитФормы(ДеревоЗначений, "РеквизитДеревоЗначений"); КонецПроцедуры
Источник