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