Как найти иерархию в 1с

Очень часто в 1С 8.3. в справочнике необходимо настроить определенный порядок подчинения элементов. Для реализации подобных задач из простого справочника необходимо сделать иерархический справочник 1С.

В платформе 1С существует два вида иерархии – иерархия групп и элементов и иерархия элементов.

Иерархия групп и элементов

Для того, чтобы справочник имел иерархию групп и элементов, необходимо в редакторе справочника на закладке Иерархия установить флаг Иерархический справочник, а свойству Вид  иерархии установить значение Иерархия групп и элементов.

Иерархический справочник 1С

Тогда у справочника можно будет создавать группы, и размещать элементы в группах.

Иерархический справочник 1С

При иерархии групп или элементов существуют группы (каталоги), в которые входят или другие группы, или элементы. И группы, и элементы являются экземплярами объекта справочника.

Группа это тоже экземпляр объекта справочника, по которому не ведется какой-либо учёт (как правило), и который может быть родителем другого экземпляра, т.е. в группу могут входить другие  группы и элементы справочников.

Иерархия  элементов

Иерархия элементов настраивается похожим способом: в редакторе справочника на закладке Иерархия  устанавливается флаг Иерархический справочник, но свойству Вид  иерархии следует установить значение Иерархия элементов.

Иерархический справочник 1С

После этого, каждый элемент может быть родителем другого элемента.

Иерархический справочник 1С

Родитель иерархического справочника 1С

У каждого элемента иерархического справочника должен быть родитель. В случае иерархии групп и элементов родитель это группа иерархического справочника, в случае иерархии элементов, родитель это элемент.

Родитель это стандартный реквизит справочника.  Если иерархия отключена, то этот стандартный реквизит не доступен. Как у этого справочника Сотрудники.

Родитель иерархического справочника 1С

А если иерархия включена, то этот реквизит доступен. Как у справочника Контрагенты.

Родитель иерархического справочника 1С

Если форма элемента справочника автоматически генерируется платформой (т.е. она не создана), то этот реквизит отображается на управляемой форме. И, в случае иерархии групп и элементов в нем указана группа, в которую входит этот элемент.

Родитель иерархического справочника 1С

Если группа не указана, то значит элемент верхнего уровня.

Родитель иерархического справочника 1С

Также, родитель имеется у элементов справочника с иерархией элементов.

Родитель иерархического справочника 1С

Создать элемент иерархического справочника 1С

Для того, чтобы создать группу справочника (в случае, иерархии групп и элементов), необходимо воспользоваться методом менеджера справочника СоздатьГруппу(). А для создания элемента следует воспользоваться методом СоздатьЭлемент(). Если мы хотим, чтобы вновь созданный элемент входил в какую-то группу, то следует в свойство Родитель этого элемента записать ссылку на нужную группу.

В коде ниже, создаем группу, а потом создаем элемент, который входит в эту группу:

НоваяГруппа = Справочники.Контрагенты.СоздатьГруппу();
НоваяГруппа.Наименование = "Магазины";
НоваяГруппа.Записать();

НовыйЭлемент = Справочники.Контрагенты.СоздатьЭлемент();
НовыйЭлемент.Наименование = "Бакалейный";
НовыйЭлемент.Родитель = НоваяГруппа.Ссылка;
НовыйЭлемент.Записать();

Заметьте, группа в коде выше, группа верхнего уровня. У неё при создании не был задан Родитель.

В случае иерархии элементов  всегда нужно создавать элементы, но также следует в свойстве Родитель созданного элемента указать ссылку на другой элемент, которому будет подчинен созданный.

РегионЗК = Справочники.Регионы.СоздатьЭлемент();
РегионЗК.Наименование = "Забайкальский край";
РегионЗК.Записать();

РегионЧО = Справочники.Регионы.СоздатьЭлемент();
РегионЧО.Наименование = "Читинская область";
РегионЧО.Родитель = РегионЗК.Ссылка;
РегионЧО.Записать();

Изменить элемент иерархического справочника 1С

Если мы хотим поменять подчиненность элемента иерархического справочника, или вообще убрать её, т.е. сделать из элемента элемент верхнего уровня, то следует работать со стандартным реквизитом Родитель. В случае, изменения подчиненности, этому реквизиту нужно присвоить ссылку на другую группу.

ОбъектКонтрагент = Элемент.ПолучитьОбъект();
ОбъектКонтрагент.Родитель = Группа;
ОбъектКонтрагент.Записать();

Если же мы хотим сделать элемент верхнего уровня, то этому реквизиту нужно присвоить пустую ссылку.

ОбъектКонтрагент = Элемент.ПолучитьОбъект();
ОбъектКонтрагент.Родитель = Справочники.Контрагенты.ПустаяСсылка();
ОбъектКонтрагент.Записать();

Поиск в иерархическом справочнике 1С

В платформе 1С имеется возможность искать в определенной группе иерархического справочника, для этого следует в методах НайтиПоНаименованию, НайтиПоКоду  и НайтиПоРеквизиту заполнять параметр Родитель.

Например, поиск в определенной группе будет осуществляться так:

ЭлементНайденый = Справочники.Контрагенты.НайтиПоНаименованию(НазваниеКонтрагента,Истина,Группа);

Если ЭлементНайденый.Пустая() Тогда 
	Сообщить("Нет такого элемента");
	Возврат
КонецЕсли;

Где, третий параметр Группа — это ссылка на группу, внутри которой ищется элемент по указанному названию.

Выборка иерархического справочника 1С

В платформе 1С 8.3. существует возможность выбрать элементы иерархического справочника, которые входят в ту или иную группу, для этого следует воспользоваться методом Выбрать с заполненным параметром Родитель. В этом случае будут выбраны группы и элементы, которых входят непосредственно в указанную группу, но не будут выбраны группы элементы, которые входят в подчиненные группы. Чтобы выбрать элемент и группы, входящие в какую-то группу, следует воспользоваться методом ВыбратьИерархически.

Например, при таком коде:

Выборка = Справочники.Контрагенты.Выбрать(Группа);
Пока Выборка.Следующий() Цикл 
	
	Если Выборка.ЭтоГруппа Тогда 
		Продолжить;
	КонецЕсли;	
	
	Сообщить(Выборка.Наименование);
КонецЦикла;

Будут выбраны элементы, входящие в указанную группу.

А в этом случае:

Выборка = Справочники.Контрагенты.ВыбратьИерархически(Группа);
Пока Выборка.Следующий() Цикл 
	
	Если Выборка.ЭтоГруппа Тогда 
		Продолжить;
	КонецЕсли;	
	
	Сообщить(Выборка.Наименование);
КонецЦикла;	

Будут выбраны элементы, которые входят и в указанную группу, и в подчиненные ей группы.

И Выбрать, и ВыбратьИерархически отбирают и группы, и элементы справочников. Поэтому, в коде выше было использовано свойство ссылки справочника ЭтоГруппа. Это свойство имеет значение Истина, если ссылка является группой справочника. 

Видео по теме:

Читайте также по теме:

Объект в 1С

Ссылка в 1С

Метаданные 1С

Документы в 1С

Более подробно и основательно начальные вопросы программирования в 1С есть вы можете изучить в
Книга «Программировать в 1С за 11 шагов»

Изучайте программирование в 1С в месте с моей книгой «Программировать в 1С за 11 шагов»

Программировать в 1С за 11 шагов

Книга написана понятным и простым языком — для новичка.

  1. Книга посылается на электронную почту в формате PDF. Можно открыть на любом устройстве!
  2. Научитесь понимать архитектуру 1С;
  3. Станете писать код на языке 1С;
  4. Освоите основные приемы программирования;
  5. Закрепите полученные знания при помощи задачника

О том как разрабатывать под управляемым приложением 1С, читайте в книге Книга «Основы разработки в 1С: Такси»

Отличное пособие по разработке в управляемом приложении 1С, как для начинающих разработчиков, так и для опытных программистов.

Основы разработки в 1С такси
  1. Очень доступный и понятный язык изложения
  2. Книга посылается на электронную почту в формате PDF. Можно открыть на любом устройстве!
  3. Поймете идеологию управляемого приложения 1С
  4. Узнаете, как разрабатывать управляемое приложение;
  5. Научитесь разрабатывать управляемые формы 1С;
  6. Сможете работать с основными и нужными элементами управляемых форм
  7. Программирование под управляемым приложением станет понятным

Промо-код на скидку в 15% — 48PVXHeYu

Эти книги, плюс книга по программированию оперативного учета имеются в едином комплекте: комплект книг по разработке в 1С.
Только для читателей моего блога,
промо-код на скидку в 300 рублей на весь комплект: blog


