Как в СКД вывести две таблицы рядом друг с другом?

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

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

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

Ограничение платформы СКД

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

Способ 1. Программное формирование и построчная склейка табличных документов

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

Разберем по шагам алгоритм реализации:

  1. В модуле отчета объявляем предопределенную процедуру ПриКомпоновкеРезультата и отключаем стандартную обработку: СтандартнаяОбработка = Ложь;.
  2. Программно инициализируем схему компоновки, компоновщик настроек, макет компоновки и процессор вывода.
  3. Формируем первую и вторую таблицы в два отдельных табличных документа (это могут быть две разные схемы либо две различные настройки одной схемы).
  4. Построчно соединяем полученные документы в результирующий табличный документ.
  5. Устанавливаем ширину колонок для присоединенной таблицы, так как метод Присоединить() не переносит ширину столбцов автоматически.

Посмотрим на пример программного кода, демонстрирующий базовое формирование таблицы через процессор компоновки:


// Получаем схему из макета
СхемаКомпоновкиДанных = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");

// Инициализируем настройки
КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных();
КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновкиДанных));
КомпоновщикНастроек.ЗагрузитьНастройки(СхемаКомпоновкиДанных.НастройкиПоУмолчанию);
Настройки = КомпоновщикНастроек.Настройки;

// Устанавливаем параметры отчета при необходимости
// Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Параметр1", ЗначениеПараметра1);

ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;

// Формируем макет компоновщика
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);

// Выполняем компоновку
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки);

// Выводим результат в промежуточный табличный документ
ТабДок1 = Новый ТабличныйДокумент();
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабДок1);
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);

Аналогичным образом формируем второй табличный документ — ТабДок2. Теперь объединим оба документа в итоговый ДокументРезультат, склеивая их построчно:


ДокументРезультат.Очистить();

МаксСтрок = Макс(ТабДок1.ВысотаТаблицы, ТабДок2.ВысотаТаблицы);

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

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

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

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

Способ 2. Объединение на уровне запроса без кода

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

Проанализируем этот подход по шагам:

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

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

Способ 3. Вывод в два элемента формы на управляемой форме

Если отчет предназначен исключительно для экранного анализа и не требует сквозного экспорта в один файл Excel или постраничной печати, можно решить задачу на уровне интерфейса.

Рассмотрим структуру элементов формы:

  1. На управляемой форме отчета создаем обычную группу с горизонтальной группировкой подчиненных элементов.
  2. Внутрь этой группы помещаем два элемента формы с видом Поле табличного документа (например, ТабличныйДокументЛевый и ТабличныйДокументПравый).
  3. В коде формирования отчета первая таблица выводится в левое поле, а вторая — в правое.

Такой подход обеспечивает независимую горизонтальную и вертикальную прокрутку каждой таблицы, сохраняет стандартные механизмы оформления и расшифровки 1С без сложного ручного объединения макетов.

← На главную