Почему не работает НачатьАвтогруппировкуСтрок() в Табличном Документе и как это исправить

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

При формировании сложных отчетов программным способом часто возникает необходимость сгруппировать данные по определенным периодам или категориям. Метод НачатьАвтогруппировкуСтрок() объекта ТабличныйДокумент кажется простым решением, однако новички часто сталкиваются с ситуацией, когда "плюсики" группировки не появляются, либо данные выводятся в ряд без ожидаемой иерархии. Разберем подробно, как работает этот механизм, проанализируем ошибки и рассмотрим правильные алгоритмы вывода.

Принцип работы автоматической группировки

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

  1. Сортировка данных: Это самое важное условие. Автогруппировка работает "на лету" в процессе вывода. Если вы выводите "Январь", затем "Февраль", а потом снова "Январь", платформа не сможет объединить их в одну группу. Данные должны идти строго последовательно.
  2. Иерархия уровней: Группировка создается только тогда, когда за строкой с уровнем N следуют строки с уровнем N + 1. Если все строки выводятся на одном уровне, никакой иерархии не возникнет.
  3. Нулевой уровень: Уровень 0 является базовым. Группировка обычно начинается с уровня 1, который подчиняется уровню 0.

Решение №1: Использование предварительно сгруппированных данных

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

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


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

// Шаг 1. Готовим список уникальных периодов для заголовков групп
ТЗ_Периоды = ТЗ.Скопировать();
ТЗ_Периоды.Свернуть("Период");
ТЗ_Периоды.Сортировать("Период Возр"); 

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

КонецЦикла;     

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

В данном примере мы четко разделяем уровни: ОбластьЗаголовок выводится на уровне 1, а ОбластьСтрока — на уровне 2. Благодаря предварительной свертке (Свернуть) и поиску строк, мы гарантируем, что для каждой даты заголовок будет выведен ровно один раз, а все данные по этой дате окажутся "внутри" него.

Решение №2: Линейный обход с контролем смены значения

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


ТЗ.Сортировать("Период Возр");
ТекущийПериод = '00010101';

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

Для каждого Строка Из ТЗ Цикл
    
    // Если период изменился — выводим новый заголовок
    Если Строка.Период <> ТекущийПериод Тогда
        ОбластьЗаголовок.Параметры.Период = Строка.Период;
        ТабДок.Вывести(ОбластьЗаголовок, 1);
        ТекущийПериод = Строка.Период;
    КонецЕсли;
    
    // Выводим детальные данные всегда на уровне 2
    ЗаполнитьЗначенияСвойств(ОбластьСтрока.Параметры, Строка);
    ТабДок.Вывести(ОбластьСтрока, 2);
    
КонецЦикла;

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

Этот метод более производителен для больших объемов данных, так как мы обходим таблицу всего один раз. Однако важно помнить: НачатьАвтогруппировкуСтрок() автоматически свяжет строки уровня 2 с последней выведенной строкой уровня 1.

Важные технические нюансы и настройки

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

Альтернатива через СКД

Как было отмечено в ходе обсуждения, многие задачи по группировке данных гораздо проще решаются через Систему Компоновки Данных (СКД). Если ваши условия отбора и группировки динамичны, рассмотрите вариант передачи вашей ТаблицыЗначений в СКД как внешний набор данных. В СКД иерархия строк настраивается в конструкторе за несколько секунд, и вам не придется вручную управлять методами Вывести() и следить за уровнями.

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

← На главную