Если Вам понравился этот урок, был полезен или помог решить какую-нибудь проблему, то Вы можете поддержать мой проект, перечислив любую сумму
.

можно оплатить вручную:

Яндекс.Деньги — 410012882996301

Подписывайтесь на мой канал в телеграмме: https://t.me/Programming1CNizamutdinov

И вступайте в мои группы:

Вконтакте: https://vk.com/1c_prosto
Фейсбуке: https://www.facebook.com/groups/922972144448119/
ОК: http://ok.ru/group/52970839015518
Твиттер: https://twitter.com/signum2009

Содержание:

1.       Что такое иерархический справочник?

2.       Создание иерархического справочника

3.       Создание элементов Иерархического справочника

4.       Изменение группы элемента Иерархического справочника  

1.    Что такое иерархический справочник?

В данной статье будет рассмотрен иерархический вид справочников 1С, а также определены действия с ним.

Справочник – это объект внутри конфигурации, который позволяет работать со списками данных (например: перечнем товаров, клиентской базой, сотрудниками, поставщиками и так далее). Признаки и уклад у справочников описаны в объектах внутри конфигурации, на их основе получаются таблицы, в которых содержится вся информация. Составляют справочника элементы, которые можно добавлять собственноручно.

Главная отличительная черта иерархического справочника – это наличие структуры иерархии (иерархия – это расположение неких элементов согласно сортировке от главного к второстепенному, по убыванию). Для удобства пользования в этом справочнике будем вводить группировку таким образом: услуги – отдельно, материалы – отдельно. В 1С это называют группами справочника. Иерархические справочники делятся на два подвида: те, у которых иерархия делит на группы и те, у которых иерархия делит на элементы.

Данные справочники в конфигурациях системы 1С:Предприятие могут транслироваться как «Список», «Иерархический список» или «Древо».  

2.    Создание иерархического справочника

В дереве конфигурации выбираем объект метаданных “Справочники”, пусть его названием будет «Номенклатура». Зачастую в типовых конфигурация 1С «Номенклатура» имеет единственное число, как в плане элемента, так и формы списка или выбора. В этом случае «Представление объекта» станет «Синоним», а вместо «Представления списка» будет «Номенклатура».

Войдём во вкладку «Подсистемы».

Согласно закономерности в данной версии платформы 1С:Предприятие список с номенклатурой будет располагаться в разделах «Учёт материалов», «Оказание услуг» и «Бухгалтерия», но следует учесть, что в бухгалтерском анализе потребуется перечень услуг и материалов. Отметим эти подсистемы, как на скриншоте ниже:

Отмечаем подсистемы в своей версии платформы 1С:Предприятие

Рис. 1 Отмечаем подсистемы в своей версии платформы 1С:Предприятие

Далее входим в панель, под названием «Иерархия», и ставим соответствующую «галочку», смотреть ниже:

Отмечаем Иерархический справочник

Рис. 2 Отмечаем Иерархический справочник

Во вкладке «Данные» оставляем стандартные настройки для типа и длины в коде, а длина в наименовании справочника пусть будет равняться 100 знакам. Также меняем «Синоним» в реквизите «Родитель», который был по умолчанию на другое название: кликаем по кнопке «Стандартные реквизиты», далее два раза кликаем по «Родитель», открываем его свойства и ставим «Синоним» в качестве справочника «Группы номенклатуры», как показано на скриншоте ниже:

Выбираем подпункт в системе 1С

Рис. 3 Выбираем справочник «Группы номенклатуры» в качестве Синонима

Далее последует настройка интерфейса в приложении. Для того чтобы стало удобно вывести новые элементы в справочнике, создаём доступ для команд «УчётМатериалов» и «ОказаниеУслуг». Следующим шагом – в древе конфигурации кликаем на «Подсистемы», вызываем их меню и выбираем подпункт «Все подсистемы», как показано на скриншоте:

Выбираем подпункт «Все подсистемы»

Рис. 4 Выбираем подпункт «Все подсистемы» в своей версии платформы 1С:Предприятие

Далее в списке «Подсистемы» маркируем «УчётМатериалов». При этом справа в «Командном интерфейсе» отражаются нужные команды из подсистемы, которую выбрали, включаем внутри группы «Командный интерфейс» отражение для команды «Номенклатура: создать». Наблюдаем, что внутри группы «Панель навигации.Обычное» прибавилась наша команда «Номенклатура» для того, чтобы открывать данный список (будет включена по умолчанию):

Выбираем «Номенклатура: создать» в своей версии платформы 1С:Предприятие

Рис. 5 Выбираем «Номенклатура: создать» в своей версии платформы 1С:Предприятие

Выделяем внутри списка с подсистемами «ОказаниеУслуг» и действуем по аналогии с предыдущим пунктом.

В подсистеме «Бухгалтерия» ничего не добавляем, так как в данном разделе номенклатура пополняться не будет.

Замечание: фрагмент внутри командного интерфейса настроить для нужной подсистемы из списка можно из вкладки для редакции данной подсистемы, кликнув на «Командный интерфейс». А если настройка требуется для командного интерфейса не одной подсистемы, а большего количества, удобно воспользоваться инструментом для редакции «Все подсистемы».

Далее последует заполнение справочника «Номенклатура»: запустим 1С: Предприятие, для отладки обновим конфигурацию, за чем последует появление окна со списком правок внутри структуры конфигурации 1С. Добавляем справочник «Номенклатура» и кликаем кнопку «Принять»:

Список правок внутри структуры конфигурации 1С

Рис. 6 Список правок внутри структуры конфигурации 1С

В новом окне наблюдаем, что в разделах «Учёт материалов», «Оказание услуг» и «Бухгалтерия» создалась новая команда – «Номенклатура», которая служит, чтобы открыть список с номенклатурой, её название – это синоним объекта. Выполним данную команду («Номенклатура») в разделе «Учёт материалов» и перед нами будет форма из списка с номенклатурой.  

3.    Создание элементов Иерархического справочника

Конструируем группы «Материалы» и «Услуги» внутри корня справочника, как показано на скриншоте ниже:

Конструируем группы внутри корня справочника

Рис. 7 Конструируем группы внутри корня справочника

Дадим название группам «Материалы» и «Услуги». Далее двойным кликом откроем «Материалы» и создадим элементы (пример элементов будет представлен на скриншотах ниже). Чтобы добавить элемент в группу справочника (она должна быть открытой), кликаем «Создать», открывается форма:

Добавление элемента в группу справочника

Рис. 8 Добавление элемента в группу справочника

Чтобы создать элемент в справочнике воспользуемся командой «Номенклатура» (один из возможных вариантов), которая есть в таких разделах как «Учёт материалов» и «Оказание услуг». Но в таком варианте элемент не связан со списком номенклатуры (то есть 1С не понимает, в какую из групп определить элемент – нужно прописывать вручную).

Связываем элемент со списком номенклатуры в группе справочников

Рис. 9 Связываем элемент со списком номенклатуры в группе справочников

Чтобы избрать значение для поля справочника «Группа номенклатуры», воспользуемся поиском значения из справочника по строке.

Рассмотрим группу «Услуги», где будет создано также несколько элементов (например, для ремонта телевизоров и ремонта стиральных машин, как на скриншоте ниже):

Элементы группы услуги в 1С:Предприятие

Рис. 10 Элементы группы услуги в 1С:Предприятие  

4.    Изменение группы элемента Иерархического справочника

Создадим две группы по смыслу, чтобы разъединить услуги: открываем «Услуги» и делаем две группы (в нашем примере это «Телевизоры» и «Стиральные машины»):

Создадим группы Иерархического справочника

Рис. 11 Создадим группы Иерархического справочника

Для нахождения услуг в соответствующих группах выполняем команду «Переместить в группу» (в меню «Ещё»):

Команда Переместить в группу

Рис. 12 Команда Переместить в группу

Перемещаем услуги в соответствующие группы. Также создаём группы в материалах.

Рассмотрим создание элементов, которых не хватает, при их выборе в иных полях. Откроем любой элемент из любой группы. Нам необходимо поменять поле справочника «Группа номенклатуры» на «Прочее», но этой группы пока не существует. Кликаем на «Создать» и знак «+» (находится в окне с выбором значений). Перед нами всплывает форма создания группы внутри справочника. Выводим название «Прочее» и кликаем «Записать и закрыть».

список в виде дерева

Рис. 13 Создание элементов Иерархического справочника

