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

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

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

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

Метод 1: Использование промежуточной таблицы значений и макета

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

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


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    ДокументРезультат.Очистить();
    
    // 1. Получаем настройки и инициализируем компоновщик макета
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    
    // Важно: используем тип генератора для коллекции значений
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки, , 
        Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
    
    // 2. Инициализируем процессор компоновки
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
    
    // 3. Выгружаем результат в Таблицу Значений
    ТЗ = Новый ТаблицаЗначений;
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
    ПроцессорВывода.УстановитьОбъект(ТЗ);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
    // 4. Формируем финальный табличный документ из макета
    Макет = ПолучитьМакет("МакетТабличногоДокумента");
    КоличествоПолВыборки = Цел((ТЗ.Количество() - 1) / 2); // Находим середину
    
    Для НомерСтроки = 0 По КоличествоПолВыборки Цикл
        
        // Выводим левую колонку
        ТекСтрокаЛево = ТЗ[НомерСтроки];
        Область = Макет.ПолучитьОбласть("Строка");
        Область.Параметры.Заполнить(ТекСтрокаЛево);
        ДокументРезультат.Вывести(Область);
        
        // Выводим правую колонку (присоединяем к текущей строке)
        ИндексПравойСтроки = НомерСтроки + КоличествоПолВыборки + 1;
        Если ИндексПравойСтроки < ТЗ.Количество() Тогда
            ТекСтрокаПраво = ТЗ[ИндексПравойСтроки];
            Область = Макет.ПолучитьОбласть("Строка");
            Область.Параметры.Заполнить(ТекСтрокаПраво);
            ДокументРезультат.Присоединить(Область);
        КонецЕсли;
        
    КонецЦикла;

КонецПроцедуры

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

Метод 2: Построчный вывод через Процессор Компоновки (без ТЗ)

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

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

  1. Инициализируем ПроцессорКомпоновкиДанных стандартным образом.
  2. В цикле вызываем ПроцессорКомпоновки.Следующий().
  3. Сохраняем элементы результата в массив.
  4. Как только мы набрали нужное количество элементов для «половины» страницы, начинаем процесс вывода, используя методы Вывести() и Присоединить().

Этот способ сложнее в реализации индексов, но гораздо стабильнее работает с большими отчетами.

Метод 3: «Разрезание» готового табличного документа

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

  1. Выводим отчет в промежуточный (скрытый) ТабличныйДокумент стандартным образом.
  2. Определяем общее количество строк в документе через свойство ВысотаТаблицы.
  3. Разделяем высоту пополам.
  4. Создаем основной ДокументРезультат.
  5. В цикле берем область из левой части (строки от 1 до N/2) и присоединяем к ней область из правой части (строки от N/2 + 1 до N).

Для копирования данных используем метод Область() с указанием координат, например: ТабличныйДокумент.Область(1, 1, Высота, Ширина).

Метод 4: Вычисляемые поля и группировки колонок

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

Алгоритм действий:

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

Важные нюансы при работе с макетами

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

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

← На главную