Как программно объединить несколько колонок в группу в отчете на СКД?

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

При разработке сложных отчетов в Системе компоновки данных (СКД) часто возникает необходимость динамического формирования колонок. Например, когда количество периодов (месяцев или кварталов) заранее неизвестно и зависит от выбранного пользователем интервала. В таких случаях мы создаем поля программно, но стандартный вывод "в ряд" не всегда удобен для чтения. Чтобы сделать отчет профессиональным, необходимо объединять связанные показатели (например, «Остаток», «Себестоимость» и «Сумма») под общим заголовком периода. В этой статье мы подробно разберем, как реализовать программное создание колонок-групп.

Постановка задачи и анализ ситуации

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

Способ 1: Использование Группы выбранных полей (в настройках)

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

Рассмотрим пошагово процесс создания такой структуры в цикле:


// Предположим, у нас есть количество периодов в переменной КолПериодов
Для Сч = 1 По КолПериодов Цикл
    
    // 1. Создаем общую группу для текущего периода в настройках СКД
    ИмяГруппы = "Период " + Формат(Сч, "ЧГ=0");
    ГруппаПолей = НастройкиСКД.Выбор.Элементы.Добавить(Тип("ГруппаВыбранныхПолейКомпоновкиДанных"));
    ГруппаПолей.Заголовок = ИмяГруппы;
    
    // КРИТИЧЕСКИ ВАЖНО: устанавливаем горизонтальное расположение, 
    // чтобы вложенные поля шли слева направо под общим заголовком
    ГруппаПолей.Расположение = РасположениеПоляКомпоновкиДанных.Горизонтально;
    ГруппаПолей.Использование = Истина;

    // 2. Добавляем поля в набор данных схемы (если они не были добавлены ранее)
    // Поле "Остаток"
    ИмяПоляОстаток = "Остаток_" + Сч;
    ПолеНабора = СхемаКомпоновкиДанных.НаборыДанных.НаборДанных1.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
    ПолеНабора.ПутьКДанным = ИмяПоляОстаток;
    ПолеНабора.Поле = ИмяПоляОстаток;
    ПолеНабора.Заголовок = "Остаток";

    // 3. Добавляем созданное поле именно ВНУТРЬ ГруппыПолей, а не в корень Выбора
    ВыбранноеПоле = ГруппаПолей.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
    ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных(ИмяПоляОстаток);
    ВыбранноеПоле.Использование = Истина;
    
    // Повторяем для других колонок (Себестоимость, Сумма...)
    // ...
КонецЦикла;

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

Варианты расположения полей в группе

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

  1. Горизонтально: Стандартный вариант для создания общих шапок. Поля располагаются в ряд, а заголовок группы "растягивается" над ними.
  2. Вертикально: Поля выводятся друг под другом. Это крайне полезно для экономии места. Например, можно вывести «Сумму» и «Количество» в одной узкой колонке, где одно значение будет над другим.
  3. Вместе: Система попытается вывести значения в одну ячейку через разделитель (запятую). Часто используется для контактной информации или адресов.
  4. Авто: Поведение определяется платформой автоматически, чаще всего совпадает с горизонтальным.

Способ 2: Создание папок в наборе данных

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

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


ИмяПапки = "ДанныеПродаж";
Папка = СхемаКомпоновкиДанных.НаборыДанных.НаборДанных1.Поля.Добавить(Тип("ПапкаПолейНабораДанныхСхемыКомпоновкиДанных"));
Папка.Заголовок = "Продажи за период";
Папка.ПутьКДанным = ИмяПапки;

// Добавляем поле внутрь
Поле = СхемаКомпоновкиДанных.НаборыДанных.НаборДанных1.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
Поле.Заголовок = "Сумма выручки";
// Путь должен включать имя папки через точку!
Поле.ПутьКДанным = ИмяПапки + ".Сумма"; 
Поле.Поле = "Сумма";

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

Программная работа с ресурсами

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

Посмотрим на пример добавления ресурса:


ПолеРесурса = СхемаКомпоновкиДанных.ПоляИтога.Добавить();
ПолеРесурса.ПутьКДанным = ИмяКолонки; // Должно совпадать с ПутьКДанным поля набора
ПолеРесурса.Выражение = "Сумма(" + ИмяКолонки + ")";

Обратите внимание, что для некоторых показателей (например, "Себестоимость" или "Цена") логичнее использовать выражение "Среднее(" + ИмяКолонки + ")" или "Максимум(...)".

Очистка настроек перед формированием

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


// Очищаем выбранные поля, чтобы не было дублей при повторном формировании
КомпоновщикНастроек.Настройки.Выбор.Элементы.Очистить();

// Также стоит проверить, не нужно ли очистить ресурсы в самой схеме, 
// если схема создается/модифицируется динамически
СхемаКомпоновкиДанных.ПоляИтога.Очистить();
СхемаКомпоновкиДанных.НаборыДанных.НаборДанных1.Поля.Очистить();

Нюансы для кросс-таблиц

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

В такой ситуации нам потребуется найти нужную группировку в структуре настроек:


// Ищем группировку колонок в таблице
ГруппировкаКолонок = НастройкиСКД.Структура[0].Колонки[0]; // Примерный путь
// Добавляем группу полей именно в выбор этой группировки
ГруппаПолей = ГруппировкаКолонок.Выбор.Элементы.Добавить(Тип("ГруппаВыбранныхПолейКомпоновкиДанных"));

Заключение

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

← На главную