Пусть нужно представить наш иерархический список как древо. Для этого в меню «Ещё» ищем кнопку «Режим просмотра», а внутри уже этого раздела кликаем на режим «Древо» – иерархический список с номенклатурой отобразится следующим образом:

Отображение иерархического списка в виде дерева

Рис. 14 Отображение иерархического списка в виде дерева

Специалист компании «Кодерлайн»

Айдар Фархутдинов

Оглавление

  1. Теория графов и 1С
  2. Иерархия 1С и как она устроена изнутри
    1. Справочники с иерархией элементов/групп и элементов
    2. Справочники с владельцами
    3. Иерархия в запросах 1С
  3. Прикладные задачи использования иерархии в 1С
    1. Иерархии нет, а если найду?
    2. Иерархия в отчете приготовления блюд
    3. Если нам нужен иерархический вид, а его нет
    4. Диаграмма структуры организации за 5 минут
    5. Оптимизация «Структурных единиц»
  4. Матрица смежности в древовидных структурах 1С необходима

Теория графов и 1С

Данной статьей мы открываем цикл, посвященный работе с графовыми структурами. Почему мы решили поговорить об этом? Оказывается не все так просто, как может показаться на первый взгляд.

Мы попробуем ответить на вопросы, где платформа заботится о нас и строит иерархию за нас, поэтому мы не нуждаемся в программировании и понимании дискретной математики, где мы должны строить иерархию самостоятельно и насколько далеко распространяется наша самостоятельность.

Только ли флаг иерархии — это та самая иерархия или бывают иные случаи? Что такое иерархия с точки зрения устройства таблиц СУБД? Как платформа пытается заботиться о производительности, когда работает с иерархическими структурами?

Поговорим, конечно, и о приемах визуализации.

Первая статья цикла будет посвящена деревьям в 1С.

Дерево (теория графов) — это связный ациклический граф. Связность означает наличие маршрута между любой парой вершин, ацикличность — отсутствие циклов.

Wikipedia®

Иерархия 1С и как она устроена изнутри

Рассмотрим, как устроены различные механизмы, которые предоставляет платформа 1С для построения иерархии. Это может быть классическая иерархия в справочнике, связь с планом видов характеристик, или же вовсе иерархический вывод данных в отчете.

Справочники с иерархией элементов/групп и элементов

В самом простом случае, если мы хотим настроить порядок подчинения элементов между собой, в платформе 1С существует возможность указания иерархии для справочника. Вид иерархии может быть «Иерархия элементов» и «Иерархия групп и элементов».

Справочники с иерархией элементов/групп и элементов

Для иерархии элементов у справочника появляется стандартный реквизит «Родитель», который содержит ссылку на элемент верхнего уровня иерархии по отношению к текущему. Для элементов верхнего уровня родитель будет не заполнен. Таким образом и определяется подчиненность элементов.

Справочники с иерархией элементов/групп и элементов

Заглянем в описание таблицы на уровне системы управления базами данных. Чтобы найти имя соответствующей таблицы в базе, воспользуемся обработкой «Структура хранения метаданных»:

Справочники с иерархией элементов/групп и элементов

Далее, если мы используем в качестве СУБД MSSQL Server воспользуемся программой Management Studio для просмотра описания таблиц базы данных. Находим описание и видим добавленную колонку «ParentIDRef»:

Справочники с иерархией элементов/групп и элементов

Если говорить о СУБД PostgreSQL, то здесь можно либо воспользоваться программой pgAdmin с графическим интерфейсом:

Справочники с иерархией элементов/групп и элементов

Или же консольной утилитой psql, входящей в состав дистрибутива PostgreSQL. Для этого сначала необходимо подключиться к базе данных по ее имени при помощи опции -d:

Справочники с иерархией элементов/групп и элементов

Затем обратиться к описанию таблицы по имени при помощи специальной команды d:

Справочники с иерархией элементов/групп и элементов

Когда выстраиваем иерархию, задача быстрой работы списков никуда не уходит. Давайте посмотрим на индексы по полю родителя:

  • Индекс, содержащий колонку родителя, а также код, если его длина не равна 0:

Справочники с иерархией элементов/групп и элементов

  • Индекс, содержащий колонку родителя, а также наименование, если его длина не равна 0. Аналогично, для MSSQL и PostgreSQL:

Справочники с иерархией элементов/групп и элементов

  • Индекс, содержащий колонку родителя, а также значение реквизита, для которого включено индексирование. Например, в справочнике «Циклы планирования», используемом в данном примере, проиндексируем поле «Общее количество дней»:

Справочники с иерархией элементов/групп и элементов

После этого, в системе появится дополнительный индекс с полями «ParentIDRef», которое соответствует стандартному реквизиту «Родитель» и «_Fld34748», которое соответствует проиндексированному реквизиту «Общее количество дней»:

Справочники с иерархией элементов/групп и элементов

В случае иерархии групп и элементов дополнительно вводится разделение элементов при помощи реквизита «Это группа», причем родителем в таком случае может быть только группа.

Справочники с иерархией элементов/групп и элементов

В описание таблицы на уровне СУБД добавляется колонка «Folder»:

Справочники с иерархией элементов/групп и элементов

Также, с включенным в свойствах справочника флагом «Размещать группы сверху», который указывает на порядок расположения групп и элементов на одном уровне иерархии, в вышеописанные индексы будет добавлено поле «Folder» сразу после поля «ParentIDRef». Например для индекса по коду это будет выглядеть следующим образом:

Справочники с иерархией элементов/групп и элементов

Стоит отметить, что в MSSQL и PostgreSQL индексы строятся аналогично, пример описания аналогичного индекса в PgAdmin:

Справочники с иерархией элементов/групп и элементов

Для чего же система добавляет все перечисленные индексы? Для ускорения построения иерархии и доступа к свойствам родительских элементов справочника. В этом можно убедиться рассмотрев запросы, которые используются платформой при работе с иерархией, что будет сделано далее.

Также следует задуматься нужна ли вам иерархия групп, а не только элементов. Ведь за это удобство приходится расплачиваться дополнительным полем в таблице и в индексе.

Еще одно обобщение, которое можно сделать, изучая данный раздел, что за каждое действие, которое вы производите на уровне конфигурирования, вам приходится «расплачиваться» чем-то с точки зрения устройства СУБД. Поэтому хорошей рекомендацией будет изучать раздел знаний, называемый «экспертиза производительности», чтобы всегда иметь возможность глубокого понимания последствий ваших действий.

Справочники с владельцами

В том случае, когда необходимо подчинить элементы одного справочника элементам другого справочника, выстроив иерархию, в платформе 1С есть возможность указания владельцев справочника.

Справочники с владельцами

При такой настройке элементы подчиненного справочника всегда должны иметь владельца. Для его указания используется соответствующий стандартный реквизит:

Справочники с владельцами

В описание таблицы на уровне СУБД добавляется колонка «OwnerIDRRef». А для организации иерархии применяется ряд дополнительных индексов, т. к. конкретный элемент подчиненного справочника не используется без указания его владельца. По аналогии с иерархическими справочниками, это индексы содержащие владельца и поля наименование/код, если их длина не равна 0 или любой проиндексированный в конфигураторе реквизит:

Справочники с владельцами

Если же справочник одновременно является и подчиненным и иерархическим, то для всех индексов, содержащих поле «Родитель» в начало также добавляется и поле «Владелец»:

Справочники с владельцами

Из вышеописанного можно сделать вывод, что иерархические и подчиненные справочники содержат большое количество дополнительных индексов и это следует учитывать при проектировании системы. И прежде чем сделать подчиненный справочник иерархическим да еще с подчинением групп и элементов, подумайте, действительно ли вы в этом нуждаетесь.

Иерархия в запросах 1С

Рассмотрим, как система может использовать созданные индексы в иерархических справочниках при выполнении запросов в различных стандартных ситуациях.

В языке запросов 1С существует возможность вывести элементы справочника с итогами по иерархии. Пусть, у нас есть справочник со следующей иерархией групп и элементов:

Иерархия в запросах 1С

Настроим сбор логов технологического журнала событий SDBL и DBMSSQL для того, чтобы отследить, какие запросы выполняются в системе:


<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://v8.1c.ru/v8/tech-log">  
      <log history="2" location="f:chesdmtjlogs">
            <property name="all"/>
            <event>
                  <eq property="name" value="SDBL"/>
                  <eq property="p:processname" value="chesdm_supo"/>
            </event>
            <event>
                  <eq property="name" value="DBMSSQL"/>
                  <eq property="p:processname" value="chesdm_supo"/>
            </event>         
      </log>
</config> 

Выполним запрос, который строит итоги по иерархии вышеописанного справочника без отбора:

