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

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

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

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

Способ 1. Автоматическое заполнение параметра через выражения СКД

Рассмотрим простейшую ситуацию: у вас есть параметр &ВыбДокумент и параметр &ДатаАнализа. Вы хотите, чтобы при выборе документа в &ДатаАнализа подставлялась его дата. Это позволит виртуальным таблицам (например, ЦеныНоменклатуры.СрезПоследних) автоматически использовать дату этого документа.

Для реализации этого метода выполним следующие шаги в конструкторе СКД:

  1. Перейдем на закладку Параметры.
  2. Найдем параметр ДатаАнализа.
  3. В колонке Выражение пропишем логику получения даты. Важно учитывать, что тип параметра &ВыбДокумент может быть составным, поэтому лучше использовать явное приведение типа.

Пример выражения для параметра:


ВЫБОР 
    КОГДА &ВыбДокумент = ЗНАЧЕНИЕ(Документ.ИнвентаризацияТоваров.ПустаяСсылка) 
    ТОГДА &ТекущаяДата 
    ИНАЧЕ ВЫРАЗИТЬ(&ВыбДокумент КАК Документ.ИнвентаризацияТоваров).Дата 
КОНЕЦ

Важный нюанс: Чтобы пользователь не путался, для параметра ДатаАнализа рекомендуется установить флаг Ограничение доступности. В этом случае система сама вычислит дату, и пользователю не придется вводить ее вручную. Если вы используете УТ 11, помните, что обращение через точку (.Дата) к реквизиту объекта в выражениях параметров работает корректно, если объект выбран.

Способ 2. Получение цен для списка документов (Срез последних на каждую дату)

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

Рассмотрим решение через связи наборов данных. Это наиболее "чистый" и производительный способ в СКД.

Разберем алгоритм настройки:

  1. Создадим первый набор данных (Запрос): Назовем его НаборДанныхДокументы. Здесь мы выбираем наши документы (например, Инвентаризации) и их даты.
    
    ВЫБРАТЬ
        Инвентаризация.Ссылка КАК Документ,
        Инвентаризация.Дата КАК ДатаДокумента,
        Инвентаризация.Номенклатура КАК Товар
    ИЗ
        Документ.ИнвентаризацияТоваров КАК Инвентаризация
    ГДЕ
        Инвентаризация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
    
  2. Создадим второй набор данных (Запрос): Назовем его НаборДанныхЦены. В нем обратимся к срезу последних цен.
    
    ВЫБРАТЬ
        Цены.Номенклатура КАК Номенклатура,
        Цены.Цена КАК ЦенаЗакупа
    ИЗ
        РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ПериодЦен, ВидЦены = &ВидЦен) КАК Цены
    
    Обратите внимание: Мы используем параметр &ПериодЦен, который позже свяжем с датой из первого набора.
  3. Настроим связи: Перейдем на закладку Связи наборов данных.
    • Источник связи: НаборДанныхДокументы
    • Приемник связи: НаборДанныхЦены
    • Условие связи: Товар = Номенклатура
    • Параметры: В колонке "Параметры" для связи укажем, что в параметр ПериодЦен передается поле ДатаДокумента.

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

Способ 3. Реализация через левое соединение в одном запросе

Если вы предпочитаете использовать один запрос (например, для оптимизации при очень больших объемах данных), можно применить классический прием "Срез последних на языке запросов". Выясним, как это работает.

Сначала мы выбираем документы, затем соединяем их с регистром сведений по условию Регистр.Период <= Документ.Дата. Чтобы получить именно последнюю запись, нам нужно найти максимум периода для каждой пары "Документ + Номенклатура".

Пример структуры такого запроса:


ВЫБРАТЬ
    Док.Ссылка КАК Документ,
    Док.Номенклатура КАК Номенклатура,
    МАКСИМУМ(Цены.Период) КАК ПериодДляЦены
ПОМЕСТИТЬ ВТ_МаксимальныеДаты
ИЗ
    Документ.ИнвентаризацияТоваров КАК Док
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК Цены
    ПО Док.Номенклатура = Цены.Номенклатура
    И Цены.Период <= Док.Дата
ГРУППИРОВАТЬ ПО
    Док.Ссылка,
    Док.Номенклатура;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ.Документ,
    ЦеныСрез.Цена
ИЗ
    ВТ_МаксимальныеДаты КАК ВТ
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК ЦеныСрез
    ПО ВТ.Номенклатура = ЦеныСрез.Номенклатура
    И ВТ.ПериодДляЦены = ЦеныСрез.Период

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

Особенности для конфигурации Управление торговлей 11

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

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

{ГДЕ (ВидЦены = &ВидЦены)}

Использование функций общих модулей в параметрах

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

ОбщегоНазначенияКлиентСервер.КонецДня(ВЫРАЗИТЬ(&ВыбДокумент КАК Документ.ИнвентаризацияТоваров).Дата)

Это дает огромную гибкость при настройке автоматического поведения отчета без написания сложного кода в модуле формы.

Резюме

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

← На главную