- Как получить все данные из дерева значений?
- v8: Как выбрать все строки дерева значений?
- Дерево значений в 1С 8.3
- Дерево значений на управляемой форме
- Заполнение дерева значений
- Ручное заполнение реквизита формы с типом «ДеревоЗначений»
- Заполнение дерева значений из результата запроса
- Поиск строк в дереве значений
- Метод «Найти()»
- Метод «НайтиСтроки()»
- Очистка дерева значений или строк
- Обход дерева значений в 1С
- Как преобразовать дерево значений в таблицу значений
Как получить все данные из дерева значений?
У меня простой и наверное банальный вопрос. Как получить все данные из дерева значений неограниченной вложенности?
В поиск прошу не посылать. Сразу туда ходил.. Но ничего не нашел кроме как использовать поиск.
Помогите построить такую рекурсивную выборку (обход) дерева значений
Процедура ВывестиСтрокуИПодчиненные(Стр,Отступ = «»)
Сообщить(Отступ+Стр.«что-нибудь»);
Для каждого Подч из Стр Цикл
ВывестиСтрокуИПодчиненные(Подч, Отступ+» «);
КонецЦикла
КонецПроцедуры
ну, или что-то типа того.
Чтобы понять рекурсию, надо понять рекурсию!
Функция ПрочитатьЗначениеСтрокиДерева(пСтрокаДерева, пТабличко)
Для Каждого цСтрока Из пСтрокаДерева Цикл
НовСтр = пТабличко.Добавить();
НовСтр.Значение = цСтрока.Значение;
ПрочитатьЗначениеСтрокиДерева(цСтрока, пТабличко);
+ (3) вместо Для Каждого цСтрока Из пСтрокаДерева Цикл
читать
Для Каждого цСтрока Из пСтрокаДерева.Строки Цикл
(9)ограничена вложенность. Поэтому итерация врядли здесь уместна.
но если не сложно выложите. интересно как это делает итерационно
если организовать стек родителей, то теоретически можно в цикле обработать. но это будет долго, и потом хрен отладишь, а через пол года когда туда взглянешь, воскликнешь: какого хухя я это не через рекурсию сделал.
добавляешь в дерево недоступную колонку типа булево и МоеДерево.Строки.НайтиСтроки(Новый Структура(«СпецКоллонка», Ложь), Истина) вернет массив всех строк
была у меня такая проблема — надо было посмотреть что находится в ветке дерева значений. само дерево доступно не было, а у ветки нету метода ВыбратьСтроку(). В итоге пришлось написать выгрузку ветки в дерево.
Процедура ДобавитьСтрокуВДерево(СтрокаРодитель1, СтрокаДерева) СтрокаРодитель2 = СтрокаРодитель1.Строки.Добавить(); ТекИндекс = 0; Для Каждого Знч Из СтрокаДерева Цикл СтрокаРодитель2.Установить(ТекИндекс, Знч); ТекИндекс = ТекИндекс + 1; КонецЦикла; КоллекцияСтрок = СтрокаДерева.Строки; Для Каждого СтрокаПодчиненная Из СтрокаДерева.Строки Цикл ДобавитьСтрокуВДерево(СтрокаРодитель2, СтрокаПодчиненная); КонецЦикла; КонецПРоцедуры //Вывод на экран структуры строки дерева Процедура ВСД(СтрокаДерева) Дерево = Новый ДеревоЗначений; Для Каждого Знч Из СтрокаДерева Цикл Дерево.Колонки.Добавить(); КонецЦикла; ДобавитьСтрокуВДерево(Дерево, СтрокаДерева); Дерево.ВыбратьСтроку(); КонецПроцедуры
пусть ГлавныйРодитель — корневой элемент
тогда напишем кривой итерационный код который мне в силу глубокого нежелания грузить стэк нравится больше
МассивГотовых = Новый массив;
Пока истина цикл
МассивПотомков = главныйРодитель.ПолучитьПотомков();
Для каждого Элемент из массивпотомков цикл
конецЦикла
МассивПотомков = промежуточныйМассивПотомков;
Если Массивпотомков.количество() = 0 тогда
Прервать
конецЕсли
конецЦикла
что то вроде такого. Писал навскидку багов не исключаю, но вроде бы существует теорема о том что любой рекурсивный метод можно реализовать итерационно
ой))) надо чуть чуть по другому
МассивГотовых = Новый массив;
МассивПотомков = главныйРодитель.ПолучитьПотомков();
Пока истина цикл
Для каждого Элемент из массивпотомков цикл
МассивГотовых.Добавить(Элем);
конецЦикла
МассивПотомков = промежуточныйМассивПотомков;
Если Массивпотомков.количество() = 0 тогда
Прервать
конецЕсли
конецЦикла
Источник
v8: Как выбрать все строки дерева значений?
Получилось так:
======================================================
ДерЗнач.Колонки.Добавить(«НовоеПоле»);
ВсеСтроки = ДерЗнач.Строки.НайтиСтроки(Новый Структура(«НовоеПоле», Неопределено), Истина);
======================================================
Но это как-то странно. Есть ли более правильный способ?
Не нужно выбирать все строки, свойство «Строки» — это коллекция, иди по коллекции и будет тебе счастье.
Не понял о чем говорит (1). Коллекция-коллекцией, но при выборке из неё будут выбираться только строки первого уровня? На то оно и дерево.
Для выборки всех строк дерева используй простейшую рекурсию.
.
Процедура ВыбратьВсеСтрокиДерева(Дерево)
Для Каждого СтрокаДерева Из Дерево.Строки Цикл
Сообщить(«Строка: «+СтрокаДерева);
ВыбратьВсеСтрокиДерева(СтрокаДерева.Строки);
КонецЦикла
КонецПроцедуры
(1) При переборе этой коллекции будут выбираться только строки первого уровня, так что счастья не будет 🙂
(2) Спасибо, но по-моему, решение в (0) проще, чем рекурсия 🙂
(3) 🙂 Смотря для какой цели. Мне, например, надо было перебирать дерево и по выполнению определённого условия выпадать из перебора с возвратом Истина. Рекурсия замечательно отрабатывает, надеюсь (хотя не проверял) быстрее чем добавление новой колонки и поиск строк по ней.
К тому же в рекурсии можно на ходу определять уровень строки.
.
А для каких-то случаев, возможно, первый вариант более приемлем благодаря своей простоте.
Источник
Дерево значений в 1С 8.3
Объект «ДеревоЗначений» в 1С 8.3 представляет собой динамический набор значений любого типа. Для такого набора доступны свойства «колонки» и «строки» где каждая строка может иметь набор подчинённых строк, а каждая подчинённая строка набор своих подчинённых строк и т.д. Программная инициализация дерева значений в 1С осуществляется с помощью оператора НОВЫЙ.
ДеревоЗначений = Новый ДеревоЗначений;
Визуально, объект «ДеревоЗначений» похож на дерево групп справочника. К примеру, можно открыть справочник «Номенклатура» любой типовой конфигурации выставив форму списка в «Режим просмотра» — «Дерево».
Полезно понимать, что объект «ДеревоЗначений» схож с объектом «ТаблицаЗначений». Основной отличительный признак наличие дополнительного реквизита «Родитель» у объекта «ДеревоЗначений», с помощью которого и организовывается иерархия и подчинённость.
Наша команда предоставляет услуги по консультированию, настройке и внедрению 1С.
Связаться с нами можно по телефону +7 499 350 29 00.
Услуги и цены можно увидеть по ссылке.
Будем рады помочь Вам!
Дерево значений на управляемой форме
Если появляется необходимость показать данные в виде дерева пользователю, следует на форме создать реквизит с типом «ДеревоЗначений» и определится с составом колонок.
Для отображения на форме добавим реквизит в раздел элементов формы простым перетаскиванием.
Заполнение дерева значений
Получите понятные самоучители по 1С бесплатно:
Заполнить данными дерево значений в 1С можно программно (вручную) или получить из результата запроса. Рассмотрим на примерах оба способа.
Ручное заполнение реквизита формы с типом «ДеревоЗначений»
&НаКлиенте Процедура ДЗ_НаФорме(Команда) ДЗ_НаФормеНаСервере(); КонецПроцедуры &НаСервере Процедура ДЗ_НаФормеНаСервере() // Преобразуем реквизит формы ДЗ в объект прикладного типа ДеревоЗначений = РеквизитФормыВЗначение("ДЗ"); Корень = ДеревоЗначений.Строки.Добавить(); Корень.Наименование = "Корневая группа"; Группа1 = Корень.Строки.Добавить(); Группа1.Наименование = "Первая группа"; Элемент1 = Группа1.Строки.Добавить(); Элемент1.Наименование = "Элемент №1"; Группа2 = Корень.Строки.Добавить(); Группа2.Наименование = "Втровая группа"; Элемент1 = Группа2.Строки.Добавить(); Элемент1.Наименование = "Элемент №1"; Элемент2 = Группа2.Строки.Добавить(); Элемент2.Наименование = "Элемент №2"; // Преобразуем объект ДеревоЗначений в реквизит формы ЗначениеВРеквизитФормы(ДеревоЗначений,"ДЗ"); КонецПроцедуры
Результат запроса на форме:
Заполнение дерева значений из результата запроса
Сделаем простой запрос к справочнику «Номенклатура». Результат запроса преобразуем в дерево значений с помощью метода «Выгрузить», установив для его параметра «ТипОбхода» в значение «ПоГруппировкамСИерархией». Для передачи сформированного дерева значений на форму, важно чтобы имена колонок совпадали с именами колонок реквизита на форме.
&НаКлиенте Процедура ДЗ_НаФорме(Команда) ДЗ_НаФормеНаСервере(); КонецПроцедуры &НаСервере Процедура ДЗ_НаФормеНаСервере() Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | Номенклатура.Ссылка КАК Наименование |ИЗ | Справочник.Номенклатура КАК Номенклатура | |УПОРЯДОЧИТЬ ПО | Наименование ИЕРАРХИЯ"; ДеревоЗначений = Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией); ЗначениеВРеквизитФормы(ДеревоЗначений, "ДЗ"); КонецПроцедуры
Результат запроса на форме может выглядеть так:
Поиск строк в дереве значений
Для поиска строк в дереве значений существует два способа, точнее говоря, метода.
Метод «Найти()»
Возвращает строку дерева значений, если строка не найдена, вернёт «Неопределено». Поиск можно ограничивать, указав в параметре нужные колонки для поиска. Также расширять, указав для параметра значение «Истина», тогда в поиске будут участвовать строки подчинённых коллекций.
Для примера найдём строку со значением «Элемент №1» в дереве значений вида:
&НаКлиенте Процедура НайтиСтрокуДЗ(Команда) НайтиСтрокуДЗ_НаСервере(); КонецПроцедуры &НаСервере Процедура НайтиСтрокуДЗ_НаСервере() // Преобразуем реквизит формы ДЗ в объект прикладного типа ДеревоЗначений = РеквизитФормыВЗначение("ДЗ"); // Ищем строку НайденнаяСтрока = ДеревоЗначений.Строки.Найти("Элемент №1","Наименование", Истина); // Анализ результата поиска Если НайденнаяСтрока = Неопределено Тогда Сообщить("Строка не найдена"); Иначе Сообщить(НайденнаяСтрока.Наименование + " - " + НайденнаяСтрока.Родитель.Наименование); КонецЕсли; КонецПроцедуры
Из результата видно, что метод вернул первую попавшуюся строку, и поиск был прекращён.
Метод «НайтиСтроки()»
Если необходимо найти все строки со значением «Элемент №1» тогда следует использовать метод НайтиСтроки()
Где — это условия для поиска в виде структуры, а параметр с помощью значений Ложь/Истина контролирует возможность поиска в подчинённых коллекциях.
&НаКлиенте Процедура НайтиСтрокиДЗ(Команда) НайтиСтрокиДЗНаСервере(); КонецПроцедуры &НаСервере Процедура НайтиСтрокиДЗНаСервере() // Преобразуем реквизит формы ДЗ в объект прикладного типа ДеревоЗначений = РеквизитФормыВЗначение("ДЗ"); // Условие для поиска ПараметрыОтбора = Новый Структура; ПараметрыОтбора.Вставить("Наименование", "Элемент №1"); // Поиск строк МассивСтрок = ДеревоЗначений.Строки.НайтиСтроки(ПараметрыОтбора, Истина); // Проверяем найдены ли строки Если МассивСтрок.Количество() = 0 Тогда Сообщить("Не найдено ни одной строки, удовлетворяющей условия поиска."); КонецЕсли; // Перебор массива строк Для Каждого Строка Из МассивСтрок Цикл Если Строка.Родитель = Неопределено Тогда Сообщить(Строка.Наименование + " - Корень дерева значений."); Иначе Сообщить(Строка.Наименование + " - " + Строка.Родитель.Наименование); КонецЕсли КонецЦикла; КонецПроцедуры
Очистка дерева значений или строк
Для очистки дерева значений пригодятся методы Очистить(), Удалить(). Пример кода:
&НаСервере Процедура УдалитьСтрокуНаСервере() // Преобразуем реквизит формы ДЗ в объект прикладного типа ДеревоЗначений = РеквизитФормыВЗначение("ДЗ"); ДеревоЗначений.Строки.Очистить(); // Или по индексу ДеревоЗначений.Строки.Удалить(0); // Преобразуем объект ДеревоЗначений в реквизит формы ЗначениеВРеквизитФормы(ДеревоЗначений, "ДЗ"); КонецПроцедуры
С помощью данных методов возможно удаление конкретных строк дерева значений.
. При удалении либо очистки строки все её подчинённые строки удалятся.
Обход дерева значений в 1С
Обойти все строки дерева значений удобнее всего с помощью рекурсии. Таким способом мы сможем обойти дерево значений любой вложенности.
&НаСервере Процедура ОбойтиДЗ_НаСервере() ДеревоЗначений = РеквизитФормыВЗначение("ДЗ"); ОбходДереваЗначений(ДеревоЗначений); КонецПроцедуры &НаСервере Процедура ОбходДереваЗначений(Данные) Для Каждого Строка Из Данные.Строки Цикл Сообщить(Строка.Наименование); Если Строка.Строки.Количество()>0 Тогда ОбходДереваЗначений(Строка); КонецЕсли; КонецЦикла; КонецПроцедуры
Как преобразовать дерево значений в таблицу значений
Состав элементов и реквизитов формы:
&НаКлиенте Процедура ВТЗ(Команда) ВТЗНаСервере(); КонецПроцедуры &НаСервере Процедура ВТЗНаСервере() ДеревоЗначений = РеквизитФормыВЗначение("ДЗ"); ТаблицаЗначений = РеквизитФормыВЗначение("ТЗ"); ПреобразоватьВ_ТЗ(ДеревоЗначений, ТаблицаЗначений, Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000")); ДеревоЗначений.Строки.Очистить(); ЗначениеВРеквизитФормы(ТаблицаЗначений, "ТЗ"); ЗначениеВРеквизитФормы(ДеревоЗначений, "ДЗ"); КонецПроцедуры &НаСервере Процедура ПреобразоватьВ_ТЗ(Данные, ТаблицаЗначений, ГУИД) Для Каждого Строка Из Данные.Строки Цикл НовСтрока = ТаблицаЗначений.Добавить(); НовСтрока.Наименование = Строка.Наименование; НовСтрока.Родитель = ГУИД; НовСтрока.ГУИД = Новый УникальныйИдентификатор(); Если Строка.Строки.Количество()>0 Тогда ПреобразоватьВ_ТЗ(Строка, ТаблицаЗначений, НовСтрока.ГУИД); КонецЕсли; КонецЦикла; КонецПроцедуры
Используя данный способ можно легко преобразовать таблицу значений обратно в дерево значений. Из примера «ГУИД» это уникальный идентификатор строки, а «Родитель» уникальный идентификатор родителя. Если обратного преобразования не требуется можно исключить использование колонок «Родитель» и «ГУИД».
Источник