ВЫБРАТЬ
      УОП_ЦиклыПланирования.Ссылка КАК Ссылка
ИЗ
      Справочник.УОП_ЦиклыПланирования КАК УОП_ЦиклыПланирования
ИТОГИ ПО
      Ссылка ИЕРАРХИЯ 

По событию DBMSSQL в логах технологического журнала видим, что на уровне СУБД система точно также, как и в языке запросов 1С, выбрала все записи из справочника (за исключением отбора по полю разделителя Fld929), но в выбранных полях к ссылке добавила еще и поле родителя для построения иерархии:

SELECT
        T1._IDRRef,
        T1._ParentIDRRef
FROM dbo._Reference34768 T1
WHERE (T1._Fld929 = ?) 

Попробуем воспользоваться еще одной стандартной функциональностью — запросом с отбором по иерархии:

ВЫБРАТЬ
         УОП_ЦиклыПланирования.Ссылка КАК Ссылка
ИЗ
        Справочник.УОП_ЦиклыПланирования КАК УОП_ЦиклыПланирования
ГДЕ
         УОП_ЦиклыПланирования.Ссылка В ИЕРАРХИИ(&Ссылка) 

Здесь уже имеем гораздо большее количество запросов, т. к. система пытается вычислить массив ссылок, по которым необходимо выполнить отбор в таблице. Сначала создается временная таблица, содержащая колонку со ссылкой, а также кластерный индекс к ней:

CREATE TABLE #tt2 (_REFFIELDRRef BINARY(16))
CREATE UNIQUE CLUSTERED INDEX idx2 ON #tt2 (_REFFIELDRRef) 

Затем в эту временную таблицу добавляются все потомки переданного в качестве параметра элемента справочника (первая часть запроса), а также сам переданный элемент справочника (вторая часть запроса):

INSERT INTO #tt2 WITH(TABLOCK)    (_REFFIELDRRef) SELECT
T1._IDRRef
FROM
dbo._Reference34678 T1
WHERE
((T1._Fld929 = ?)) AND ((T1._ParentIDRRef IN (?)))
UNION SELECT
T2._IDRRef
FROM
dbo._Reference34678 T2
WHERE
((T2._Fld929 = ?)) AND ((T2._IDRRef IN (?)))
p_0: 0N
p_1: 0x810A002590A7FB1511ECA50B450BD2CE
p_2: 0N
p_3: 0x810A002590A7FB1511ECA50B450BD2CE 

Далее к полученной на предыдущем шаге временной таблице добавляются элементы, родителями которых являются элементы, уже присутствующие во временной таблице:

INSERT INTO #tt2 WITH(TABLOCK)    (_REFFIELDRRef) SELECT
T1._IDRRef
FROM
dbo._Reference34678 T1
INNER JOIN #tt2 T2 WITH(NOLOCK)
ON T1._ParentIDRRef = T2._REFFIELDRRef
LEFT OUTER JOIN #tt2 T3 WITH(NOLOCK)
ON T1._IDRRef = T3._REFFIELDRRef
WHERE
((T1._Fld929 = ?)) AND (T3._REFFIELDRRef IS NULL)
p_0: 0N 

Такой запрос будет выполнен столько раз, сколько подчиненных уровней иерархии еще осталось присоединить, после чего во временной таблице #tt2 получим ссылки на все подчиненные группы и элементы для того элемента, который был передан в качестве параметра в исходном запросе 1С.

Далее система выбирает все ссылки из временной таблицы и следующим запросом уже обращается к таблице справочника с отбором по найденным ссылкам:

SELECT
T1._REFFIELDRRef
FROM #tt2 T1 WITH(NOLOCK)

SELECT
T1._IDRRef
FROM dbo._Reference34678 T1
WHERE ((T1._Fld929 = ?)) AND (((T1._IDRRef IN (?, ?, ?, ?, ?, ?))))
p_0: 0N
p_1: 0x810A002590A7FB1511ECA50B450BD2CE
p_2: 0x810A002590A7FB1511ECA50B4F5183F8
p_3: 0x810A002590A7FB1511ECA52A0F5F731D
p_4: 0x810A002590A7FB1511ECAA75D1DEAB1C
p_5: 0x810A002590A7FB1511ECAA75D93F4697
p_6: 0x810A002590A7FB1511ECAA75DFAF00AF 

Группировка полей в схеме компоновки данных

Следующий случай построения иерархии платформой — это группировка полей в схеме компоновки данных. К примеру, если в качестве источника данных укажем вышеописанный иерархический справочник, а в настройках полей группировок укажем необходимость построения иерархии:

Группировка полей в схеме компоновки данных

То система на уровне СУБД выполнит дополнительный запрос, в котором добавится поле родителя:

SELECT
T1._IDRRef,
T1._IDRRef,
T1._Description,
T1._ParentIDRRef,
T1._Description
FROM dbo._Reference34678 T1
WHERE
((T1._Fld929 = ?)) AND ((T1._IDRRef IN (?, ?, ?, ?, ?, ?, ?, ?, ?)))

Отображение динамического списка в виде дерева

Еще один случай построения иерархии — это непосредственное отображение динамического списка в форме списка справочника при условии, что режим отображения такого списка установлен в виде дерева так, как это было показано на рисунке выше.

Настройка такого динамического списка будет выглядеть следующим образом:

Отображение динамического списка в виде дерева

Отображение динамического списка в виде дерева

Сначала выбираются элементы верхнего уровня (у которых ссылка на родителя пустая), причем не все, а только первые N (в нашем случае первые 45), причем количество выбираемых строк вычисляется платформой автоматически:

SELECT TOP 45
T1._IDRRef,
T1._Marked,
T1._ParentIDRRef,
CASE WHEN (T1._Folder = 0x00) THEN 0x01 ELSE 0x00 END,
T1._Code,
T1._Description,
CASE WHEN T1._PredefinedID > 0x00000000000000000000000000000000 THEN 0x01 ELSE 0x00 END
FROM dbo._Reference34678 T1
WHERE
((T1._Fld929 = ?)) AND ((T1._ParentIDRRef = 0x00000000000000000000000000000000))
ORDER BY
CASE WHEN ((T1._Folder = 0x00)) THEN 0x01 ELSE 0x00 END DESC, (T1._Description), (T1._IDRRef)

Затем, при условии, что мы указали необходимость разворачивания дерева динамического списка в его свойствах, для каждого элемента верхнего уровня, который является группой, выбираются его потомки второго уровня (причем отдельным запросом для каждого из элементов верхнего уровня):

SELECT TOP 45
T1._IDRRef,
T1._Marked,
T1._ParentIDRRef,
CASE WHEN (T1._Folder = 0x00) THEN 0x01 ELSE 0x00 END,
T1._Code,
T1._Description,
CASE WHEN T1._PredefinedID > 0x00000000000000000000000000000000 THEN 0x01 ELSE 0x00 END
FROM dbo._Reference34678 T1
WHERE ((T1._Fld929 = ?)) AND ((T1._ParentIDRRef = ?))
ORDER BY CASE WHEN ((T1._Folder = 0x00)) THEN 0x01 ELSE 0x00 END DESC, (T1._Description), (T1._IDRRef)

Далее, к предыдущему запросу добавляется парный запрос, который строит иерархию множественным соединением таблицы справочника с самой собой по полю родителя из первой таблицы равному полю ссылки во второй (получение потомков):

SELECT
T1._IDRRef,
T1._ParentIDRRef,
T2._IDRRef,
T2._ParentIDRRef,
T3._IDRRef,
T3._ParentIDRRef,
T4._IDRRef,
T4._ParentIDRRef,
T5._IDRRef,
T5._ParentIDRRef,
T6._IDRRef,
T6._ParentIDRRef,
T7._IDRRef,
T7._ParentIDRRef,
T8._IDRRef,
T8._ParentIDRRef,
T9._IDRRef,
T9._ParentIDRRef,
T10._IDRRef
FROM dbo._Reference34678 T1
LEFT OUTER JOIN dbo._Reference34678 T2
ON (T1._ParentIDRRef = T2._IDRRef) AND (T2._Fld929 = ?)
LEFT OUTER JOIN dbo._Reference34678 T3
ON (T2._ParentIDRRef = T3._IDRRef) AND (T3._Fld929 = ?)
LEFT OUTER JOIN dbo._Reference34678 T4
ON (T3._ParentIDRRef = T4._IDRRef) AND (T4._Fld929 = ?)
LEFT OUTER JOIN dbo._Reference34678 T5
ON (T4._ParentIDRRef = T5._IDRRef) AND (T5._Fld929 = ?)
LEFT OUTER JOIN dbo._Reference34678 T6
ON (T5._ParentIDRRef = T6._IDRRef) AND (T6._Fld929 = ?)
LEFT OUTER JOIN dbo._Reference34678 T7
ON (T6._ParentIDRRef = T7._IDRRef) AND (T7._Fld929 = ?)
LEFT OUTER JOIN dbo._Reference34678 T8
ON (T7._ParentIDRRef = T8._IDRRef) AND (T8._Fld929 = ?)
LEFT OUTER JOIN dbo._Reference34678 T9
ON (T8._ParentIDRRef = T9._IDRRef) AND (T9._Fld929 = ?)
LEFT OUTER JOIN dbo._Reference34678 T10
ON (T9._ParentIDRRef = T10._IDRRef) AND (T10._Fld929 = ?)
WHERE ((T1._Fld929 = ?)) AND ((T1._IDRRef IN (?)))

