- Рекурсия в 1С и управление деревом значений
- Работа с деревом значений в 1С
- Дерево значений
- Дерево значений на форме
- Заполнение дерева значений
- Обход дерева значений
- Как свернуть и развернуть дерево значений
- Как удалить строку и очистить дерево значений
- Запрос и дерево значений
- Дерево значений в таблицу значений и обратно
- Отбор в дереве значений
- Рекурсивное заполнение дерева на форме результатом запроса в виде дерева значений.
Рекурсия в 1С и управление деревом значений
Термин «рекурсия» используется во многих областях знаний. В программировании рекурсия – вызов процедуры (функции) из нее же самой. Статья рассказывает об использовании рекурсии в 1С Предприятии для работы с деревом значений.
Термин «рекурсия» используется во многих областях знаний. В программировании рекурсия – вызов процедуры (функции) из нее же самой. Различают простую и сложную рекурсию. При простой рекурсии некоторая процедура А вызывает сама себя, пока не выполниться заданное условие выхода, или же бесконечно. В случае сложной рекурсии процедура А вызывает процедуру Б, которая опять вызывает процедуру А, и так далее до выполнения условия выхода или бесконечно. В сложной рекурсии может участвовать и больше двух процедур или функций. Организовать рекурсию средствами встроенного языка 1С Предприятия очень легко. Вот пример простой рекурсии: Процедура ПроцедураА ()
ПроцедураА ();
КонецПроцедуры А это сложная рекурсия: Процедура ПроцедураА ()
ПроцедураБ ();
КонецПроцедуры
Процедура ПроцедураБ ()
ПроцедураА ();
КонецПроцедуры Оба фрагмента кода приведены исключительно для примера. При попытке их выполнить возникнет бесконечный цикл и, как результат, произойдет зависание системы, поскольку не задано условие выхода. Создадим рекурсию с условием выхода: Процедура ВывестиЧисла ( пЧисло )
Если пЧисло Сообщить ( Строка ( пЧисло ));
пЧисло = пЧисло + 1 ;
ВывестиЧисла ( пЧисло );
Иначе
Возврат;
КонецЕсли;
КонецПроцедуры
ВывестиЧисла ( 1 ); Этот фрагмент кода выведет в окно служебных сообщений 1С Предприятия числа от 1 до 100. После этого выполниться условие выхода и программа будет завершена. Процедура вызовет сама себя ровно 100 раз. Количество таких вызовов процедуры или функции называется глубиной рекурсии. Реализация рекурсивных вызовов функций и процедур в практически применяемых языках и средах программирования, использует механизм стека вызовов — адрес возврата и локальные переменные функции записываются в стек, благодаря чему каждый следующий рекурсивный вызов этой функции пользуется своим набором локальных переменных и за этот счёт работает корректно. Оборотной стороной этого довольно простого по структуре механизма является то, что рекурсивные вызовы не бесплатны — на каждый рекурсивный вызов требуется некоторое количество оперативной памяти компьютера, и при чрезмерно большой глубине рекурсии может наступить переполнение стека вызовов. Вследствие этого обычно рекомендуется избегать рекурсивных программ, которые приводят к слишком большой глубине рекурсии. Пример с выводом чисел естественно не является оптимальным, он приведен только в целях демонстрации. На практике в этом случае гораздо удобнее использовать цикл. Рекурсию следует использовать там, где с помощью циклов решать задачу нецелесообразно. В 1С Предприятии 8.х рекурсия может быть использована для решения задач управления деревом значений. Например, мы интерактивно изменяем пометку элемента, который находиться на одном из верхних уровней дерева значений. В таком случае пометки должны программно устанавливаться (или сниматься) и для всех подчиненных ему элементов, находящихся на более низких уровнях дерева. Если максимальное количество уровней дерева известно, то эта задача может быть решена следующим образом: Процедура ИзменитьПометкиПодчиненных ( пГлавный )
Подчиненные1 = пГлавный . Строки ;
// Первый уровень подчиненных
Для Каждого Подчиненный1 Из Подчиненные1 Цикл
Подчиненный1 . Пометка = пГлавный . Пометка ;
Подчиненные2 = Подчиненный1 . Строки ;
// Второй уровень подчиненных
Для Каждого Подчиненный2 Из Подчиненные2 Цикл
Подчиненный2 . Пометка = пГлавный . Пометка ;
Подчиненные3 = Подчиненный2 . Строки ;
Источник
Работа с деревом значений в 1С
В последнее время аномально часто мне в работе попадалось дерево значений, поэтому решил написать на эту тему статью.
Попробую рассмотреть способы решения основных задач связанных с деревом значений, при этом постараюсь писать «без воды».
Дерево значений
Из названия объекта понятно, что дерево значений служит для хранения/отображения какой-либо иерархической информации. Каждая строка дерева значений может иметь какое-то количество подчиненных строк, при этом такие операции как поиск, сортировка, подсчет итогов можно проводит с учетом уровня иерархии и подчиненных строк.
Кроме этого, каждая строка дерева значений имеет свойства «Родитель» и «Строки».
Дерево значений на форме
Визуальное представление дерева значений обеспечивает элемент «Табличное поле».
Заполнение дерева значений
При заполнении дерева значений нужно помнить, что сам объект «ДеревоЗначений» и все его строки имеют свойство «Строки»и добавление новых строк на любом уровне дерева осуществляется через это свойство.
Сам же объект «ДеревоЗначений» имеет еще и свойство «Колонки», которое ничем не отличается от аналогичного свойства у таблицы значений.
Небольшой пример программного заполнения таблицы значений для управляемых форм:
Обход дерева значений
Обход всех строк дерева значений делается при помощи рекурсии, вот так будет выглядеть код для обхода дерева созданного в примере выше:
Как свернуть и развернуть дерево значений
Сворачивается и разворачивается дерево значений очень просто.
Привел три примера: для сворачивания текущей строки, для сворачивания строк верхнего уровня, для сворачивания вообще всех строк (рекурсия).
Два примера: для разворачивания текущей строки и для разворачивания всех строк. У метода «Развернуть» есть дополнительный параметр, который позволяет указать нужно ли разворачивать подчиненные строки.
Как удалить строку и очистить дерево значений
Тут опять же все просто, нужно помнить, что при удалении/очистке строки, все подчиненные строки удаляются.
Точно также можно очистить от подчиненных элементов другую другую строку.
Удалить строку дерева значений не сложнее — нужно только знать ее индекс:
Запрос и дерево значений
Результат выполнения запроса очень легко преобразовать в дерево значений, для этого нужно воспользоваться методом «Выгрузить» и указать параметр «ТипОбхода» отличным от того, что стоит по умолчанию, т.е. «ПоГруппировкам» или «ПоГруппировкамСИерархией».
Если на форме имеется реквизит «ДеревоЗначений» и связанный с ним визуальный элемент, то можно сделать примерно так:
Причем полного совпадения колонок и типов не требуется — лишние колонки будут просто отброшены, а колонки с различными типами будут заполнены пустыми значениями.
Дерево значений в таблицу значений и обратно
Преобразовать дерево значений в таблицу значений и наоборот достаточно просто, ведь дерево значений это та же таблица значений, но с дополнительной колонкой — «Родитель». У меня есть отдельная статья о том как преобразовать дерево значений в таблицу значений и обратно.
Отбор в дереве значений
Стандартного отбора в дереве значений не предусмотрено. Так получилось потому, что непонятно как разрешать ситуацию, когда родительский элемент не удовлетворяет условию отбора, а подчиненные ему элементы удовлетворяют.
Таким образом, если Вам нужно реализовать отбор в дереве значений, то начать нужно с решения именно этой проблемы. А уже после этого можно придумать несколько способов реализовать задуманное.
Первый способ — накладывать отбор до вывода дерева значений (в запросе например). Это не классический отбор, но в тех случаях когда этот способ применим, то следует применять именно его, так как это почти всегда быстрее и правильнее чем что-либо другое.
Второй способ — перебор всех строк дерева значений. Описывать здесь особенно нечего, нужно просто взять обход дерева значений, проверять каждую строку на соответствие условию отбора и удалять лишние строки.
Еще один способ заключается в том, чтобы преобразовать дерево значений в таблицу значений, сделать отбор в таблице значений, проконтролировать результат (почистить «хвосты» — строки, родитель которых не удовлетворил условию отбора) и выполнить обратное преобразование в дерево значений.
На этом все, рассказал все, что знал, надеюсь мне удалось сэкономить Вам немного времени.
Если Вы нашли ошибку или неточность, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.
(оценок: 36, средняя оценка: 4,64 из 5)
Источник
Рекурсивное заполнение дерева на форме результатом запроса в виде дерева значений.
Добрый вечер, форумчане! Искал в интернете способы заполнения дерева на форме результатом запроса в виде дерева значений, все примеры не дают никакого понимания принципа, как именно заполняется дерево. Если кому-то не очень лень, объясните, пожалуйста, на пальцах принцип, как с помощью рекурсивной функции заполнить дерево? Если есть источник, где информация изложена предельно ясно, был бы так же благодарен.
Дерево.Загрузить( Результатзапроса.Выгрузить( РежимОбхода.ПоГруппировкам ) ) ЗначениеВРекаизитФормы( Дерево, "ДеревоНаФорме" )
Дерево.Загрузить( Результатзапроса.Выгрузить( РежимОбхода.ПоГруппировкам ) ) ЗначениеВРекаизитФормы( Дерево, "ДеревоНаФорме" )
Запрос = Новый Запрос("ВЫБРАТЬ | СтруктураПредприятия.Ссылка КАК Ссылка, | Пользователи.Сотрудник КАК Сотрудник, | СтруктураПредприятия.Родитель КАК Родитель |ИЗ | Справочник.СтруктураПредприятия КАК СтруктураПредприятия | ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Пользователи КАК Пользователи | ПО СтруктураПредприятия.Ссылка = Пользователи.ТекущееПодразделение |ИТОГИ ПО | Ссылка ИЕРАРХИЯ"); ДеревоЗначений = Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией); ЗначениеВРеквизитФормы(ДеревоЗначений, "ДеревоПользователей");
Возникает ошибка ниже. Пробовал уже такой вариант. «ДеревоЗначений» имеет тип ДеревоЗначений.
На этом скрине нет того, что я прошу.
(9) Да без проблем. Только для реквизита формы «ДеревоЗначений» разве есть метод объекта «Загрузить»?
(11) И тем не менее, ЗначениеВРеквизитФормы возвращает вот такую ошибку. Вероятнее всего, я просто не понимаю, как правильно это сделать.
Статья. Что такое рекурсия.
Рекурсия — это когда процедура вызывает сама себя.
Конец статьи.
Процедура ЗаполнитьДерево(СтрокаДерева, СтрокаКоторуюЗаполняем) ЗаполнитьЗначенияСвойств(СтрокаКоторуюЗаполняем, СтрокаДерева); Для Каждого СтрокаСтроки Из СтрокаДерева.Строки Цикл ЗаполнитьДерево(СтрокаСтроки, СтрокаКоторуюЗаполняем.Строки.Добавить()); КонецЦикла; КонецПроцедуры Процедура ГдеНадоВызватьЗаполнение() Для Каждого Строка Из ДеревоИсходное Цикл ЗаполнитьДерево(Строка, ДеревоДляЗаполнения.Строки.Добавить()); КонецПроцедуры
Источник