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