Вышеописанные два запроса повторяются для каждого последующего уровня иерархии для всех элементов, которые являются группами. При этом, если начать скроллинг списка, то данные будут подгружаться порциями по N штук, как и при его открытии, повторяя все вышеописанные запросы.

Можем сделать вывод, что развертка динамического списка в виде дерева требует большого количества запросов для построения иерархии этого самого дерева. Поэтому для справочников, содержащих большое количество данных рекомендуется использовать режим отображения «Иерархический список» или по крайней мере не устанавливать свойство «Начальное отображение дерева» в значение «Раскрывать все уровни».
           

Прикладные задачи использования иерархии в 1С

Как вы могли заметить технологическая платформа «1С:Предприятие 8» предоставляет различные возможности построения иерархии. Однако всегда ли их хватает и всегда ли результат ожидаемый?

Для того, чтобы ответить на данный вопрос, давайте рассмотрим пару кейсов, которые произошли у нас на проектах за последнее время.

Иерархии нет, а если найду?

Одной из особенностей платформы 1С:Предприятие 8 является отключение отображения иерархии при отборах, кроме необходимых ей для построения самой иерархии.

Прикладные задачи использования иерархии в 1С

Можно предположить, что так было сделано по причине неясности ожиданий пользователя. Например, нужен ли ему просто быстрый поиск значения или же он ожидает увидеть и иерархию недоступную для выбора. Что делать если задача отобразить эту иерархию все-таки есть или нужно сформировать общую иерархию двух таблиц?

Возможно, эта задача покажется сложной и весьма не очевидной. Однако, для таких задач можно использовать механизм схемы компоновки данных, а точнее его возможности связи наборов данных.

Давайте рассмотрим использование этого механизма на примере. В библиотеке стандартных подсистем существует механизм дополнительных реквизитов и сведений. Данный механизм позволяет расширять структуру объектов метаданных из режима «1С:Предприятие». Благодаря этому типовые решения могут подходить самым разным клиентам, не углубляясь в тонкости отрасли.

Прикладные задачи использования иерархии в 1С

Подготовим новый дополнительный реквизит «Инвентарь» для справочника «Сотрудники» и заполним его у текущих сотрудников.

Прикладные задачи использования иерархии в 1С

Прикладные задачи использования иерархии в 1С

Далее перед нами появляется задача отобразить все значения данного реквизита, а также их владельцев. Для применения механизма схемы компоновки данных необходимо подготовить таблицу с матрицей связей между элементами. В данной ситуации она будет состоять из объединения таблиц инвентаря и сотрудников. В таблице инвентаря матрица связи является хранимой и описывается реквизитами «Ссылка» и «Родитель», где «Ссылка» является источником, а «Родитель» — приемником.

При этом у таблицы сотрудников источником будет выступать аналогично реквизит «Ссылка», а вот приемником — значение дополнительного реквизита.

ВЫБРАТЬ
       СправочникЗначений.Ссылка КАК Источник,
       СправочникЗначений.Родитель КАК Приемник
ИЗ
       Справочник.ЗначенияСвойствОбъектов КАК СправочникЗначений
ГДЕ
       СправочникЗначений.Владелец = &ДополнительныйРеквизит

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
ТЧДополнительныеРеквизиты.Ссылка,
ТЧДополнительныеРеквизиты.Значение
ИЗ
Справочник.Сотрудники.ДополнительныеРеквизиты КАК ТЧДополнительныеРеквизиты
ГДЕ
ТЧДополнительныеРеквизиты.Свойство = &ДополнительныйРеквизит 

Затем подготовим макет схемы компоновки данных, где создадим набор данных с двумя полями «Источник» и «Приемник». В данном примере на входе набора данных мы используем внешний набор данных, что позволяет нам максимально гибко подготовить исходные данные для формирования иерархии. Однако это не является ограничением использования данного подхода и при желании можно использовать и другие источники наборов данных.

Прикладные задачи использования иерархии в 1С

Далее перейдем на вкладку связи наборов данных и добавим правило связи, где укажем поля источника и приемника, а также начальное значение связи.

Прикладные задачи использования иерархии в 1С

На вкладке настройки добавим пустую группировку и заполним выбранные поля соответствующими значениями.

Прикладные задачи использования иерархии в 1С

Подготовив данный макет останется последовательно инициализировать все элементы компоновки данных и заполнить реквизит с типом дерево на форме.

// Получение макета СКД.
СхемаКомпоновкиДанных = Справочники.ЗначенияСвойствОбъектов.ПолучитьМакет("УОП_ИерархияЗначений");

// Инициализация компоновщиков.
КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновкиДанных));
КомпоновщикНастроек.ЗагрузитьНастройки(СхемаКомпоновкиДанных.НастройкиПоУмолчанию);

КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных,
КомпоновщикНастроек.Настройки,,,
Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));

ВнешнийНаборДанных = Новый Структура("ТаблицаЭлементов", ТаблицаСвязей);

ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, ВнешнийНаборДанных);

// Подготовка и заполнение дерева иерархии.
ДеревоИерархии = Новый ДеревоЗначений;

ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(ДеревоИерархии);

