Почему СКД выводит только первую строку табличной части и как это исправить?

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

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

Разбор основной ошибки: Обращение к табличной части через точку

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

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

Проанализируем пример кода, который приводит к ошибке:


ВЫБРАТЬ
    CGU_ПартииТоваровНаСкладахОстаткиИОбороты.Склад.Наименование КАК НаименованиеСклада,
    Склады.КонстантыОборота.(
        Наименование,
        ОборЗаДень,
        НензЗалДесятьДней
    ) КАК Константы
ИЗ
    РегистрНакопления.CGU_ПартииТоваровНаСкладах2.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Авто, , ) КАК CGU_ПартииТоваровНаСкладахОстаткиИОбороты
        ПОЛНОЕ СОЕДИНЕНИЕ Справочник.Склады КАК Склады
        ПО CGU_ПартииТоваровНаСкладахОстаткиИОбороты.Склад = Склады.Ссылка

В данном случае поле Константы является вложенной таблицей. Чтобы отчет заработал корректно, нам необходимо отказаться от обращения через точку и перейти к явному соединению с таблицей табличной части.

Решение №1: Прямое соединение с таблицей табличной части

Для того чтобы каждая строка табличной части стала отдельной строкой в результате запроса, мы должны соединяться не с самим справочником, а с его вложенной таблицей. В структуре метаданных 1С табличные части хранятся как отдельные таблицы с именем ИмяСправочника.ИмяТабличнойЧасти.

Разберем, как должен выглядеть исправленный запрос:


ВЫБРАТЬ
    CGU_ПартииТоваровНаСкладахОстаткиИОбороты.Номенклатура.Наименование,
    CGU_ПартииТоваровНаСкладахОстаткиИОбороты.Склад,
    СкладыКонстантыОборота.Наименование КАК КонстантаНаименование,
    СкладыКонстантыОборота.ОборЗаДень КАК ОборЗаДень,
    СкладыКонстантыОборота.НензЗалДесятьДней КАК НензЗалДесятьДней
ИЗ
    РегистрНакопления.CGU_ПартииТоваровНаСкладах2.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Авто, , ) КАК CGU_ПартииТоваровНаСкладахОстаткиИОбороты
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Склады.КонстантыОборота КАК СкладыКонстантыОборота
        ПО CGU_ПартииТоваровНаСкладахОстаткиИОбороты.Склад = СкладыКонстантыОборота.Ссылка
        И CGU_ПартииТоваровНаСкладахОстаткиИОбороты.Номенклатура = СкладыКонстантыОборота.Наименование

Важные моменты:

  1. Вместо Справочник.Склады мы выбираем Справочник.Склады.КонстантыОборота.
  2. Соединение происходит по полю Ссылка табличной части (которое указывает на сам Склад) и по полю, связывающему строку ТЧ с конкретным товаром.
  3. Мы используем ЛЕВОЕ СОЕДИНЕНИЕ. Это гарантирует, что если в табличной части склада нет данных для товара, сам товар с его остатками все равно попадет в отчет.

Решение №2: Исправление связей по полям (Ссылка vs Наименование)

Часто программисты допускают еще одну ошибку — соединяют таблицы по строковым наименованиям. Например: Номенклатура.Наименование = СкладыКонстантыОборота.Наименование.Наименование. Рассмотрим, почему это плохо.

Проанализируем риски:

Посмотрим на правильный способ установки связи в запросе:


ПО CGU_ПартииТоваровНаСкладахОстаткиИОбороты.Номенклатура = СкладыКонстантыОборота.ТоварСсылка

Где ТоварСсылка — это реквизит табличной части типа СправочникСсылка.Номенклатура.

Решение №3: Использование связей наборов данных в СКД

Если запрос становится слишком громоздким из-за множества ПОЛНОЕ СОЕДИНЕНИЕ, рекомендуется разделить его на два независимых набора данных. Рассмотрим этот алгоритм:

  1. Создаем НаборДанных1 (Запрос), где получаем остатки и обороты из регистров.
  2. Создаем НаборДанных2 (Запрос), где выбираем данные только из табличной части справочника Склады.
  3. Переходим на вкладку «Связи наборов данных».
  4. Указываем НаборДанных1 как источник, а НаборДанных2 как приемник.
  5. В колонках «Условие связи» выбираем Склад и Номенклатура в обоих наборах.

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

Особенности настройки ресурсов

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

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

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

← На главную