Как вывести данные из табличной части документа и соединить их с информацией из регистра накопления в отчете на СКД?

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

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

Мы вместе пройдем по шагам создания запроса для СКД, который позволит нам объединить строки табличной части документа с соответствующими записями регистра накопления. Выясним основные принципы построения таких запросов для быстрого анализа данных и рассмотрим различные нюансы, которые могут возникнуть в процессе разработки.

Понимание структуры данных и проблемы

Прежде чем перейти к решению (изучив информер по метаданным), нам важно понимать, с какой проблемой мы сталкиваемся. В типовом отчете, построенном на основе документа, данные из шапки документа часто повторяются для каждой строки табличной части. Наша цель — вывести каждую строку табличной части как отдельную запись отчета, дополненную связанной информацией из регистров.

Например, если у нас есть документ РеализацияТоваровУслуг с табличной частью Товары, содержащей поля Номенклатура, Количество, Сумма и СерияНоменклатуры, и нам необходимо к каждой строке этой табличной части добавить Себестоимость из РегистрНакопления.Себестоимость. Нам нужно будет построить такой запрос, который корректно свяжет эти два источника данных.

Основные принципы, которыми мы будем руководствоваться:

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

Шаг 1: Формирование основного запроса к табличной части документа

Начнем с самого простого — получения данных непосредственно из табличной части документа, в чем может помочь ИИ-помощник для задач 1С. В СКД это делается путем создания нового набора данных типа "Запрос". В конструкторе запросов или вручную мы обращаемся к табличной части через ссылку на документ.

Предположим, наш документ называется Документ.РеализацияТоваровУслуг, а его табличная часть — Товары. Мы можем выбрать все необходимые поля из этой табличной части.


ВЫБРАТЬ
    РеализацияТоваровУслугТовары.Ссылка КАК СсылкаДокумента,
    РеализацияТоваровУслугТовары.Номенклатура КАК Номенклатура,
    РеализацияТоваровУслугТовары.Количество КАК Количество,
    РеализацияТоваровУслугТовары.Сумма КАК Сумма,
    РеализацияТоваровУслугТовары.СерияНоменклатуры КАК СерияНоменклатуры
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары

В этом запросе мы получаем базовые сведения о каждой строке табличной части. Поле Ссылка из табличной части является ссылкой на сам документ, что очень удобно для последующего соединения с другими таблицами или регистрами, если потребуется получить данные из шапки документа или выполнить дальнейшую детализацию.

Шаг 2: Присоединение данных из регистра накопления

Теперь, когда у нас есть базовые данные из табличной части, нам нужно присоединить к ним информацию о себестоимости из регистра накопления РегистрНакопления.Себестоимость. Здесь есть несколько важных моментов, которые мы должны учесть:

  1. Тип соединения: Чаще всего используется ЛЕВОЕ СОЕДИНЕНИЕ. Это гарантирует, что все строки из нашей табличной части (левой таблицы) попадут в отчет, даже если для них не найдется соответствующая запись в регистре накопления. В этом случае поле себестоимости будет иметь значение NULL, которое мы можем обработать функцией ЕСТЬNULL.
  2. Виртуальные таблицы регистров: Для получения актуальных данных из регистров накопления на определенный момент времени (например, на дату документа или на период отчета), нам необходимо использовать виртуальные таблицы, такие как Остатки, Обороты или ОстаткиИОбороты. Эти таблицы позволяют нам "срезать" данные по периоду и измерениям.
  3. Условия соединения: Важно правильно указать условия соединения. Как правило, это измерения регистра, которые совпадают с реквизитами табличной части документа (например, Номенклатура) и, возможно, ссылку на документ-регистратор.

Рассмотрим пример запроса, который присоединяет себестоимость из виртуальной таблицы РегистрНакопления.Себестоимость.Обороты:


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

В этом запросе мы сделали несколько важных уточнений:

  1. Мы использовали РегистрНакопления.Себестоимость.Обороты(...), что позволяет нам получить обороты (движения) за определенный период.
  2. Параметры виртуальной таблицы &НачалоПериода и &КонецПериода должны быть определены в СКД. Мы можем установить им значения по умолчанию (например, дату документа для НачалоПериода и конец дня даты документа для КонецПериода), чтобы получать себестоимость на момент проведения документа.
  3. В условиях соединения мы добавили не только Регистратор, но и Номенклатура. Это обеспечивает более точное сопоставление данных, так как нам нужна себестоимость конкретной номенклатуры из конкретного документа.
  4. Функция ЕСТЬNULL(СебестоимостьОбороты.СуммаОборот, 0) гарантирует, что если для какой-то номенклатуры себестоимость не будет найдена, в отчете будет показан 0, а не пустое значение.

Важный нюанс: Если регистр себестоимости содержит дополнительные измерения (например, ХарактеристикаНоменклатуры, Серия), то их также необходимо включать в условия соединения для получения максимально точных данных. Например, если в регистре есть серия, а в ТЧ документа есть серия, то условие должно быть:


