Как в СКД вывести в один отчет данные из разных несвязанных запросов

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

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

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

Причина проблемы: особенности работы компоновщика с наборами данных

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

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

Тем не менее решить задачу в рамках СКД можно несколькими путями в зависимости от требований к внешнему виду отчета.

Способ 1. Несколько наборов данных и независимые структуры в настройках

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

Разберем по шагам порядок настройки схемы:

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

Способ 2. Объединение разнородных данных в единый запрос

Если требуется свести показатели в одну таблицу или управлять порядком их вывода через единую структуру группировок, мы можем объединить запросы на уровне SQL с помощью конструкции ОБЪЕДИНИТЬ ВСЕ.

Рассмотрим пример построения такого запроса:


ВЫБРАТЬ
    "1. Клиенты" КАК РазделОтчета,
    Залогодатели.Ссылка КАК Аналитика,
    Залогодатели.ВесЗолота КАК Количество,
    0 КАК Сумма
ИЗ
    Справочник.Залогодатели КАК Залогодатели

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    "2. Касса",
    Кассы.Наименование,
    0,
    Остатки.СуммаОстаток
ИЗ
    РегистрНакопления.ДенежныеСредства.Остатки(&Период, ) КАК Остатки
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Кассы КАК Кассы
        ПО Остатки.Касса = Кассы.Ссылка

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    "3. Поступления",
    Приход.СтатьяДвиженияДенежныхСредств.Наименование,
    0,
    Приход.Сумма
ИЗ
    Документ.ПриходныйКассовыйОрдер КАК Приход
ГДЕ
    Приход.Дата МЕЖДУ &НачалоПериода И &КонецПериода

В таком подходе мы искусственно приводим разнородные таблицы к единому составу колонок:

  1. Поле РазделОтчета выступает классификатором строк и используется в настройках как основная группировка первого уровня.
  2. Поле Аналитика содержит названия клиентов, касс или статей.
  3. Для числовых колонок задаются ресурсы на вкладке Ресурсы с функцией Сумма(). Для тех веток, где показатель не имеет смысла, в запросе подставляется числовой ноль.

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

Способ 3. Передача сводных скалярных значений через параметры

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

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

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

Способ 4. Программный вывод через процедуру ПриКомпоновкеРезультата

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

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

Откроем модуль объекта отчета и переопределим стандартное событие ПриКомпоновкеРезультата:


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

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

Таким образом, для вывода несвязанных данных можно использовать как полностью декларативный подход (несколько наборов данных с независимыми ветками группировок без полей в корне), так и программную компоновку с ручным заполнением итогового табличного документа.

← На главную