Как передать дату документа в параметр запроса виртуальной таблицы в 1С:СКД?

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

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

Анализ проблемы: почему стандартное соединение не работает

Разберем типичную ситуацию, с которой столкнулся автор темы. В запросе делается попытка соединить таблицу документов с виртуальной таблицей остатков. Проблема в том, что параметры виртуальных таблиц (такие как &ДатаПлана) вычисляются единожды перед выполнением всего запроса. Если в отчет попадает несколько документов с разными датами, система не сможет «подставить» свою дату для каждой строки автоматически через обычное левое соединение.

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


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

Здесь параметр &ДатаПлана является статичным для всего результирующего набора. Если нам нужно получить остатки на дату конкретного документа (через поле Ссылка), мы должны использовать механизмы СКД или изменить структуру запроса.

Решение №1: Использование фигурных скобок в СКД

Одним из ключевых моментов в СКД является механизм расширения языка запросов. Чтобы система компоновки данных могла гибко управлять параметрами и отборами, используются фигурные скобки {}. Как справедливо отмечено в обсуждении, это «самое главное» для корректной работы параметров в виртуальных таблицах.

Рассмотрим исправленный вариант запроса для отчета по конкретному документу:


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

В данном случае, когда мы указываем {&ДатаОстатков}, мы даем СКД возможность перехватить этот параметр. Если мы установим значение &ДатаОстатков в настройках отчета или программно, СКД подставит его в подзапрос получения остатков. Это работает хорошо, если мы формируем отчет по одному конкретному документу, переданному через параметр &Ссылка.

Решение №2: Связи наборов данных (для списка документов)

Выясним причину, почему предыдущий способ не подходит для списка документов с разными датами. Если документов много, параметр остатков все равно будет один на всех. В этом случае нам поможет самый мощный механизм СКД — Связи наборов данных. Проанализируем пошаговый алгоритм решения:

  1. Создадим два набора данных:
    • НаборДанных1 (Запрос): Выбираем данные из документа ПланЗакупок (Номенклатура, ДатаПланирования, Ссылка).
    • НаборДанных2 (Запрос): Выбираем остатки из виртуальной таблицы ТоварыНаСкладах.Остатки(&Период, ). В параметре указываем стандартное имя &Период.
  2. Настроим связь:
    • Перейдем на закладку "Связи наборов данных".
    • Источник связи: НаборДанных1, Приемник: НаборДанных2.
    • Условие связи: Номенклатура = Номенклатура.
    • Параметры связи: В колонке "Параметр" выбираем Период, а в колонке "Выражение источника" выбираем ДатаПланирования из первого набора.

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

Важный нюанс: Момент времени и Граница

Проанализируем ситуацию, когда остатки выводятся некорректно. Часто программисты жалуются, что остатки «не видят» движения самого документа. Рассмотрим, почему это происходит:

Если в параметр &ДатаОстатков передать просто дату документа (например, 01.01.2023 12:00:00), 1С получит остатки на начало этой секунды. Движения документа, сделанные в эту же самую секунду, не будут включены в результат.

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


Выражение для параметра &ДатаОстатков:
ДОБАВИТЬКДАТЕ(КонецПериода(&ДатаДокумента, "Секунда"), "Секунда", 1)

Или, если используется программная установка значений:


Параметр = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("ДатаОстатков");
Параметр.Значение = Новый Граница(ВыбраннаяДата, ВидГраницы.Включая);
Параметр.Использование = Истина;

Заключение

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

Помните, что работа с виртуальными таблицами требует понимания того, как платформа 1С транслирует ваш запрос в SQL. Использование связей наборов данных порождает множество мелких запросов к базе, поэтому всегда ограничивайте выборку данных в наборе-источнике (например, по периоду или конкретной ссылке), чтобы сохранить высокую производительность вашего отчета.

← На главную