Работа с иерархическими детальными записями
Система компоновки данных позволяет выводить в отчет иерархические детальные записи. В данной статье описываются особенности работы с данным механизмом.
При выводе в результат детальных записей система анализирует наличие у выводимого набора данных связи к самому себе. В случае если такая связь обнаружена, система рекурсивно выполняет связь для получения вложенных записей.
Рассмотрим пример. В примере будем выдавать в отчет иерархический справочник номенклатуры.
Запрос набора данных для получения номенклатуры будет выглядеть так:
ВЫБРАТЬ Номенклатура.Ссылка, Номенклатура.Родитель, Номенклатура.Код, Номенклатура.Наименование, Номенклатура.ЭтоГруппаИЗ Справочник.Номенклатура КАК НоменклатураГДЕ Номенклатура.Родитель В(&Родители)
При помощи данного запроса будут получаться записи с указанным родителем. Если параметр Родитель будет содержать пустую ссылку, то будут получены записи, у которых родителей нет, т.е. корневые записи.
Набор данных с указанным запросом назовем Номенклатура.
Для обеспечения вывода иерархии опишем связь набора данных Номенклатура к самому себе.
В качестве выражения — источника будем использовать значение поля Ссылка.
В качестве выражения — приемника буем использовать значение поля Родитель.
Таким образом, для каждой записи набора данных в наборе данных будут искаться записи, у которых поле Родитель имеет значение поля Ссылка родительской записи.
Т.к. запрос получает данные с фильтрацией по родителю, в связи укажем параметр связи «Родитель». Таким образом, при получении дочерних записей система будет передавать значения поля Ссылка дочернему запросу через этот параметр. Т.к. параметр Родитель используется в конструкции языка запроса В, то в качестве значения параметра система может передавать не одно, а сразу несколько значений. Чтобы система это делала, укажем в связи признак «Список параметров».
Справочник Номенклатура имеет иерархию групп и элементов. При этом дочерние записи могут существовать только у групп. Поэтому, для того, чтобы система не осуществляла поиск дочерних записей не у групповых записей, укажем в связи условие связи: «ЭтоГруппа». Таким образом, система будет выполнять запросы для получения дочерних записей только для тех записей, у которых значение поля ЭтоГруппа имеет значение Истина, т.е. только для групп.
Последнее, что нам нужно сделать, это указать, с какого значения система должна начинать получать иерархические записи. Делается это при помощи свойства связи «Начальное значение связи». Нам нужно, чтобы на первом уровне отчета выдавались записи, у которых родитель отсутствует. Поэтому в качестве начального значения связи укажем выражение «Значение(Справочник.Номенклатура.ПустаяСсылка)» (без кавычек). Таким образом, при первом получении данных из набора данных система будет получать записи, у которых значение поля Родитель равно пустой ссылке, т.е. корневые записи.
На следующем рисунке показана полностью заполненная связь в конструкторе схемы:
Для вывода в результат такого набора данных достаточно вывести в результат детальные записи с нужными полями.
Для этого добавим в настройки детальные записи (группировку без полей группировки) и выберем поля, которые мы хотели бы видеть в результате:
Результат такого отчета будет выглядеть следующим образом:
Код | Наименование |
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с
Родитель – это группа (папка), которой принадлежит элемент.
Основные методы работы с родителем:
Все примеры рассматриваются для справочников, в которых установлен Переключатель «Серии Кодов» — «Во всем справочнике»
Иначе, используемая автором функция Спр.НайтиПоКоду() мягко говоря может дать непредсказуемый результат.
Выбор всех элементов, принадлежащих группе:
//Выбираем элементы, лежащие в группе с кодом Гл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С
Очень часто в 1С 8.3. в справочнике необходимо настроить определенный порядок подчинения элементов. Для реализации подобных задач из простого справочника необходимо сделать иерархический справочник 1С.
В платформе 1С существует два вида иерархии – иерархия групп и элементов и иерархия элементов.
Иерархия групп и элементов
Для того, чтобы справочник имел иерархию групп и элементов, необходимо в редакторе справочника на закладке Иерархия установить флаг Иерархический справочник, а свойству Вид иерархии установить значение Иерархия групп и элементов.
Тогда у справочника можно будет создавать группы, и размещать элементы в группах.
При иерархии групп или элементов существуют группы (каталоги), в которые входят или другие группы, или элементы. И группы, и элементы являются экземплярами объекта справочника.
Группа это тоже экземпляр объекта справочника, по которому не ведется какой-либо учёт (как правило), и который может быть родителем другого экземпляра, т.е. в группу могут входить другие группы и элементы справочников.
Иерархия элементов
Иерархия элементов настраивается похожим способом: в редакторе справочника на закладке Иерархия устанавливается флаг Иерархический справочник, но свойству Вид иерархии следует установить значение Иерархия элементов.
После этого, каждый элемент может быть родителем другого элемента.
Родитель иерархического справочника 1С
У каждого элемента иерархического справочника должен быть родитель. В случае иерархии групп и элементов родитель это группа иерархического справочника, в случае иерархии элементов, родитель это элемент.
Родитель это стандартный реквизит справочника. Если иерархия отключена, то этот стандартный реквизит не доступен. Как у этого справочника Сотрудники.
А если иерархия включена, то этот реквизит доступен. Как у справочника Контрагенты.
Если форма элемента справочника автоматически генерируется платформой (т.е. она не создана), то этот реквизит отображается на управляемой форме. И, в случае иерархии групп и элементов в нем указана группа, в которую входит этот элемент.
Если группа не указана, то значит элемент верхнего уровня.
Также, родитель имеется у элементов справочника с иерархией элементов.
Создать элемент иерархического справочника 1С
Для того, чтобы создать группу справочника (в случае, иерархии групп и элементов), необходимо воспользоваться методом менеджера справочника СоздатьГруппу(). А для создания элемента следует воспользоваться методом СоздатьЭлемент(). Если мы хотим, чтобы вновь созданный элемент входил в какую-то группу, то следует в свойство Родитель этого элемента записать ссылку на нужную группу.
В коде ниже, создаем группу, а потом создаем элемент, который входит в эту группу:
НоваяГруппа = Справочники.Контрагенты.СоздатьГруппу(); НоваяГруппа.Наименование = "Магазины"; НоваяГруппа.Записать(); НовыйЭлемент = Справочники.Контрагенты.СоздатьЭлемент(); НовыйЭлемент.Наименование = "Бакалейный"; НовыйЭлемент.Родитель = НоваяГруппа.Ссылка; НовыйЭлемент.Записать();
Заметьте, группа в коде выше, группа верхнего уровня. У неё при создании не был задан Родитель.
В случае иерархии элементов всегда нужно создавать элементы, но также следует в свойстве Родитель созданного элемента указать ссылку на другой элемент, которому будет подчинен созданный.
РегионЗК = Справочники.Регионы.СоздатьЭлемент(); РегионЗК.Наименование = "Забайкальский край"; РегионЗК.Записать(); РегионЧО = Справочники.Регионы.СоздатьЭлемент(); РегионЧО.Наименование = "Читинская область"; РегионЧО.Родитель = РегионЗК.Ссылка; РегионЧО.Записать();
Изменить элемент иерархического справочника 1С
Если мы хотим поменять подчиненность элемента иерархического справочника, или вообще убрать её, т.е. сделать из элемента элемент верхнего уровня, то следует работать со стандартным реквизитом Родитель. В случае, изменения подчиненности, этому реквизиту нужно присвоить ссылку на другую группу.
ОбъектКонтрагент = Элемент.ПолучитьОбъект(); ОбъектКонтрагент.Родитель = Группа; ОбъектКонтрагент.Записать();
Если же мы хотим сделать элемент верхнего уровня, то этому реквизиту нужно присвоить пустую ссылку.
ОбъектКонтрагент = Элемент.ПолучитьОбъект(); ОбъектКонтрагент.Родитель = Справочники.Контрагенты.ПустаяСсылка(); ОбъектКонтрагент.Записать();
Поиск в иерархическом справочнике 1С
В платформе 1С имеется возможность искать в определенной группе иерархического справочника, для этого следует в методах НайтиПоНаименованию, НайтиПоКоду и НайтиПоРеквизиту заполнять параметр Родитель.
Например, поиск в определенной группе будет осуществляться так:
ЭлементНайденый = Справочники.Контрагенты.НайтиПоНаименованию(НазваниеКонтрагента,Истина,Группа); Если ЭлементНайденый.Пустая() Тогда Сообщить("Нет такого элемента"); Возврат КонецЕсли;
Где, третий параметр Группа — это ссылка на группу, внутри которой ищется элемент по указанному названию.
Выборка иерархического справочника 1С
В платформе 1С 8.3. существует возможность выбрать элементы иерархического справочника, которые входят в ту или иную группу, для этого следует воспользоваться методом Выбрать с заполненным параметром Родитель. В этом случае будут выбраны группы и элементы, которых входят непосредственно в указанную группу, но не будут выбраны группы элементы, которые входят в подчиненные группы. Чтобы выбрать элемент и группы, входящие в какую-то группу, следует воспользоваться методом ВыбратьИерархически.
Например, при таком коде:
Выборка = Справочники.Контрагенты.Выбрать(Группа); Пока Выборка.Следующий() Цикл Если Выборка.ЭтоГруппа Тогда Продолжить; КонецЕсли; Сообщить(Выборка.Наименование); КонецЦикла;
Будут выбраны элементы, входящие в указанную группу.
А в этом случае:
Выборка = Справочники.Контрагенты.ВыбратьИерархически(Группа); Пока Выборка.Следующий() Цикл Если Выборка.ЭтоГруппа Тогда Продолжить; КонецЕсли; Сообщить(Выборка.Наименование); КонецЦикла;
Будут выбраны элементы, которые входят и в указанную группу, и в подчиненные ей группы.
И Выбрать, и ВыбратьИерархически отбирают и группы, и элементы справочников. Поэтому, в коде выше было использовано свойство ссылки справочника ЭтоГруппа. Это свойство имеет значение Истина, если ссылка является группой справочника.
Читайте также по теме:
Более подробно и основательно начальные вопросы программирования в 1С есть вы можете изучить в
Книга «Программировать в 1С за 11 шагов»
Изучайте программирование в 1С в месте с моей книгой «Программировать в 1С за 11 шагов»
Книга написана понятным и простым языком — для новичка.
- Книга посылается на электронную почту в формате PDF. Можно открыть на любом устройстве!
- Научитесь понимать архитектуру 1С;
- Станете писать код на языке 1С;
- Освоите основные приемы программирования;
- Закрепите полученные знания при помощи задачника
О том как разрабатывать под управляемым приложением 1С, читайте в книге Книга «Основы разработки в 1С: Такси»
Отличное пособие по разработке в управляемом приложении 1С, как для начинающих разработчиков, так и для опытных программистов.
- Очень доступный и понятный язык изложения
- Книга посылается на электронную почту в формате PDF. Можно открыть на любом устройстве!
- Поймете идеологию управляемого приложения 1С
- Узнаете, как разрабатывать управляемое приложение;
- Научитесь разрабатывать управляемые формы 1С;
- Сможете работать с основными и нужными элементами управляемых форм
- Программирование под управляемым приложением станет понятным
Промо-код на скидку в 15% — 48PVXHeYu
Эти книги, плюс книга по программированию оперативного учета имеются в едином комплекте: комплект книг по разработке в 1С.
Только для читателей моего блога,
промо-код на скидку в 300 рублей на весь комплект: blog
Если Вам понравился этот урок, был полезен или помог решить какую-нибудь проблему, то Вы можете поддержать мой проект, перечислив любую сумму.
можно оплатить вручную:
И вступайте в мои группы:
One Reply to “Иерархический справочник 1С”
Стас Антонов :
1. Создать справочник Жанры, справочник ТВКаналы с реквизитами номер, название канала(изменить стандартный код и наименование с помощью синонима) и Характер канала, с типом справочник ссылка жанры, подчиненный ему справочник Программы , с типом время начала и время окончания. Сделать все реквизиты обязательными для заполнения.
2. Создать форму элемента для справочника Сотрудники с реквизитами: фамилия, имя, отчество с типом строка; Должность (тип справочник ссылка должность); группу основные сведения, в ней пол (перечисления. пол), дата рождения (дата.дата), семейное положение (перечисление или справочник . семейное положение), количество детей (число, неотрицательное, точность 0); группу место проживание, в ней город и адрес (строка); группа Сведения об образованиях , в ней образование (справочник или перечисление образование), место учебы (строка); привести форму к следующему виду, картинка может быть любая, но она должна быть отображена полностью и не растягивать форму.
Получение всех родителей элемента справочника
В языке запросов не предусмотрено специальных средств для получения всех родителей элемента. Для выполнения задачи можно воспользоваться иерархическими итогами, однако получение иерархических итогов оптимизировано для построения итогов большого количества записей, и не вполне эффективно для получения родителей одного элемента. Для более эффективного получения всех родительских записей элемента, рекомендуется перебирать в цикле его родителей небольшими порциями. Пример:
Код 1C v 8.х
ТекущийЭлементНоменклатуры = ЭлементНоменклатура;
Запрос = Новый Запрос("ВЫБРАТЬ
| Номенклатура.Родитель,
| Номенклатура.Родитель.Родитель,
| Номенклатура.Родитель.Родитель.Родитель,
| Номенклатура.Родитель.Родитель.Родитель.Родитель,
| Номенклатура.Родитель.Родитель.Родитель.Родитель.Родитель
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|
|ГДЕ
| Номенклатура.Ссылка = &ТекущийЭлементНоменклатуры";
Пока Истина Цикл
Запрос.УстановитьПараметр("ТекущийЭлементНоменклатуры", ТекущийЭлементНоменклатуры);
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Прервать;
КонецЕсли;
Выборка = Результат.Выбрать();
Выборка.Следующий();
Для НомерКолонки = 0 По Результат.Колонки.Количество() - 1 Цикл
ТекущийЭлементНоменклатуры = Выборка[НомерКолонки];
Если ТекущийЭлементНоменклатуры = Справочники.Номенклатура.ПустаяСсылка() Тогда
Прервать;
Иначе
Сообщить(ТекущийЭлементНоменклатуры);
КонецЕсли;
КонецЦикла;
Если ТекущийЭлементНоменклатуры = Справочники.Номенклатура.ПустаяСсылка() Тогда
Прервать;
КонецЕсли;
КонецЦикла;
В данном примере в окно служебных сообщений выводятся все родители для ссылки, записанной в переменную ЭлементНоменклатура. В цикле выбирается по 5 родителей ссылки.
Если число уровней в справочнике ограничено и невелико, то возможно получение всех родителей одним запросом без цикла.