Почему в планировщике 1С выводятся все сотрудники для каждого подразделения и как настроить правильную группировку?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

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

Выясним причину проблемы

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


Табель.Измерения.Очистить();
ИПодразделение = Табель.Измерения.Добавить("Подразделение", "Подразделение");
ИСотрудник = Табель.Измерения.Добавить("Сотрудник", "Сотрудник");

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

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

Штатное решение: использование иерархии внутри одного измерения

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

Разберем по шагам, как переписать алгоритм:

  1. Очищаем коллекцию измерений и создаем ровно одно измерение — например, "Структура" или "Сотрудники".
  2. Для каждого подразделения верхнего уровня добавляем элемент в коллекцию Измерение.Элементы.
  3. Для добавления сотрудников обращаемся к свойству Элементы конкретного объекта ЭлементИзмеренияПланировщика (то есть подразделения). Таким образом, сотрудники становятся дочерними узлами подразделения.
  4. При создании записей планировщика (Табель.Элементы.Добавить(...)) в соответствие ЗначенияИзмерений передаем только конечное измерение — конкретного сотрудника.

Посмотрим на практический пример кода, реализующий данный подход:


Табель.Измерения.Очистить();
Табель.Элементы.Очистить();

// Создаем только одно измерение вместо двух
ИзмерениеСотрудники = Табель.Измерения.Добавить("Сотрудник", "Сотрудники подразделений");

Для Каждого СтрокаПодразделение Из ДанныеТабеля.Строки Цикл
    
    ПодразделениеУИД = Строка(СтрокаПодразделение.ПодразделениеУИД);
    
    // Ищем или создаем родительский элемент (Подразделение)
    ЭлементПодразделение = ИзмерениеСотрудники.Элементы.Найти(ПодразделениеУИД);
    Если ЭлементПодразделение = Неопределено Тогда 
        ЭлементПодразделение = ИзмерениеСотрудники.Элементы.Добавить(ПодразделениеУИД, СтрокаПодразделение.Подразделение);
    КонецЕсли;                
    
    Для Каждого СтрокаСотрудник Из СтрокаПодразделение.Строки Цикл  
        
        СотрудникУИД = Строка(СтрокаСотрудник.СотрудникУИД);
        
        // Добавляем сотрудника во вложенную коллекцию элементов подразделения!
        ЭлементСотрудник = ЭлементПодразделение.Элементы.Найти(СотрудникУИД);
        Если ЭлементСотрудник = Неопределено Тогда 
            ЭлементСотрудник = ЭлементПодразделение.Элементы.Добавить(СотрудникУИД, СтрокаСотрудник.Сотрудник);
        КонецЕсли;
        
        Для Каждого СтрокаТабеля Из СтрокаСотрудник.Строки Цикл
            
            // Задаем отбор только по нашему измерению (указывая сотрудника)
            ОтборИзмерений = Новый Соответствие;
            ОтборИзмерений.Вставить("Сотрудник", СотрудникУИД);
            
            Если Не ЗначениеЗаполнено(СтрокаТабеля.НачалоИнтервала) Или Не ЗначениеЗаполнено(СтрокаТабеля.ОкончаниеИнтервала) Тогда 
                Продолжить;
            КонецЕсли;
            
            НовыйЭлементПланировщика = Табель.Элементы.Добавить(СтрокаТабеля.НачалоИнтервала, СтрокаТабеля.ОкончаниеИнтервала);
            НовыйЭлементПланировщика.ЗначенияИзмерений = Новый ФиксированноеСоответствие(ОтборИзмерений);
            НовыйЭлементПланировщика.Значение = Новый Структура("ТипСостояния, ПричинаСостояния", СтрокаТабеля.ТипСостояния, СтрокаТабеля.ПричинаСостояния);
            НовыйЭлементПланировщика.Текст = СтрокаТабеля.ТипСостоянияОписание;
            НовыйЭлементПланировщика.Подсказка = СтрокаТабеля.ПричинаСостоянияОписание;  
            
        КонецЦикла;
    КонецЦикла;
КонецЦикла;

Управление иерархией элементов в интерфейсе

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

  1. Навигация по структуре: у объекта ЭлементИзмеренияПланировщика доступны свойства Элементы (коллекция подчиненных строк) и Родитель (ссылка на вышестоящий узел либо Неопределено).
  2. Программное управление узлами: для раскрытия и сворачивания веток можно вызывать методы планировщика РазвернутьЭлементИзмерения(<Элемент>, <СПодчиненными>) и СвернутьЭлементИзмерения(<Элемент>, <СПодчиненными>).
  3. Динамическая загрузка данных: если список сотрудников огромный, полезно использовать события планировщика ПередРазворачиваниемЭлементаИзмерения и ПередСворачиваниемЭлементаИзмерения, чтобы подгружать данные по сотрудникам только в момент раскрытия подразделения пользователем.

Что делать, если версия платформы ниже 8.3.17?

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

  1. Вынос фильтрации на форму: в самом планировщике создается только одно плоское измерение «Сотрудник». Выбор подразделения выносится в отдельное поле ввода или дерево на форме. При смене подразделения планировщик программно переформировывается только для сотрудников выбранного отдела.
  2. Смена элемента управления: если требуется полноценное отображение сложной многоуровневой структуры с гибкими группировками и пересечениями, лучше отказаться от планировщика в пользу Диаграммы Ганта, Поля табличного документа или визуализации на базе Поля HTML-документа.
← На главную