При разработке отчетов в системе «1С:Предприятие 8» часто возникает ситуация, когда необходимо объединить данные из двух уже существующих и настроенных отчетов. Например, у нас есть детальный отчет по продажам контрагентам и сложный отчёт по оплатам с запутанной бизнес-логикой. Мы разберем, как объединить эти данные в одну форму, минимизируя трудозатраты на переписывание программного кода и запросов.
Рассмотрим ситуацию, когда один из отчетов настолько сложен, что копирование его запроса в новый отчет приведет к трудностям в поддержке. В этом случае мы можем использовать Набор данных — объект. Этот метод позволяет нам программно получить данные из второго отчета и передать их в основную схему компоновки. Для ускорения разработки можно взять за основу готовый шаблон отчета с выводом внешнего отчета СКД в общий табличный документ.
Проанализируем алгоритм действий:
Набор данных - объект и даем ему имя, например, ТаблицаОплат.ПриКомпоновкеРезультата, мы программно инициализируем второй отчет.ВнешниеНаборыДанных.Пример кода для реализации такого подхода в модуле объекта:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Инициализируем второй (сложный) отчет
ВнешнийОтчет = Отчеты.ОплатыКонтрагентов.Создать();
СхемаОплат = ВнешнийОтчет.СхемаКомпоновкиДанных;
НастройкиОплат = ВнешнийОтчет.КомпоновщикНастроек.ПолучитьНастройки();
// Настраиваем компоновщик макета
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаОплат, НастройкиОплат, ДанныеРасшифровки);
// Выполняем компоновку во временную таблицу значений
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
ТаблицаОплат = Новый ТаблицаЗначений;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТаблицуЗначений;
ПроцессорВывода.УстановитьОбъект(ТаблицаОплат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
// Подготавливаем внешние наборы данных для основной СКД
ВнешниеДанные = Новый Структура;
ВнешниеДанные.Вставить("ТаблицаОплат", ТаблицаОплат);
// Запускаем основную компоновку
ПроцессорКомпоновкиОсновной = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиОсновной.Инициализировать(МакетКомпоновкиДанных, ВнешниеДанные, ДанныеРасшифровки);
// Выводим результат в документ
ПроцессорВыводаОсновной = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВРезультатУвеличенный;
ПроцессорВыводаОсновной.УстановитьДокумент(ДокументРезультат);
ПроцессорВыводаОсновной.Вывести(ПроцессорКомпоновкиОсновной);
КонецПроцедуры
Выясним, существует ли штатный способ «вложить» один отчет в другой без написания кода. В системе компоновки данных предусмотрен механизм Вложенных отчетов. Это идеальный вариант, если нужно сохранить логику сложного отчета изолированной.
Рассмотрим пошагово, как это настроить:
Параметр.Контрагент вложенного отчета должен быть равен полю Контрагент основного отчета.Важный нюанс: логика сложного отчета при таком подходе остается внутри него самого, и СКД автоматически передаст нужные фильтры (контекст текущей строки основного отчета) во вложенный отчет.
Если наша задача — вывести данные по продажам и оплатам в одну общую таблицу (одной строкой по контрагенту), то лучше всего использовать Набор данных — объединение. Проанализируем, почему этот метод считается самым надежным.
В конструкторе СКД мы создаем один родительский узел типа «Объединение», а внутрь него помещаем два разных Набора данных - запрос. Один запрос выбирает продажи, второй — оплаты. Важно, чтобы поля в обоих запросах имели идентичные псевдонимы, например: Контрагент, СуммаОборот, Период. В этом случае СКД самостоятельно выполнит группировку данных, и если по одному контрагенту есть и продажи, и оплаты, они «схлопнутся» в одну строку отчета.
Рассмотрим ситуацию, когда нам нужно связать два независимых запроса по ключевому полю. Мы можем добавить в СКД два Набора данных - запрос и настроить их связь на закладке Связи наборов данных.
Однако здесь стоит учитывать технические особенности платформы 1С:
Выясним причину возможного «раздвоения» сумм при объединении сложных данных. Если мы связали продажи и оплаты, и у одного контрагента пять документов оплаты на одну реализацию, сумма реализации может суммироваться пять раз в общих итогах. Чтобы этого избежать, разберем использование функции ВычислитьВыражениеСГруппировкойМассив в ресурсах СКД. При необходимости можно ознакомиться с примерами отчетов СКД со сложными выражениями компоновки и программной обработкой.
Вместо простого Сумма(СуммаПродажи) в поле ресурса следует прописать выражение, которое сначала сгруппирует данные по уникальному идентификатору (например, по регистратору или контрагенту), а затем просуммирует их:
Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(СуммаПродажи)", "Контрагент"))
Такой подход гарантирует, что даже при наличии множественных связей, сумма по контрагенту будет учтена в общих итогах только один раз.
Проанализируем ситуацию, когда сложные запросы должны обмениваться промежуточными данными. Если мы решили все же перенести текст сложного запроса в новый отчет, мы можем использовать Менеджер временных таблиц. Это позволит нам в первом наборе данных подготовить выборку, поместить ее во временную таблицу, а во втором наборе — обратиться к ней по имени. Для этого в коде модуля необходимо инициализировать менеджер и передать его в параметры запросов СКД через КомпоновщикНастроек или напрямую в Запрос внутри набора данных.
Подводя итог, выбор метода зависит от ваших приоритетов: если важна быстрота разработки и сохранение модульности — выбирайте Вложенный отчет. Если требуется максимальная производительность и корректность итогов — используйте Набор данных — объединение с предварительной подготовкой данных.