Почему при использовании {&ПериодОтчета} в СКД остатки берутся на текущий момент и как это исправить?

Программист 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

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

Разбираем механизм работы фигурных скобок в СКД

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

Если в настройках компоновки данных (в пользовательских настройках или программно) значение этого параметра не будет установлено или не будет включен флаг его использования, СКД просто «вырежет» этот кусок из итогового запроса, который отправится на SQL-сервер. Для виртуальной таблицы Остатки отсутствие параметра периода означает, что данные нужно получить на самую актуальную дату, то есть на текущий момент.

Рассмотрим пример запроса, с которым возникла проблема:


ВЫБРАТЬ
    ХозрасчетныйОстатки.Субконто1 КАК Номенклатура,
    ХозрасчетныйОстатки.КоличествоОстаток КАК ОстатокБП
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки({&ПериодОтчета}, Счет = &Счет, , ) КАК ХозрасчетныйОстатки

Если мы уберем фигурные скобки, параметр &ПериодОтчета станет обязательным. В этом случае система выдаст ошибку, если значение не передано. Однако использование фигурных скобок — это стандарт гибкой разработки, и отказываться от них не стоит. Нужно лишь понять, почему значение не доходит до запроса.

Анализируем типичную ошибку программной установки параметров

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


ОСКД = ОбъектОтчет.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
ПараметрыДанныхОСКД = ОСКД.Параметры;
ЭлементПериодОтчета = ПараметрыДанныхОСКД.Найти("ПериодОтчета");
Если Не ЭлементПериодОтчета = Неопределено Тогда
    ЭлементПериодОтчета.Значение = ПериодОтчета;
КонецЕсли;

В чем заключается ошибка? Мы меняем значение в самой схеме (макете), но отчет при формировании использует Настройки (Settings), которые хранятся в КомпоновщикНастроек.Настройки.

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

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

Для того чтобы СКД «увидела» ваш параметр и корректно подставила его в виртуальную таблицу, необходимо обращаться к КомпоновщикуНастроек. Рассмотрим правильный алгоритм действий:

  1. Обращаемся к коллекции ПараметрыДанных текущих настроек компоновщика.
  2. Находим нужный параметр по имени.
  3. Устанавливаем значение и обязательно включаем флаг Использование.

Пример правильного кода:


// Установка параметра в настройках компоновщика
ПараметрПериод = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("ПериодОтчета");
Если ПараметрПериод <> Неопределено Тогда
    ПараметрПериод.Значение = КонецДня(НужнаяДата);
    ПараметрПериод.Использование = Истина;
КонецЕсли;

Если вы используете типовые отчеты или БСП, рекомендуется использовать вспомогательный метод:


КомпоновщикНастроек.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("ПериодОтчета", НужнаяДата);

Этот метод автоматически устанавливает значение и включает признак использования параметра.

Работа с типом «Граница» для точных остатков

Выясним еще одну важную причину, почему остатки могут казаться «неверными». В 1С остатки на дату 31.03.2024 23:59:59 не включают движения, сделанные ровно в эту секунду, если не использовать специальный объект Граница.

Если ваша задача — получить остатки, включающие все документы на конец дня, проанализируем использование объекта Граница. Программно это выглядит так:


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

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

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

Это выражение сдвигает границу на начало следующего дня, что гарантирует включение всех документов последнего дня периода.

Проверка настроек в конструкторе СКД

Посмотрим на настройки в самом конструкторе схемы компоновки данных. Бывает, что даже при правильном коде параметр не подхватывается. Проверьте следующие моменты:

Резюме

Подведем итог. Если вы используете {&ПериодОтчета} и получаете остатки на текущий момент, проанализируйте свой код и настройки отчета по следующим пунктам:

  1. Где устанавливается значение? Всегда устанавливайте параметры в КомпоновщикНастроек.Настройки.ПараметрыДанных, а не в самой схеме.
  2. Включено ли использование? Убедитесь, что Использование = Истина для данного параметра.
  3. Как передается дата? Используйте КонецДня или объект Граница для включения документов последней секунды.
  4. Консоль запросов: Помните, что обычная консоль запросов не имитирует поведение СКД на 100%. Фигурные скобки в консоли могут обрабатываться иначе, чем в реальном механизме компоновки данных.

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

← На главную