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