ПроцессорВывода.Вывести(ПроцессорКомпон

В результате можно получить вот такое дерево элементов, где к основной иерархии элементов инвентаря был добавлен дополнительный уровень с сотрудниками.

Прикладные задачи использования иерархии в 1С

Тут важно понимать, что в данном случае мы занимаемся так называемой декларативной частью разработки. То есть описываем, какие именно поля связываются, чтобы образовать матрицу связности, а ее построением и рекурсивным обходом занимается «черный ящик» СКД, за что ему большое спасибо!

Таким образом, для решения задачи формирования иерархии разнотипных сущностей и формировании сложных деревьев можно использовать механизм схемы компоновки данных платформы «1С:Предприятие 8». Данный подход является универсальным и подходит для решения большого количества задач связанных с формированием иерархии.

Иерархия в отчете приготовления блюд

В предыдущем примере мы рассмотрели базовый вариант, когда иерархия одной из таблиц уже являлась хранимой. Однако, на практике так бывает далеко не всегда. Следующая история произошла при разработке «Отчета по плановой себестоимости» конфигурации «1С:Предприятие 8. Общепит, редакция 3.0».

Данный отчет отображает плановую себестоимость приготовления блюд по ингредиентам с учетом разложения их полуфабрикатов. При этом для оценки каждого блюда или полуфабриката используются только актуальные рецептуры на конкретную дату. Соответственно состав входящих полуфабрикатов от времени может меняться, т. е. не является хранимым.

Пример построенного отчета.

Иерархия в отчете приготовления блюд

Если мы посмотрим на пример сформированного отчета, то можно увидеть все уровни приготовления блюда «Пюрешка с котлеткой и огурчиком» согласно его рецептуры.

Что же из себя представляет эта рецептура? Рецептура приготовления является документом, в котором в шапке указывается блюдо и количество, которое получается на выходе, а в табличной части указан состав ингредиентов, необходимый для его приготовления. При этом ингредиентом может выступать и полуфабрикат, который по сути является таким же блюдом со своей рецептурой приготовления.

Иерархия в отчете приготовления блюд

Иерархия в отчете приготовления блюд

Получается, что на уровне объекта метаданных связь между блюдами и ингредиентами определяется лишь объектно, а не двумя реквизитами, но иерархию построить нужно. Для этого мы используем тот же самый принцип со схемой компоновки данных, а именно, сначала готовим таблицу производства, где описывается связь между блюдами и ингредиентами, затем она передается схеме компоновки данных и результат выводится в отчет.

Построение таблицы производства осуществляется в несколько этапов:

  1. Получение составов рецептур приготовляемых блюд и их полуфабрикатов с учетом актуальных рецептур.
  2. Получение стоимости приготовления каждого блюда/фабриката по ценам ингредиентов.
  3. Получение итоговой общей таблицы.

Для сохранения связей между блюдами и ингредиентами при построении таблицы производства заполняются служебные колонки «Ключ источника» и «Ключ приемника». Ключ источника идентифицирует конкретную строку приготовления. Он может быть представлен уникальным идентификатором или же просто числом, которое постепенно увеличивается. Ключом приемника является ключ источника блюда/полуфабриката для приготовления которого и нужен этот ингредиент.

В результате получим следующую таблицу производства.

Блюдо Ингредиент Ключ источника Ключ приемника Уровень Количество блюда Количество ингредиента Сумма
Пюрешка с котлеткой и огурчиком 1 0 0 1 1 882,5
Пюрешка с котлеткой и огурчиком Пюрешка с котлеткой 2 1 1 1 1 882,5
Пюрешка с котлеткой и огурчиком Огурчик свежий 3 1 1 1 0,5 0
Пюрешка с котлеткой Пюрешка 4 2 2 1 1 240
Пюрешка с котлеткой Котлетка 5 2 2 1 0,5 642,5
Пюрешка Картошка 6 4 3 1 4 200
Котлетка Мука 7 5 3 0,5 0,25 2,5
Пюрешка Молоко 8 4 3 1 1 40
Котлетка Фарш 9 5 3 0,5 2,5 625
Котлетка Хлеб 10 5 3 0,5 0,5 15

Полученную таблицу помещаем в качестве набора данных.

Иерархия в отчете приготовления блюд

На вкладке связи наборов указываем поле «Ключ источника» в качестве выражения источника и «Ключ приемника» в качестве выражения приемника.

Иерархия в отчете приготовления блюд

Для группировки колонок «Блюдо» и «Ингредиент», а также «Количество блюда» и «Количество ингредиента» подготовим соответствующие вычисляемые поля «Номенклатура» и «Количество», которые будем заполнять в зависимости от типа строки.

Иерархия в отчете приготовления блюд

На вкладке настройки укажем выбранные поля.

Иерархия в отчете приготовления блюд

После компоновки данных получается отчет с иерархией по каждому уровню производства.

Иерархия в отчете приготовления блюд

По итогу, вследствие использования схемы компоновки данных для формирования иерархии, результат можно представить как в виде дерева элементов, так и в табличном документе.

Если нам нужен иерархический вид, а его нет

Давайте представим себе ситуацию, что к вам приходит клиент и говорит, что у вас справочник не иерархический, а нам нужен именно иерархический и все доводы ни к чему не приходят.

Схожая ситуация у нас произошла при разработке «1С:УНФ 8. Управление предприятием общепита», в котором справочник «Дисконтные карты» являлся линейным, но с подчинением справочнику «Виды карт». Однако подчинение другому справочнику не решало все возможные ситуации. Потому мы решили это исправить.

Для этого мы сначала включили свойство справочника иерархический и выбрали вид иерархии.

Прикладные задачи использования иерархии в 1С

Однако если запустить такой справочник и попробовать создать группу, то режим отображения останется список и переключение на другие варианты будет недоступно. Даже если вы заполните у элементов реквизит «Родитель».

Прикладные задачи использования иерархии в 1С

Прикладные задачи использования иерархии в 1С

Данное поведение связано с тем, что данный справочник является подчиненным и для построения иерархии платформе требуется отбор по полю владельца.

Прикладные задачи использования иерархии в 1С

Прикладные задачи использования иерархии в 1С

Стоит отметить, что если попробовать просто выполнить группировку по полю владельца, то платформа все равно не отобразит иерархию.

Прикладные задачи использования иерархии в 1С

Диаграмма структуры организации за 5 минут

К вам приходит начальник и просит показать структуру организации в графическом виде, а до совещания осталось пару минут — не беда.

Для построения диаграмм на платформе «1С:Предприятие 8» можно воспользоваться табличным документом, графической схемой или полем HTML. Однако, при использовании табличного документа или графической схемы разработчику потребуется генерировать объекты, связи между ними и смещать относительно друг от друга.

Пока речь идет о прямой линейной структуре это звучит не так страшно. Хотя и за короткое время решить не получится. Однако если структура дерева начинает ветвится или имеет петли? В такие моменты приходит на помощь поле HTML. В частности для реализации данной задачи можно воспользоваться библиотекой динамической визуализации Vis.js. Она проста в использовании и предоставляет возможность обработки большого объема данных.

Для начала подготовим HTML-разметку, которая будет помещаться в реквизит поля. В разделе <head> разместим подключение библиотеки Vis.js, а в <body> разместим область куда будет выведено дерево и место для скрипта инициализации дерева.

<html> 
<head>
<!– Подключим библиотеку Vis.js-->
<script type="text/javascript" src="https://unpkg.com/vis-network/dist/vis-network.min.js"></script>
</head> 
<body>
     <div id="canvasConvainer" style="width: 100%; height: 100%;">
          <!-- Здесь будет располагаться дерево после инициализации -->
     </div>   
     <script type="text/javascript">
          // Здесь будет располагаться скрипт инициализации дерева.
     </script>
</body>
</html> 

Для инициализации дерева с помощью библиотеки необходимо подготовить список узлов и таблицу ребер. В качестве примера представим следующую структуру организации:

  • Офис Сладкоежка (Код 001):
    • Офис Плюшки (Код 002);
    • Офис Пампушки (Код 003);
  • Офис Сытый волк (Код 004).

Представим структуру данной организации в виде соответствующих коллекций узлов и связей между ними.

Коллекция узлов:

Код узла Наименование узла
001 Офис Сладкоежка
002 Офис Плюшки
003 Офис Пампушки
004 Офис Сытый волк

Коллекция связей между узлами (Таблица ребер):

Источник Приемник
002 001
003 001

Преобразуем данные коллекции в строки скрипта инициализации дерева.

//  Подготовим список узлов.
var nodes = new vis.DataSet([
{ id: "001", label: "Офис Сладкоежка" },
{ id: "002", label: "Офис Плюшки" },
{ id: "003", label: "Офис Пампушки" },
{ id: "004", label: "Офис Сытый волк" },
]);

// Подготовим таблицу ребер.
var edges = new vis.DataSet([
{ from: "002", to: "001" },
{ from: "003", to: "001" }
]); 

Добавим определение места размещения дерева и передадим необходимые параметры для инициализации.

// Объект HTML документа помещаем в переменную
var container = document.getElementById("canvasConvainer");
// Коллекция данных для визуализации
var data = {nodes: nodes, edges: edges,};
// Коллекция параметров визуализации
var options = {};
// Инициализация объекта приложения
var network = new vis.Network(container, data, options); 

Разместим текст итогового скрипта в исходную HTML-разметку. В результате запуска получим следующую картинку:

Прикладные задачи использования иерархии в 1С

Если же написать заполнение этих коллекций на основании результата запроса по нужным нам таблицам, то в качестве узлов будут выступать уникальные идентификаторы ссылок, а связь между узлами может быть описана идентификаторами реквизитов «Ссылка» и «Родитель».

Таким образом, благодаря использованию библиотеки Vis.js можно формировать сложные диаграммы связи между объектами за считанные минуты.

Оптимизация «Структурных единиц»

Случай произошел при внедрении типового продукта «1С:УНФ 8. Управление предприятием общепита» у крупного промышленного предприятия. Пользователи системы открывали форму выбора структурных единиц и время ее открытия составляло от 2 до 5 минут, что, конечно, не считалось приемлемым. При этом в качестве системы управления базами данных использовалась Microsoft SQL Server 2017, а технологическая платформа была версии 8.3.18.1289.

Для того, чтобы разобраться с этой проблемой давайте посмотрим на саму форму выбора. Она состоит из динамического списка, полей отборов и вывода контактной информации.

Оптимизация «Структурных единиц»

Если ее запустить с замером производительности, то в результате в лидерах можно увидеть: обход всех строк динамического списка методом ПриПолученииДанныхНаСервере.

Оптимизация «Структурных единиц»

Данные строки кода действительно создают задержку при отображении списка. Однако их продолжительность не занимает все время и лидирующую позицию занимает событие открытия формы. Из чего можно предположить, что данная форма так долго открывается из-за чего то другого. Например, влияния условного оформления или набора картинок значений в динамическом списке или вообще чего-то другого.

Для того, чтобы исключить все возможные гипотезы с неоптимальным кодом и модификациями форм, создадим простую внешнюю обработку, которая будет содержать только динамический список.

Оптимизация «Структурных единиц»

Пробуем ее запустить вместе с замером производительности. И тут начинается самое интересное: вроде кода нет, но почему тогда форма снова открывается так долго. Давайте разбираться.

Для этого настроим сбор технологического журнала по событиям CALL и SDBL:


<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://v8.1c.ru/v8/tech-log">
     <log history="24"
                location="e:ЛогиТестСтруктурныхЕдиниц">
          <property name="all"/>
          <event>
                <eq property="name" value="CALL"/>
                <eq property="p:processName" value="grimut_WhatYouWant3"/>         
          </event>
          <event>
                <eq property="name" value="SDBL"/>
                <eq property="p:processName" value="grimut_WhatYouWant3"/>         
          </event>
     </log>
</config> 

Повторим открытие формы и остановим сбор. После открытия файла логов можно увидеть вот такие запросы и их количество совпадает с количеством элементов — 615.

Оптимизация «Структурных единиц»

Таким образом, технологическая платформа для получении дерева элементов выполняет запросы уточнения всей иерархии на вложенность в справочнике и сумма выполнения данных запросов занимает все указанное время.

Стоит отметить, что справочник «Структурные единицы» является иерархическим, с иерархией элементов.

Оптимизация «Структурных единиц»

Данная технология не является новой и применяется в других типовых решениях. Например, в «малоизвестном» продукте «1С:ERP Управление предприятием 2» справочник «Партнеры» также имеет иерархию элементов и при этом работает очень быстро. Если мы заглянем на его форму списка, то увидим лишь одно явное отличие: свойство отображение таблицы в справочнике «Партнеры» стоит «Иерархический список», а в «Структурные единицы» — Дерево.

Оптимизация «Структурных единиц»

Оптимизация «Структурных единиц»

Делаем предположение, что причиной является этот переключатель. Устанавливаем его в значение в «Иерархический список» и повторяем эксперимент. В результате получаем открытие формы за 3 секунды. А установив значение «Список» форма открылась меньше чем за одну секунду. Повторив сбор технологического журнала мы пришли к выводу, что для отображении иерархии платформа формирует запросы для каждого отображаемого элемента. При этом если элемент вложенный и ветка не раскрыта, то данные по нему получены не будут, что и влияет на скорость отображения.

Далее перед нами стал выбор: отказаться от использования дерева и перейти к иерархическому списку или реализовать данное дерево заполняя его самостоятельно.

Выбирать подразделения или склады не осознавая структуры предприятия очень тяжело. Особенно, если название элементов совпадает. Потому мы приняли решение сохранить отображение деревом. Для этого мы добавили честный реквизит с типом «Дерево» и повторили отображаемые колонки.

Для заполнения этого дерева мы сначала выполняем запрос повторяющий текст запроса динамического списка, а затем пользуемся механизмом схемы компоновки данных. Данный механизм позволяет сократить время на формирование иерархии, т. к. решает задачу иерархии не с помощью запросов к базе данных, а с помощью встроенного механизма компоновки данных.

Оптимизация «Структурных единиц»

Оптимизация «Структурных единиц»

Повторив эксперимент после модернизации получили время выполнения меньше одной секунды. Таким образом, использование динамических списков иерархических объектов и отображение в виде дерева может привести к большому количеству служебных запросов к базе данных и задержке при открытии, перемещении или поиске по таблице.

Для того, чтобы этого избежать рекомендуется либо отказаться от режима отображения деревом и перейти к одноуровневому списку, либо формировать иерархию деревьев самостоятельно. Например, с помощью механизма схемы компоновки данных.

Матрица смежности в древовидных структурах 1С необходима

Что ж, подведем первые итоги.

Прежде всего заметим, что математику никто не отменял (да и вряд ли когда-то отменит) и если речь идет о решении задачи построения графа, а в данном случае частного случая графа — дереве, то обойтись без матрицы смежности нам не удастся. 1С строит матрицу смежности, именно поэтому неизбежно возникает поле родителя или поле владельца в структуре СУБД.

Поскольку для построения дерева по матрице смежности системе нужно строить соединение по этому полю, то оно индексируется и включается в состав индексов других индексированных полей.

Кроме того, мы и сами можем построить деревья. Для этого мы можем воспользоваться возможностями СКД или сторонних компонент, но так или иначе от матрицы смежности нам никуда не деться.

Что ожидает нас в последующей серии публикации? Мы поговорим о:

  • сетевых маршрутах;
  • компонентах сильной связности;
  • циклах;
  • графах с миллионами ребер;
  • реальных задачах, где возникают названные пункты и о подходах к их решению.

Вторая статья про графовые структуры в 1С: «Графовые структуры в 1С — сетевые маршруты для анализа финансового результата».

Авторы статьи

Дмитрий Чесноков

Дмитрий Чесноков

Андрей Черанев

Андрей Черанев

Всем привет. Продолжаем уроки по основам работы на платформе 1С: Предприятие 8.3.

Напомню, что уроки будут с самого просто к самому сложному, то есть будут такие этапы: новичок, средний уровень и более сложный уровень. На протяжении всех этих уровней мы будем изучать новые темы и работать как в качестве разработчика, так и в качестве пользователя. Зачем так? Для того, чтобы больше понимать как и что разрабатывать, необходимо понимать какие процессы происходят в режиме пользователя.

Сегодня мы с вами продолжим изучать справочник и его особенности. На одном из уроков мы проходили, что справочник может быть иерархическим, а сама иерархия у него может быть двух видов: Иерархия групп и элементов и Иерархия элементов.

Вспомните, когда мы выбирали Иерархия групп и элементов, у нас в пользовательском режиме появлялось поле “Родитель” – это та папка (группа), которая содержит в себе побочные элементы. Запомните это, будет удивление, когда мы создадим справочник со вторым видом.

Первый вид мы уже рассмотрели и поработали с ним, теперь необходимо поработать со вторым видом – Иерархия элементов.

Напомню, что менять отображение элементов можно по команде: “Еще-Режим просмотра-Дерево”.

Иерархия элементов – это та ситуация, когда элемент может быть просто элементом или может быть элементом, который содержит другие элементы (Рисунок 1).

Рисунок 1 - Иерархия элементов
Рисунок 1 – Иерархия элементов

Запустим информационную базу в режиме разработчика и создадим новый справочник “Отдел” (Рисунок 2). Перейдем на вкладку “Иерархия” и там выберем “Иерархия элементов”.

Рисунок 2 - Вкладка "Иерархия"
Рисунок 2 – Вкладка “Иерархия”

После этого перейдем в пользовательский режим и заполним справочник (Рисунок 3).

Рисунок 3 - Иерархия элементов.
Рисунок 3 – Иерархия элементов.

На что тут важно обратить внимание. Нажмите на кнопку “Создать” и посмотрим из чего состоит форма элемента (Рисунок 4).

Рисунок 4 - Форма элемента
Рисунок 4 – Форма элемента

Присмотритесь на рисунок 4, на форме элемента есть поле “Родитель”!!! Такое же поле было, когда мы создавали справочник с иерархией групп и элементов, но в том случае было понятно: родитель это тот, который главный и содержит в себе элементы. А как же в этом случае? В этом случае элемент одновременно является и элементом и родителем, который может содержать в себе другие элементы. Такая иерархия тоже важна, но смысл мы ее поймем только немного позже, а сейчас необходимо и самое главное, это создавать такие справочники и понимать, что в данном случае элемент – это и родитель и содержит в себе другие элементы.

Еще один момент, который необходимо рассмотреть в иерархии – это такое свойство как “Ограничение количества уровней иерархии” (Рисунок 5).

Рисунок 5 - Ограничение уровней
Рисунок 5 – Ограничение уровней

Что означает это свойство:

Посмотрите на рисунок 5. В данном случае у нас ограничение стоит 2, а это значит, что вы сможете создать в справочнике группу и указать в качестве родителя только одну группу, то есть внутри группы вы сможете создать максимум еще одну группу, а внутри второй группы уже не сможете и для этого необходимо увеличить это ограничение

Рисунок 6 - Увеличение количества уровней (вложенности)
Рисунок 6 – Увеличение количества уровней (вложенности)

На этом статья урока подходит к концу. Попробуйте выполнить все действия, которые описаны в этом уроке.

Всем спасибо. Задать вопросы, которые у вас возникли вы можете, написав комментарий или вступить в группу и задать там свой вопрос. Ссылка для вступления в группу – t.me.Apiscourses

Так же можно посмотреть видео по платформе, для этого нажми YouTube

Подписаться в группу ВКонтакте

Или написать на электронную почту – awesome.razrab@yandex.ru

Прошлые уроки:

Введение Урок 1 Урок 2 Урок 3 Урок 4 Урок 5 Урок 6

Урок 7 Урок 8 Урок 9 Урок 10 Урок 11 Урок 12

На этом все. Жду Вас на следующем занятии.

P.S. Подписывайтесь на мой канал 🙂

Получение элементов иерархического справочника, находящихся в подчинении заданной группы

Для получения подчиненных элементов иерархического справочника в языке запросов предусмотрена конструкция В ИЕРАРХИИ:

ВЫБРАТЬ
    Номенклатура.Код, 
    Номенклатура.Наименование КАК Наименование, 
    Номенклатура.ЗакупочнаяЦена 
ИЗ 
    Справочник.Номенклатура КАК Номенклатура
ГДЕ 
    Номенклатура.Ссылка В ИЕРАРХИИ (&Группа) 

В данном примере будут получены все записи справочника Номенклатура, находящиеся в группе &Группа, включая ее саму, ее подчиненные группы и элементы, принадлежащие подчиненным группам.

Если же нас интересуют только элементы и группы, находящиеся непосредственно в заданной группе, то такие элементы мы можем получить, установив условие на поле Родитель:

ВЫБРАТЬ
    Номенклатура.Код, 
    Номенклатура.Наименование КАК Наименование, 
    Номенклатура.ЗакупочнаяЦена 
ИЗ 
    Справочник.Номенклатура КАК Номенклатура
ГДЕ 
    Номенклатура.Родитель = &Группа

Такой запрос выберет группы и элементы, находящиеся в подчинении группы со ссылкой &Группа.

Проверка наличия подчиненных элементов у элемента справочника

Для проверки наличия подчиненных записей элемента справочника можно пользоваться запросом, аналогичным представленному:

ВЫБРАТЬ ПЕРВЫЕ 1 
    Номенклатура.Ссылка 
ИЗ 
    Справочник.Номенклатура КАК Номенклатура 
ГДЕ 
    Номенклатура.Родитель = &Родитель

В данном примере ссылка элемента, для которого необходимо проверить наличие дочерних элементов, записывается в параметр запроса &Родитель. После выполнения такого запроса необходимо проверить результат на пустоту. Если результат не пустой, то подчиненные записи есть. Иначе — нет.

Если Запрос.Выполнить().Пустой() Тогда 
    Сообщить("Записей нет"); 
Иначе 
    Сообщить("Записи есть"); 
КонецЕсли;

Получение всех родителей элемента

В языке запросов не предусмотрено специальных средств для получения всех родителей элемента. Для выполнения задачи можно воспользоваться иерархическими итогами, однако получение иерархических итогов оптимизировано для построения итогов большого количества записей, и не вполне эффективно для получения родителей одного элемента. Для более эффективного получения всех родительских записей элемента, рекомендуется перебирать в цикле его родителей небольшими порциями.

ТекущийЭлементНоменклатуры = ЭлементНоменклатура;

Запрос = Новый Запрос(
    "ВЫБРАТЬ 
    |    Номенклатура.Родитель, 
    |    Номенклатура.Родитель.Родитель, 
    |    Номенклатура.Родитель.Родитель.Родитель, 
    |    Номенклатура.Родитель.Родитель.Родитель.Родитель, 
    |    Номенклатура.Родитель.Родитель.Родитель.Родитель.Родитель 
    |ИЗ 
    |    Справочник.Номенклатура КАК Номенклатура 
    |ГДЕ 
    |    Номенклатура.Ссылка = &ТекущийЭлементНоменклатуры"
); 

Пока Истина Цикл 
    Запрос.УстановитьПараметр("ТекущийЭлементНоменклатуры", ТекущийЭлементНоменклатуры); 
    Результат = Запрос.Выполнить(); 
    Если Результат.Пустой() Тогда 
        Прервать; 
    КонецЕсли; 
    Выборка = Результат.Выбрать(); 
    Выборка.Следующий(); 
    Для НомерКолонки = 0 По Результат.Колонки.Количество() - 1 Цикл 
        ТекущийЭлементНоменклатуры = Выборка[НомерКолонки]; 
        Если ТекущийЭлементНоменклатуры = Справочники.Номенклатура.ПустаяСсылка() Тогда 
            Прервать; 
        Иначе 
            Сообщить(ТекущийЭлементНоменклатуры); 
        КонецЕсли; 
    КонецЦикла; 

    Если ТекущийЭлементНоменклатуры = Справочники.Номенклатура.ПустаяСсылка() Тогда 
        Прервать; 
    КонецЕсли; 
КонецЦикла;

В данном примере в окно служебных сообщений выводятся все родители для ссылки, записанной в переменную ЭлементНоменклатура. В цикле выбирается по пять родителей ссылки.

Если число уровней в справочнике ограничено и невелико, то возможно получение всех родителей одним запросом без цикла.

Вывод иерархического справочника в отчет

Для вывода иерархического справочника в отчет с сохранением иерархии необходимо пользоваться запросом аналогичным следующему:

ВЫБРАТЬ
    Номенклатура.Код, 
    Номенклатура.Наименование КАК Наименование, 
    Номенклатура.ЗакупочнаяЦена 
ИЗ 
    Справочник.Номенклатура КАК Номенклатура 
УПОРЯДОЧИТЬ ПО 
    Наименование ИЕРАРХИЯ

Данный запрос выбирает все записи из справочника и производит упорядочивание по иерархии. Результат будет упорядочен по наименованию, с учетом иерархии.

Для того, чтобы группы справочника размещались выше элементов необходимо в данном запросе заменить предложение УПОРЯДОЧИТЬ ПО на следующее:

УПОРЯДОЧИТЬ ПО 
    Номенклатура.ЭтоГруппа ИЕРАРХИЯ,
    Наименование

Результат по-прежнему будет упорядочен по иерархии, однако группы будут располагаться выше элементов.

Возможна также замена предложения УПОРЯДОЧИТЬ ПО на предложение АВТОУПОРЯДОЧИВАНИЕ. В этом случае результат будет упорядочен в соответствии с настройками справочника, т.е. если в справочнике указано, что группы должны располагаться выше элементов, то они будут расположены выше.

Получить иерархическую структуру справочника также возможно и при помощи итогов:

ВЫБРАТЬ 
    Номенклатура.Код, 
    Номенклатура.Наименование КАК Наименование, 
    Номенклатура.ЗакупочнаяЦена 
ИЗ 
    Справочник.Номенклатура КАК Номенклатура 
ГДЕ 
    Номенклатура.ЭтоГруппа = ЛОЖЬ 
УПОРЯДОЧИТЬ ПО 
    Наименование 
ИТОГИ ПО
    Номенклатура.Ссылка ТОЛЬКО ИЕРАРХИЯ

Получение итогов по иерархии

Для получения итогов по иерархии в запросе необходимо в предложении ИТОГИ ПО указать ключевое слово ИЕРАРХИЯ после указания поля, по которому будет рассчитываться итоги. Пример отчета «Обороты номенклатуры» с получением итогов по иерархии:

ВЫБРАТЬ
    УчетНоменклатурыОбороты.Номенклатура КАК Номенклатура, 
    УчетНоменклатурыОбороты.Номенклатура.Представление, 
    УчетНоменклатурыОбороты.КоличествоОборот КАК КоличествоОборот 
ИЗ 
    РегистрНакопления.УчетНоменклатуры.Обороты КАК УчетНоменклатурыОбороты 
ИТОГИ СУММА(КоличествоОборот) ПО 
    Номенклатура ИЕРАРХИЯ

В результате данного запроса будут рассчитаны итоги не только для каждой номенклатуры, но и для групп, к которым принадлежит та или иная номенклатура.

В случае, когда не нужны итоги по элементам, а нужны итоги только по группам, необходимо использовать в итогах конструкцию ТОЛЬКО ИЕРАРХИЯ:

ВЫБРАТЬ
    УчетНоменклатурыОбороты.Номенклатура КАК Номенклатура, 
    УчетНоменклатурыОбороты.Номенклатура.Представление, 
    УчетНоменклатурыОбороты.КоличествоОборот КАК КоличествоОборот 
ИЗ 
    РегистрНакопления.УчетНоменклатуры.Обороты КАК УчетНоменклатурыОбороты 
ИТОГИ СУММА(КоличествоОборот) ПО 
    Номенклатура ТОЛЬКО ИЕРАРХИЯ

В результате данного запроса будут итоговые записи только для групп номенклатуры.

Поиск:
1С:Предприятие • Иерархия • Справочник • Язык запросов

Добавить комментарий