ПО РеализацияТоваровУслугТовары.Ссылка = СебестоимостьОбороты.Регистратор
И РеализацияТоваровУслугТовары.Номенклатура = СебестоимостьОбороты.Номенклатура
И РеализацияТоваровУслугТовары.СерияНоменклатуры = СебестоимостьОбороты.Серия

Шаг 3: Настройка параметров СКД для периода

Для корректной работы с виртуальными таблицами регистров нам обязательно нужно объявить параметры &НачалоПериода и &КонецПериода в схеме компоновки данных. Эти параметры затем можно будет использовать в пользовательских настройках отчета.

  1. В режиме редактирования схемы СКД перейдите на вкладку Параметры.
  2. Добавьте новые параметры: НачалоПериода и КонецПериода.
  3. Установите для них тип Дата.
  4. Настройте свойства этих параметров:

Если нам нужна себестоимость именно на дату документа, мы можем добавить параметр &ДатаДокумента в СКД и установить его значение из поля РеализацияТоваровУслуг.Дата. Тогда параметры виртуальной таблицы оборотов будут выглядеть так:


ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Себестоимость.Обороты(
    &ДатаДокумента,
    ДОБАВИТЬКДАТЕ(&ДатаДокумента, ДЕНЬ, 1), // Конец дня документа
    Регистратор,
    Номенклатура = РеализацияТоваровУслугТовары.Номенклатура
) КАК СебестоимостьОбороты

Такой подход гарантирует, что себестоимость будет рассчитана точно на момент проведения документа, исключая влияние последующих движений.

Шаг 4: Использование временных таблиц для сложных сценариев и оптимизации

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

Принцип работы с временными таблицами в СКД следующий:

  1. Мы формируем первый запрос, результат которого помещаем во временную таблицу (с помощью оператора ПОМЕСТИТЬ).
  2. Затем мы создаем второй запрос, который обращается к этой временной таблице и выполняет дальнейшие соединения или выборки.

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


// Запрос 1: Получаем данные из табличной части и помещаем во временную таблицу
ВЫБРАТЬ
    ТЧ.Ссылка КАК СсылкаДокумента,
    ТЧ.Номенклатура КАК Номенклатура,
    ТЧ.Количество КАК Количество,
    ТЧ.Сумма КАК Сумма,
    ТЧ.СерияНоменклатуры КАК СерияНоменклатуры
ПОМЕСТИТЬ ВТ_ТоварыДокумента
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК ТЧ
;

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

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

  1. Разделение логики: Запрос становится более модульным и понятным. Отдельные шаги обработки данных видны явно.
  2. Улучшение производительности: В некоторых случаях СУБД может более эффективно оптимизировать выполнение запросов с временными таблицами, особенно если результаты промежуточных выборок используются несколько раз.
  3. Фильтрация и предварительная обработка: Вы можете отфильтровать или сгруппировать данные в первой временной таблице, прежде чем выполнять сложные соединения.

Обратите внимание, что при использовании нескольких запросов с временными таблицами в одном наборе данных СКД, они должны быть разделены точкой с запятой (;), как показано в примере.

Шаг 5: Настройка полей и группировок в СКД

После того как запрос к данным готов, нам необходимо правильно настроить поля и структуру отчета в СКД:

  1. Перейдите на вкладку Наборы данных в схеме СКД и убедитесь, что все необходимые поля (СсылкаДокумента, Номенклатура, Количество, Сумма, СерияНоменклатуры, Себестоимость) выбраны и имеют корректные типы. При необходимости настройте синонимы для более понятного отображения в отчете.
  2. На вкладке Настройки мы определяем структуру нашего отчета. Если нам нужен детализированный список по строкам табличной части, мы можем создать простую таблицу. Добавьте выбранные поля в раздел Выбранные поля.
  3. Если нам нужно сгруппировать данные (например, по документу, а затем по номенклатуре), мы можем добавить группировки. Например, сначала по СсылкаДокумента, а затем по Номенклатура. Однако в нашем случае, где целью является детализация по каждой строке табличной части, основные группировки могут быть не нужны, и мы просто выводим поля как детальные записи.
  4. Убедитесь, что для числовых полей (Количество, Сумма, Себестоимость) правильно установлены функции агрегирования, если вы используете группировки. Для детальных записей агрегация не требуется.

Заключение и полезные советы

Мы рассмотрели ключевые подходы к получению данных из табличных частей документов и их соединению с информацией из регистров накопления в отчетах на СКД. Правильное построение запроса с использованием ЛЕВОГО СОЕДИНЕНИЯ, виртуальных таблиц регистров с параметрами периода и, при необходимости, временных таблиц, позволяет нам создавать гибкие и точные отчеты.

Несколько дополнительных советов:

Следуя этим рекомендациям, вы сможете создавать мощные и информативные отчеты на СКД, которые точно отвечают потребностям бизнеса.

← На главную