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

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

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

Разберем детально, почему возникает эта проблема и как правильно настроить параметры и текст запроса в схеме компоновки данных.

Анализ проблемы: почему функция НАЧАЛОПЕРИОДА не работает в параметрах виртуальной таблицы

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


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

ОБЪЕДИНИТЬ ВСЕ

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

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

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

Пошаговое решение: настройка параметров и синтаксиса расширения СКД

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

  1. Создание отдельного параметра в схеме:

    Перейдем на вкладку «Параметры» схемы компоновки данных и добавим новый параметр с именем НачалоМесяца (тип — Дата).

  2. Настройка выражения для вычисления даты:

    В колонке «Выражение» для параметра НачалоМесяца пропишем формулу на языке выражений СКД:

    НАЧАЛОПЕРИОДА(&НачалоПериода, "МЕСЯЦ")

    Обратите внимание: в языке выражений СКД название периодичности ("МЕСЯЦ", "ДЕНЬ", "ГОД") обязательно указывается в двойных кавычках как строковый литерал.

  3. Скрытие вспомогательного параметра от пользователя:

    Установим для параметра НачалоМесяца флажок «Ограничение доступности». Это гарантирует, что пользователь отчета не увидит технический параметр в настройках, а значение будет рассчитываться автоматически на основании выбранного пользователем параметра &НачалоПериода.

  4. Использование синтаксиса расширения СКД (фигурные скобки) в запросе:

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

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

Важное замечание по значениям NULL: В операциях ОБЪЕДИНИТЬ ВСЕ для числовых полей, которые в дальнейшем будут агрегироваться функцией СУММА(), рекомендуется заменять литерал NULL на 0. Это предотвращает потенциальные ошибки при арифметических вычислениях в итоговых запросах.

Особенности работы с границами интервалов дат

Рассмотрим еще один важный нюанс: при передаче граничных дат в таблицы оборотов условие включения записей работает как Период >= НачалоПериода И Период <= КонецПериода. Если конец первого интервала точно совпадает с началом второго (например, обе границы приходятся на &НачалоПериода 00:00:00), движения, зарегистрированные ровно на эту секунду, попадут в обе выборки.

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

ДобавитьКДате(&НачалоПериода, "Секунда", -1)

Либо, если отчет формируется за дни, приводить пользовательский конец периода к концу дня через выражение КонецПериода(&КонецПериода, "День").

Альтернативные подходы к реализации отчета

В зависимости от структуры данных и требований к отчету можно применить и другие архитектурные решения в СКД:

  1. Использование виртуальной таблицы «ОстаткиИОбороты»: Вместо объединения двух таблиц оборотов можно выбрать одну таблицу ОстаткиИОбороты за весь период и рассчитывать показатели с начала месяца средствами языка выражений СКД в ресурсах или вычисляемых полях.
  2. Связи наборов данных: Создать два отдельных набора данных-запроса и связать их на вкладке «Связи наборов данных», передав вычисленные параметры периода в условия связи подчиненного набора.
  3. Вычисляемые поля СКД с условной агрегацией: Получить все записи за максимальный интервал и производить расчет нужных колонок через условные выражения в ресурсах схемы: Сумма(Выбор Когда Период < &НачалоПериода Тогда КоличествоПриход Иначе 0 Конец)
← На главную