При разработке отчетов на Системе компоновки данных (СКД) программисты часто сталкиваются со стандартным поведением движка: все группировки, идущие друг за другом в настройках, выводятся вертикально. Если у нас есть два совершенно независимых набора данных (например, список контрагентов и список физических лиц), СКД по умолчанию выведет их один под другим. Однако для повышения наглядности часто требуется расположить эти таблицы рядом, в горизонтальной плоскости.
В этой статье мы подробно разберем, почему СКД ведет себя именно так, и рассмотрим несколько эффективных способов решения этой задачи: от настройки схемы компоновки до программного управления выводом. Мы изучим как стандартные возможности платформы, так и "хитрости", позволяющие добиться нужного визуального результата.
Прежде чем переходить к решениям, проанализируем механику работы ПроцессораВыводаРезультатаКомпоновкиДанных. Основной алгоритм СКД ориентирован на последовательное чтение дерева настроек. Когда процессор встречает новую группировку в корне отчета, он завершает вывод предыдущей и начинает новую с новой строки. Прямой настройки "Выводить следующую группировку справа" в интерфейсе настроек не существует.
Тем не менее, существует как минимум пять способов обойти это ограничение. Разберем каждый из них по шагам.
Это один из самых изящных способов, не требующий написания сложного программного кода. Суть метода заключается в том, чтобы заставить СКД считать записи из разных наборов данных частями одной строки.
Алгоритм реализации:
НомерСтроки. В 1С это удобнее всего сделать через временные таблицы и АВТОНОМЕРЗАПИСИ() или путем соединения таблицы самой с собой по условию "больше".НомерСтроки.Проанализируем результат: СКД выведет одну таблицу. В левых колонках будут данные первого набора, в правых — второго. Если в первом наборе 10 строк, а во втором 20, то в первых десяти строках будут заполнены обе части, а в последующих десяти — только правая. Визуально это выглядит как две таблицы, расположенные вплотную друг к другу.
Этот метод позволяет использовать стандартный функционал Cross-tab (Перекрестная таблица) для имитации параллельного вывода.
Разберем по шагам:
ОБЪЕДИНИТЬ ВСЕ.ИмяТаблицы. Для записей первого набора значение будет "Таблица А", для второго — "Таблица Б".ИмяТаблицы.В этом случае поле ИмяТаблицы разнесет данные по разным горизонтальным секциям, создавая эффект двух независимых блоков данных, идущих в ряд.
Если таблицы имеют принципиально разную структуру и сложные заголовки, рассмотрим вариант с использованием макета оформления.
Мы можем создать макет табличного документа, в котором в одной строке будут определены две именованные области (например, ОбластьЛево и ОбластьПраво). В эти области программно или через настройки вложенных отчетов выводятся данные. Однако, более простым вариантом в рамках только СКД является использование вложенных схем.
В основной схеме на уровне настроек можно добавить вложенный отчет. Если правильно настроить макет основной схемы, указав расположение областей, можно добиться параллельного вывода, но этот способ считается наиболее трудозатратным в плане оформления макетов.
Когда стандартных настроек недостаточно, на помощь приходит встроенный язык. Рассмотрим ситуацию, когда нам нужно вывести две таблицы из СКД программно в один ТабличныйДокумент.
Рассмотрим пример кода:
// Создаем процессор компоновки и выводим первую таблицу
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабличныйДокумент);
// Начинаем вывод
ПроцессорВывода.НачатьВывод();
// Цикл обхода элементов результата первого набора
Пока Истина Цикл
ЭлементРезультата = ПроцессорКомпоновки.Следующий();
Если ЭлементРезультата = Неопределено Тогда
Прервать;
КонецЕсли;
ПроцессорВывода.Вывести(ЭлементРезультата);
КонецЦикла;
// Теперь нам нужно "вернуться" вверх и пристыковать вторую таблицу справа
// Для этого используется метод Присоединить(), но важно помнить,
// что он работает в контексте текущей выведенной строки.
Важный нюанс: метод ПроцессорВывода.Вывести() всегда переходит на новую строку. Чтобы вывести вторую таблицу "справа", нам придется либо формировать два отдельных табличных документа и затем объединять их построчно, либо использовать метод Присоединить() для каждой области ТабличногоДокумента.
Выясним причину, почему разработчики редко используют чистый Присоединить() с процессором вывода СКД: это требует ручного управления итератором компоновки. Более надежный программный способ — вывести две таблицы в два разных скрытых табличных документа, а затем циклом объединить их в основной отчет:
Для НомерСтроки = 1 По Макс(ТД1.ВысотаТаблицы, ТД2.ВысотаТаблицы) Цикл
ОбластьИсточник = ТД2.Область(НомерСтроки, 1, НомерСтроки, ТД2.ШиринаТаблицы);
ТД1.Область(НомерСтроки, ТД1.ШиринаТаблицы + 1).Присоединить(ОбластьИсточник);
КонецЦикла;
Если данные в ваших таблицах — это числовые показатели (ресурсы), можно попробовать расположить их в колонках, используя настройку Расположение ресурсов. В настройках СКД на вкладке "Другие настройки" установите параметр Расположение ресурсов в значение Вертикально или Горизонтально в зависимости от задачи.
Чтобы ресурсы разных наборов не перемешивались, используйте группировку по фиктивному полю (как в Способе 2). Это позволит разделить блоки ресурсов визуальным разрывом или заголовком группировки.
Мы проанализировали ситуацию и выяснили, что наиболее стабильным и "чистым" способом реализации горизонтальных таблиц в СКД без использования программирования является объединение наборов данных на уровне запроса с использованием идентификатора таблицы и порядкового номера строки. Это позволяет сохранить все преимущества СКД: расшифровки, пользовательские настройки и автоматическое оформление.
Основные выводы:
Присоединить() дает максимальный контроль, но требует написания кода в модуле объекта отчета.Рассмотрев эти подходы, вы сможете выбрать наиболее подходящий для вашей конкретной задачи, обеспечив пользователям удобный и наглядный интерфейс отчета.