Как вывести два несвязанных набора данных СКД рядом по горизонтали

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

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

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

Метод 1: Искусственная нумерация и соединение по номеру строки

Самый надежный способ заставить СКД вывести данные параллельно — это создать искусственное поле связи. Разберем этот алгоритм подробнее. Если у нас есть НаборДанных1 и НаборДанных2, нам нужно пронумеровать записи в каждом из них и соединить их по этому номеру.

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


// Подготовка построителя для получения первого набора данных
ПостроительЗапроса.Выполнить();
РезультатЗапроса = ПостроительЗапроса.Результат;

ТаблицаРезультат = Новый ТаблицаЗначений;
ТаблицаРезультат.Колонки.Добавить("НомерСтрокиСвязи", Новый ОписаниеТипов("Число"));
// Добавляем колонки из первого набора
Для каждого Колонка из РезультатЗапроса.Колонки цикл
    ТаблицаРезультат.Колонки.Добавить(Колонка.Имя + "_Набор1", Колонка.ТипЗначения);    
КонецЦикла;

// Нумерация строк первого набора
Выборка = РезультатЗапроса.Выбрать();
НомерСтр = 1;
Пока Выборка.Следующий() цикл
    НоваяСтрока = ТаблицаРезультат.Добавить();
    ЗаполнитьЗначенияСвойств(НоваяСтрока, Выборка);
    НоваяСтрока.НомерСтрокиСвязи = НомерСтр;
    НомерСтр = НомерСтр + 1;
КонецЦикла;

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

Метод 2: Использование вычисляемых выражений СКД для нумерации

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

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

Важный нюанс: СКД поддерживает только левое соединение между наборами. Чтобы не потерять данные, если во втором наборе строк больше, чем в первом, рекомендуется использовать вспомогательный набор данных — «якорь», представляющий собой простую таблицу с числами от 1 до максимума. Оба рабочих набора связываются с этой таблицей левым соединением по номеру строки.

Метод 3: Программная обработка в ПриКомпоновкеРезультата

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

Выясним последовательность действий в процедуре ПриКомпоновкеРезультата:

  1. Выполняем компоновку в промежуточный ТабличныйДокумент.
  2. Используя методы Область(), Присоединить() и УдалитьОбласть(), мы находим начало второго набора данных.
  3. Копируем область второго набора и присоединяем ее справа к первому набору.
  4. Удаляем старые строки, которые теперь дублируют информацию снизу.

Проанализируем пример логики переноса:


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

Этот метод требует аккуратности с оформлением (границами, цветами), так как при копировании областей могут теряться специфические настройки форматирования.

Метод 4: Использование структуры «Таблица» в настройках СКД

Рассмотрим вариант, не требующий написания кода. В СКД можно создать структуру типа Таблица. Посмотрим, как это поможет:

  1. Добавим в оба набора данных искусственное поле ГруппаКолонок. Для первого набора заполним его значением "Документы 1", для второго — "Документы 2".
  2. В настройках СКД в «Колонки» таблицы добавим поле ГруппаКолонок.
  3. В «Строки» таблицы добавим поле НомерСтроки (рассчитанное любым из методов выше).
  4. В «Выбранные поля» добавим все необходимые реквизиты.

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

Оптимизация для больших объемов данных

Когда мы работаем с объемом в 1 миллион записей, производительность становится критическим фактором. Проанализируем основные рекомендации:

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

← На главную