Как настроить иерархию справочников и использовать её в документах и отчётах
Содержание
Иерархию в 1С включают в конфигураторе: в свойствах справочника на закладке Данные ставят флажок Иерархический справочник и выбирают вид иерархии. После этого в режиме «1С:Предприятие» в справочнике появляются группы, а у каждого элемента — реквизит Родитель, который и задаёт структуру дерева. Документы собственной иерархии не имеют: они ссылаются на иерархические справочники (номенклатуру, подразделения, статьи затрат), а отчёты строят по этим ссылкам группировки с подытогами по уровням.
Разберём, чем отличаются два вида иерархии, как правильно создать структуру справочников, как она ведёт себя в документах и запросах, и что учесть на больших классификаторах, где от выбранной схемы напрямую зависит скорость работы.
Два вида иерархии: группы и элементы или только элементы
1С предлагает ровно два варианта, и выбирают их один раз при проектировании справочника:
- Иерархия групп и элементов. Дерево строят из групп (папок), а элементы лежат внутри них как «листья». Элемент не может быть родителем другого элемента — родителем бывает только группа. У каждого объекта есть признак
ЭтоГруппа. Так устроена, например,Номенклатура: папки «Материалы», «Товары», «Услуги», а внутри — конкретные позиции. - Иерархия элементов. Группы отсутствуют, родителем выступает обычный элемент. Такую схему применяют к классификаторам, где сам элемент является и узлом, и значением:
Подразделения(отдел входит в департамент),СтатьиЗатрат, виды контактной информации, регионы.
Как выбрать — зависит от того, нужны ли вам «пустые папки» для группировки или сами значения образуют дерево:
ЭтоГруппа в запросах и формах.ЭтоГруппа нет, родителем может стать любой элемент.Вид иерархии задаётся при проектировании. Сменить «иерархию элементов» на «группы и элементы» на заполненной базе без потери или ручного переноса данных не получится — выбирайте осознанно.
Как включить иерархию справочника в конфигураторе
Настройка целиком живёт в конфигураторе, в свойствах объекта. Порядок такой:
- Откройте конфигуратор (
Конфигуратор), найдите нужный справочник в дереве метаданных. - В палитре свойств перейдите на закладку
Данные. - Установите флажок
Иерархический. Появится полеВид иерархии— выберитеИерархия групп и элементовилиИерархия элементов. - При необходимости ограничьте глубину: свойство
Количество уровней иерархии. Значение0означает «без ограничений». - Флажок
Размещать группы сверхууправляет только отображением в списках — группы показываются над элементами. - Обновите конфигурацию базы данных (
F7).
После обновления платформа сама добавляет стандартные реквизиты: Родитель (ссылка на этот же справочник) и — только для иерархии групп и элементов — ЭтоГруппа. Отдельно создавать их не нужно, индекс по Родитель платформа тоже поддерживает автоматически.
Уже заполненный справочник тоже можно сделать иерархическим. Существующие элементы окажутся в корне дерева, а дальше их переносят в группы вручную или обработкой (об этом ниже).
Работа с группами в режиме «1С:Предприятие»
В пользовательском режиме дерево строится прямо в списке справочника:
- Создать группу
— команда
Создать группув командной панели списка (отдельная от обычногоСоздать). Группа доступна только для иерархии групп и элементов. - Поместить элемент в группу — при создании укажите значение в поле
Группа(илиРодитель), либо перетащите запись мышью в нужную папку в дереве слева. - Перенести ветку — выделите элементы и воспользуйтесь командой перемещения в группу из командной панели списка; можно перетаскиванием.
- Переключить отображение — иконка режима просмотра позволяет показать список деревом, только текущей группой или сплошным списком без учёта групп.
Для иерархии элементов папок нет: подчинённость задаётся полем Родитель в самой карточке. Например, в карточке подразделения указываете вышестоящее подразделение — так собирается оргструктура.
Если в списке не видно вложенности, проверьте режим просмотра и снимите активные отборы: отбор по реквизиту может «разворачивать» дерево в плоский список, и структура визуально пропадает.
Иерархия в документах, запросах и отчётах
Сами документы в 1С не бывают иерархическими — у них нет групп и реквизита Родитель. Иерархия приходит в документы через ссылки на справочники. В строке табличной части документа вы выбираете номенклатуру из дерева, а структура берётся из справочника.
Это видно в подборе: когда в документе поступления или реализации нажимаете Подбор, открывается тот же справочник деревом — вы сворачиваете и разворачиваете папки, а в документ попадают только конечные элементы. На форме списка самого справочника дерево включает свойство динамического списка Режим просмотра; отдельного кода для этого не нужно, достаточно, чтобы основной таблицей списка был иерархический справочник.
В запросах за отбор по дереву отвечает оператор В ИЕРАРХИИ. Он возвращает элемент и всех его потомков на любую глубину:
ВЫБРАТЬ
Продажи.Номенклатура,
СУММА(Продажи.Сумма) КАК Сумма
ИЗ
РегистрНакопления.Продажи КАК Продажи
ГДЕ
Продажи.Номенклатура В ИЕРАРХИИ(&Группа)
СГРУППИРОВАТЬ ПО
Продажи.Номенклатура
Здесь &Группа — ссылка на папку: в результат попадут продажи по всем товарам внутри неё и во вложенных папках. Обычное условие = &Группа так не работает
— оно сравнит с конкретным значением и вложенность проигнорирует.
В отчётах на СКД иерархию дают два механизма:
- тип группировки
ИерархияилиТолько иерархияв настройках структуры отчёта — строки сворачиваются в дерево с подытогами по каждому уровню; - в запросе набора данных —
ИТОГИ ... ПО ... ТОЛЬКО ИЕРАРХИЯ, если отчёт строится без системы компоновки.
Благодаря этому в отчёте «Продажи по номенклатуре» сумма по папке «Товары» автоматически собирает все подчинённые позиции, а пользователь разворачивает нужную ветку.
Права доступа и производительность больших классификаторов
На объёмных справочниках (десятки тысяч позиций, номенклатура, адресный классификатор ) структура влияет и на права, и на скорость.
Права доступа
. Через RLS (ограничение доступа на уровне записей) можно выдавать доступ к ветке справочника. Условие в шаблоне строят с тем же оператором В ИЕРАРХИИ: сотруднику видна только его группа номенклатуры со всеми вложениями. Схема рабочая, но помните — RLS с иерархией добавляет подзапрос к каждому обращению, и на больших данных это ощутимо нагружает СУБД.
Производительность. Несколько практичных правил:
| Ситуация | Что делать |
|---|---|
| Глубина дерева «на всякий случай» | Ограничьте Количество уровней: контроль целостности дешевле неконтролируемой вложенности |
| Отбор по ветке в динамическом списке | Используйте В ИЕРАРХИИ, а не выборку всех родителей в цикле |
| Частые отчёты по группам | Группировку Иерархия стройте на регистрах, а не на обходе справочника кодом |
| Справочник реально плоский | Не включайте иерархию — лишний реквизит Родитель и индекс не нужны |
Если по справочнику регулярно крутятся тяжёлые отчёты с группировкой по дереву, надёжнее опираться не на обход справочника в коде, а на итоги регистров: в регистрах уже лежат готовые ссылки на номенклатуру, и запрос с В ИЕРАРХИИ по регистру работает на порядок быстрее рекурсивного прохода по справочнику. Плоский справочник с отбором по дополнительному реквизиту-категории иногда оказывается быстрее глубокого дерева — ветка сравнения = &Категория проще для СУБД, чем раскрытие иерархии.
Массовое изменение Родитель у тысяч элементов (реструктуризация классификатора) — тяжёлая операция. Запускайте её в нерабочее время: пока идёт перенос, пользователи будут видеть «переезжающие» между папками позиции, а обмен данными — ловить конфликты.
Программная работа с иерархией
Когда структуру нужно строить или перестраивать кодом — например, при загрузке классификатора из файла, — пригодятся несколько приёмов.
Определить родителя и признак группы:
Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
Если Выборка.ЭтоГруппа Тогда
Сообщить("Группа: " + Выборка.Наименование);
Иначе
Сообщить("Элемент в папке: " + Выборка.Родитель.Наименование);
КонецЦикла;
КонецЦикла;
Создать группу программно (для иерархии групп и элементов):
НоваяГруппа = Справочники.Номенклатура.СоздатьГруппу();
НоваяГруппа.Наименование = "Канцтовары";
НоваяГруппа.Записать();
У обычного элемента родителя назначают через реквизит Родитель: присваиваете ему ссылку на группу и записываете элемент.
Перенести ветку в другую папку кодом — тот же приём: получаете объект, меняете Родитель, записываете. Чтобы перенести сразу содержимое группы, сначала запросом выбирают её элементы (В ИЕРАРХИИ), затем в цикле у каждого меняют родителя:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура
|ГДЕ Ссылка В ИЕРАРХИИ(&Старая) И Ссылка <> &Старая";
Запрос.УстановитьПараметр("Старая", СтараяГруппа);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Объект = Выборка.Ссылка.ПолучитьОбъект();
Объект.Родитель = НоваяГруппа;
Объект.Записать();
КонецЦикла;
Обойти всех потомков на любую глубину удобнее запросом с В ИЕРАРХИИ, а не рекурсией по Выбрать(Родитель) — запрос делает это одним обращением к базе и работает заметно быстрее рекурсивного обхода справочника.
Для динамических списков на форме иерархию включает свойство списка Режим просмотра (дерево/список) — отдельного кода это не требует, достаточно, чтобы основная таблица списка была иерархическим справочником.
Частые ошибки при работе с иерархией
🔸 Сравнивают с группой через = вместо В ИЕРАРХИИ. Отбор Номенклатура = &Папка вернёт пусто или только саму папку. Потомков даёт только В ИЕРАРХИИ.
🔸 Забывают про ЭтоГруппа в запросах и формах. Если нужны только конечные элементы (товары без папок), добавляйте условие ЭтоГруппа = ЛОЖЬ, иначе в список или подбор попадут и папки.
🔸 Пытаются сделать родителем элемент в иерархии групп и элементов. В этой схеме родитель — только группа. Если такое всё же нужно, вид иерархии изначально должен быть «иерархия элементов».
🔸 Делают слишком глубокое дерево. Пять-шесть уровней вложенности усложняют и ввод, и отчёты. Чаще удобнее два-три уровня плюс отбор по дополнительному реквизиту.
🔸 Включают иерархию «на будущее» на плоском справочнике. Лишний реквизит Родитель, дерево в формах и индекс ничего не дают, если вложенности нет, — только усложняют интерфейс.
🔸 Ищут элемент в дереве перебором вместо запроса. Чтобы найти позицию по коду или наименованию, используйте НайтиПоКоду / НайтиПоНаименованию или запрос, а не рекурсивный обход всех групп: платформа ищет по индексу, обход — вручную и медленно.
Частые вопросы
Можно ли сделать иерархическим документ, а не справочник?
Чем группа отличается от обычного элемента?
ЭтоГруппа = Истина. В неё вкладывают другие группы и элементы, но сама по себе она обычно не несёт «данных» позиции. Элемент — конечная запись, родителем других элементов быть не может.Как перенести элемент в другую папку?
Родитель ссылку на нужную группу и записать объект.Почему отбор по группе не показывает вложенные позиции?
= вместо оператора В ИЕРАРХИИ. Первый сравнивает с одним значением, второй разворачивает всю ветку с потомками.Можно ли ограничить число уровней вложенности?
Количество уровней иерархии в конфигураторе. Ноль — без ограничений; любое положительное число запретит создавать группы глубже заданного уровня.Как выдать сотруднику доступ только к своей ветке справочника?
В ИЕРАРХИИ от разрешённой группы, тогда пользователю видна она и всё вложенное. На больших справочниках такое ограничение заметно нагружает базу — проверяйте скорость на реальных объёмах.