Работа с иерархическими детальными записями
Система компоновки данных позволяет выводить в отчет иерархические детальные записи. В данной статье описываются особенности работы с данным механизмом.
При выводе в результат детальных записей система анализирует наличие у выводимого набора данных связи к самому себе. В случае если такая связь обнаружена, система рекурсивно выполняет связь для получения вложенных записей.
Рассмотрим пример. В примере будем выдавать в отчет иерархический справочник номенклатуры.
Запрос набора данных для получения номенклатуры будет выглядеть так:
ВЫБРАТЬ Номенклатура.Ссылка, Номенклатура.Родитель, Номенклатура.Код, Номенклатура.Наименование, Номенклатура.ЭтоГруппаИЗ Справочник.Номенклатура КАК НоменклатураГДЕ Номенклатура.Родитель В(&Родители)
При помощи данного запроса будут получаться записи с указанным родителем. Если параметр Родитель будет содержать пустую ссылку, то будут получены записи, у которых родителей нет, т.е. корневые записи.
Набор данных с указанным запросом назовем Номенклатура.
Для обеспечения вывода иерархии опишем связь набора данных Номенклатура к самому себе.
В качестве выражения — источника будем использовать значение поля Ссылка.
В качестве выражения — приемника буем использовать значение поля Родитель.
Таким образом, для каждой записи набора данных в наборе данных будут искаться записи, у которых поле Родитель имеет значение поля Ссылка родительской записи.
Т.к. запрос получает данные с фильтрацией по родителю, в связи укажем параметр связи «Родитель». Таким образом, при получении дочерних записей система будет передавать значения поля Ссылка дочернему запросу через этот параметр. Т.к. параметр Родитель используется в конструкции языка запроса В, то в качестве значения параметра система может передавать не одно, а сразу несколько значений. Чтобы система это делала, укажем в связи признак «Список параметров».
Справочник Номенклатура имеет иерархию групп и элементов. При этом дочерние записи могут существовать только у групп. Поэтому, для того, чтобы система не осуществляла поиск дочерних записей не у групповых записей, укажем в связи условие связи: «ЭтоГруппа». Таким образом, система будет выполнять запросы для получения дочерних записей только для тех записей, у которых значение поля ЭтоГруппа имеет значение Истина, т.е. только для групп.
Последнее, что нам нужно сделать, это указать, с какого значения система должна начинать получать иерархические записи. Делается это при помощи свойства связи «Начальное значение связи». Нам нужно, чтобы на первом уровне отчета выдавались записи, у которых родитель отсутствует. Поэтому в качестве начального значения связи укажем выражение «Значение(Справочник.Номенклатура.ПустаяСсылка)» (без кавычек). Таким образом, при первом получении данных из набора данных система будет получать записи, у которых значение поля Родитель равно пустой ссылке, т.е. корневые записи.
На следующем рисунке показана полностью заполненная связь в конструкторе схемы:
Для вывода в результат такого набора данных достаточно вывести в результат детальные записи с нужными полями.
Для этого добавим в настройки детальные записи (группировку без полей группировки) и выберем поля, которые мы хотели бы видеть в результате:
Результат такого отчета будет выглядеть следующим образом:
Код | Наименование |
0000001 | Мониторы |
0000021 | Монитор 15′ LG Studioworks 575N |
0000022 | Монитор 17′ Philips 107S20 |
0000023 | Монитор 19′ Hitachi CM715ET |
0000024 | Монитор LCD 22′ M8537ZM/A |
0000002 | Системные блоки и комплектующие |
0000036 | Сист. блок Hewlett-Packard Brio BA410 |
0000037 | Сист. блок Hewlett-Packard Vectra VL420 |
0000038 | Сист. блок IBM NetVista A22p |
0000039 | Сист. блок IBM NetVista M41 |
0000003 | Принтеры |
0000030 | Лазерный принтер Canon LBP-810 |
0000031 | Лазерный принтер 5250197-203 Minolta-QMS |
0000032 | Лазерный принтер HP LaserJet 2200 |
0000004 | Мыши |
0000025 | Мышь 2-кноп A4Tech PS/2 |
0000026 | Мышь OK-720 Mouse A4Tech PS/2 |
0000027 | Мышь Ice Mouse MUS-2 |
0000028 | Мышь LOGITECH M-S48 PS/2 |
0000029 | Мышь GENIUS «EASY» (3 кнопки), |
0000005 | Клавиатуры |
0000018 | Клавиатура Apple Pro Keyboards |
0000020 | Клавиатура LK-601 KB-2000 PS/2 |
0000006 | Программное обеспечение |
0000045 | Windows |
0000009 | Windows XP Home Edition Russian CD |
0000010 | Windows XP Home Edition Russian UPG CD |
0000011 | Windows XP Professional Russian CD |
0000012 | 1С:Бухгалтерия 7.7 Базовая версия |
0000013 | 1С:Бухгалтерия 7.7 Стандартная версия |
0000014 | 1С:Бухгалтерия ПРОФ версия 7.7 |
0000015 | 1С:Аспект 7.7 |
0000016 | 1С:Торговля и Склад 7.7 Проф |
0000007 | Услуги |
0000041 | Доставка |
0000042 | Инсталляция ПО |
0000043 | Консультации по настройке ОС Windiws |
0000044 | Консультации по настройке 1С |
0000033 | Ноутбуки |
0000034 | Ноутбук Rover Computers Navigator KT7 |
0000035 | Ноутбук Rover Computers Explorer |
0000046 | Телефоны |
0000047 | Телефон Vega 700 |
0000048 | Телефон Vega 300 |
0000051 | Телефон Siemens SL45 |
0000052 | Телефон LG W7200 |
0000049 | Копировальные аппараты |
0000050 | Копировальный аппарат Omega |
Получить родителя элемента иерархического справочника
Если у справочника в свойствах задано Иерархический справочник, то может возникнуть необходимость найти родителя элемента справочника. Количество уровней иерархии в справочнике может быть как ограниченным, так и без ограничений.
Если количество уровней фиксированное, то через точку можно получить родительский элемент любого уровня.
РодительСсылка = СправочникСсылка.Родитель.Родитель.Родитель;
Если количество уровней не ограничено, то можно на встроенном языке 1С написать универсальную функцию, которая определит самую верхнюю группу.
Определить самого верхнего родителя
Универсальную функцию для определения самого верхнего родителя элемента можно реализовать с помощью встроенного языка программирования. Функции на вход подаётся ссылка на элемент иерархического справочника, а возвращается ссылка на самую верхнюю группу.
Функция ПолучитьРодителя(СправочникСсылка)
Пока НЕ СправочникСсылка.Родитель.Пустая() Цикл
СправочникСсылка = СправочникСсылка.Родитель;
КонецЦикла;
Возврат СправочникСсылка;
КонецФункции
Определить самого верхнего родителя с использованием запроса
В запросе можно найти родителей элемента обратившись к свойствам через точку или с помощью левого соединения. Данные методы не универсальны, так как уровень вложенности фиксирован в запросе. Такой метод подходит, когда заранее известно количество уровней иерархического справочника. Функция на вход принимает ссылку на элемент иерархического справочника, а возвращает ссылку на группу N-уровня.
Функция ПолучитьРодителейЗапросе(СправочникСсылка)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Справочник1.Родитель.Родитель.Родитель КАК Родитель
|ИЗ
| Справочник.Справочник1 КАК Справочник1
|ГДЕ
| Справочник1.Ссылка = &Справочник1Ссылка";
Запрос.УстановитьПараметр("Справочник1Ссылка", СправочникСсылка);
Результат = Запрос.Выполнить();
Если НЕ Результат.Пустой() Тогда
Выборка = Результат.Выбрать();
Выборка.Следующий();
Возврат Выборка.Родитель;
КонецЕсли;
Возврат Справочники.Справочник1.ПустаяСсылка();
КонецФункции
Комментарии (0)
О сайте | Обратная связь | Правила | Новости 1С | Copyright © 2023 Цитирование материалов (тексты, изображения, программный код) допускается только с размещением активной ссылки на сайт 1CLenta.ru |
Что такое родитель в 1с
Родитель – это группа (папка), которой принадлежит элемент.
Основные методы работы с родителем:
Все примеры рассматриваются для справочников, в которых установлен Переключатель «Серии Кодов» — «Во всем справочнике»
Иначе, используемая автором функция Спр.НайтиПоКоду() мягко говоря может дать непредсказуемый результат.
Выбор всех элементов, принадлежащих группе:
//Выбираем элементы, лежащие в группе с кодом Гл005172 Спр = СоздатьОбъект("Справочник.Номенклатура"); Если Спр.НайтиПоКоду("Гл005172") = 1 Тогда Спр.ИспользоватьРодителя(Спр.ТекущийЭлемент()); КонецЕсли; Спр.ВыбратьЭлементы(); Пока Спр.ПолучитьЭлемент() = 1 Цикл Сообщить(Спр.ТекущийЭлемент()); КонецЦикла;
Выбор элементов, непосредственно принадлежащих выбранной группе.
//Выбираем элементы, непосредственно принадлежащих группе с кодом Гл005172 Спр = СоздатьОбъект("Справочник.Номенклатура"); Если Спр.НайтиПоКоду("Гл005172") = 1 Тогда Ур = Спр.ТекущийЭлемент().Уровень() + 1; Спр.ИспользоватьРодителя(Спр.ТекущийЭлемент()); Спр.ВыбратьЭлементы(); Пока Спр.ПолучитьЭлемент() = 1 Цикл Если Спр.ТекущийЭлемент().Уровень() = Ур Тогда Сообщить(Спр.ТекущийЭлемент()); КонецЕсли; КонецЦикла; КонецЕсли;
Здесь проверяется уровень элементов и выбираются только те, чей уровень на 1 больше, чем у выбранной группы. Если нужно выбрать только элементы без групп, тогда нужно добавить проверку на ЭтоГруппа().
А если заюзать чудный метод , то код можно сделать проще:
//Выбираем элементы, непосредственно принадлежащих группе с кодом Гл005172 Спр = СоздатьОбъект("Справочник.Номенклатура"); Если Спр.НайтиПоКоду("Гл005172") = 1 Тогда // Ур = Спр.ТекущийЭлемент().Уровень() + 1; Спр.ИспользоватьРодителя(Спр.ТекущийЭлемент()); Спр.ВключатьПодчиненные(0); // Спр.ВыбратьЭлементы(); Пока Спр.ПолучитьЭлемент() = 1 Цикл // Если Спр.ТекущийЭлемент().Уровень() = Ур Тогда Сообщить(Спр.ТекущийЭлемент()); // КонецЕсли; КонецЦикла; КонецЕсли;
Изменение родителя уже существующего элемента:
//Переносим элемент с кодом Гл000485 в группу с кодом Гл005172 Спр = СоздатьОбъект("Справочник.Номенклатура"); Если Спр.НайтиПоКоду("Гл005172") = 1 Тогда Род = Спр.ТекущийЭлемент(); Если Спр.НайтиПоКоду("Гл000485") = 1 Тогда Спр.Родитель = Род; Спр.Записать(); КонецЕсли; КонецЕсли;
p.s. Обратите внимание на Спр.Записать() – часто забывают это сделать и изменения не принимаются J
p.p.s Обратите внимание на Спр.Родитель = Род. Часто пишут Спр.ТекущийЭлемент().Родитель = Род и получают ошибку о невозможности перепозиционироваться.
Перенос элементов из одной группы в другую:
//Перенос всех элементов из группы с кодом Гл000476 в группу с кодом Гл005172 Спр = СоздатьОбъект("Справочник.Номенклатура"); Справ = СоздатьОбъект("Справочник.Номенклатура"); Если Спр.НайтиПоКоду("Гл005172") = 1 Тогда Род = Спр.ТекущийЭлемент(); Если Спр.НайтиПоКоду("Гл000476") = 1 Тогда Спр.ИспользоватьРодителя(Спр.ТекущийЭлемент()); Пока Спр.ВыбратьЭлементы() = 1 Цикл Спр.ПолучитьЭлемент(); Спр.Родитель = Род; Спр.Записать(); КонецЦикла; КонецЕсли; КонецЕсли;
Перенос из одной группы в другую только элементов, без групп:
//Перенос всех элементов из группы с кодом Гл000476 в группу с кодом Гл005172 Спр = СоздатьОбъект("Справочник.Номенклатура"); Если Спр.НайтиПоКоду("Гл005172") = 1 Тогда Род = Спр.ТекущийЭлемент(); Если Спр.НайтиПоКоду("Гл000476") = 1 Тогда Спр.ИспользоватьРодителя(Спр.ТекущийЭлемент()); nn = 0; Пока nn = 0 Цикл nn = 1; Спр.ВыбратьЭлементы(); Пока Спр.ПолучитьЭлемент() = 1 Цикл Если Спр.ЭтоГруппа() = 0 Тогда Спр.Родитель = Род; Спр.Записать(); nn = 0; КонецЕсли; КонецЦикла; КонецЦикла; КонецЕсли; КонецЕсли;
Сложность двух предыдущих задач состоит в том, что при смене Родителя сбивается выборка, и ее надо делать заново.
Ну а чтобы не сбивалась выборка есть несколько способов:
-получение этой выборки запросом ;
-получение этой выборки в список значений ;
-неэффективно, но как вариант, перебор всего справочника без учета подчинения с проверкой на принадлежность нужной группе;
Для проверки принадлежности элемента группе следует использовать метод ПринадлежитГруппе().
P.S. Самая распространенная ошибка — сравнение элемента справочника со строкой. Происходит из-за непонимания, что это разные типы данных.
Если ЭлементСправочника cb">Капуста" Тогда
Если ЭлементСправочника.Наименование cb">Капуста" Тогда
Получить первого родителя справочника
Не устроил ответ?
Зарегистрируйся и задай свой вопрос. Живое общение приносит результат намного быстрее.
Реклама
Новые вакансии
- Вакансия «Прораммист/разработчи 1С» Екатеринбург от Денис Спеиалист
22 ноября 2023 г. - Вакансия Стажер Аналитик от Elizavetashkr
17 ноября 2023 г. - Вакансия Стажер Программист 1С от Elizavetashkr
17 ноября 2023 г.