Как реализовать многоуровневую иерархическую группировку в табличном документе 1С?

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

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

Анализ проблемы: почему группировка не становится вложенной

Рассмотрим ситуацию, с которой часто сталкиваются разработчики: при использовании метода НачатьГруппуСтрок визуально создается только один уровень, который просто открывает и закрывает все данные сразу. Основная ошибка здесь заключается в линейном подходе к выводу строк. Чтобы получить иерархию, вызовы методов управления группами должны быть вложенными друг в друга, либо необходимо использовать механизм автогруппировки.

Метод 1: Ручное управление вложенными группами

Проанализируем работу методов НачатьГруппуСтрок() и ЗакончитьГруппуСтрок(). Эти методы работают по принципу стека: каждая новая открытая группа внутри уже существующей становится ее дочерним элементом. Чтобы реализовать три уровня (Контрагент > Сделка > Реализация), нам нужно строго соблюдать порядок открытия и закрытия секций.

Разберем по шагам алгоритм вывода:

  1. Выводим строку-заголовок верхнего уровня (Контрагент).
  2. Вызываем НачатьГруппуСтрок() для второго уровня.
  3. В цикле выводим строки второго уровня (Сделки).
  4. Внутри этого цикла вызываем еще раз НачатьГруппуСтрок() для третьего уровня (Реализации).
  5. Выводим детальные записи.
  6. Закрываем группы в обратном порядке через ЗакончитьГруппуСтрок().

Посмотрим на пример реализации такого подхода:


// Пример ручного управления вложенностью
Для Каждого СтрКонтрагент Из ТЗГруппировка Цикл
    
    // Выводим шапку контрагента
    ОбластьКонтрагент = Макет.ПолучитьОбласть("Строка|Контрагент");
    ЗаполнитьЗначенияСвойств(ОбластьКонтрагент.Параметры, СтрКонтрагент);
    ТабДок.Вывести(ОбластьКонтрагент);
    
    // Открываем группу для Сделок
    ТабДок.НачатьГруппуСтрок("Сделки", Ложь); 
    
    Для Каждого СтрСделка Из СтрКонтрагент.СтрокиСделок Цикл
        
        ОбластьСделка = Макет.ПолучитьОбласть("Строка|Сделка");
        ЗаполнитьЗначенияСвойств(ОбластьСделка.Параметры, СтрСделка);
        ТабДок.Вывести(ОбластьСделка);
        
        // Открываем группу для Реализаций (3-й уровень)
        ТабДок.НачатьГруппуСтрок("Реализации", Ложь);
        
        Для Каждого СтрРеализация Из СтрСделка.СтрокиРеализаций Цикл
            ОбластьРеал = Макет.ПолучитьОбласть("Строка|Детали");
            ЗаполнитьЗначенияСвойств(ОбластьРеал.Параметры, СтрРеализация);
            ТабДок.Вывести(ОбластьРеал);
        КонецЦикла;
        
        // Закрываем уровень реализаций
        ТабДок.ЗакончитьГруппуСтрок();
        
    КонецЦикла;
    
    // Закрываем уровень сделок
    ТабДок.ЗакончитьГруппуСтрок();
    
КонецЦикла;

Метод 2: Использование Автогруппировки

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

Рассмотрим преимущества этого метода:

Выясним, как это выглядит на практике:


ТабДок.НачатьАвтогруппировкуСтрок();

Для Каждого Стр Из ТЗДанные Цикл
    Область = Макет.ПолучитьОбласть("Строка");
    ЗаполнитьЗначенияСвойств(Область.Параметры, Стр);
    
    // Параметр Стр.Уровень определяет вложенность (0 - корень, 1 - вложено в 0 и т.д.)
    ТабДок.Вывести(Область, Стр.Уровень); 
КонецЦикла;

ТабДок.ЗакончитьАвтогруппировкуСтрок();

Важный момент: Для того чтобы автогруппировка сработала корректно, данные в вашей таблице значений (или результате запроса) должны быть предварительно отсортированы в иерархическом порядке. Если после строки 1-го уровня пойдет строка 3-го, а затем снова 1-го, дерево группировок будет "разорвано".

Разница между Вывести() и Присоединить()

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

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

Дополнительные настройки отображения

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

Резюмируем: Для создания качественной иерархии в табличном документе 1С лучше всего использовать связку НачатьАвтогруппировкуСтрок() и передачу уровня в метод Вывести(). Это минимизирует количество ошибок и делает структуру документа гибкой.

← На главную