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

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

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

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

Способ 1. Использование встроенного языка выражений СКД (Базовый метод)

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

Давайте пошагово разберем, как настроить такую схему:

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

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

Функция ТекущаяДата() возвращает время того компьютера, на котором выполняется код. В клиент-серверном варианте работы этот код выполняется на сервере приложений 1С. Если сервер физически находится в Москве (часовой пояс UTC+3), а пользователь запускает отчет во Владивостоке (часовой пояс UTC+10), то функция ТекущаяДата() вернет московское время. В результате отчет для пользователя сформируется некорректно — со сдвигом на 7 часов назад.

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

Правильное выражение для СКД будет выглядеть следующим образом:

КонецПериода(ТекущаяДатаСеанса(), "День")

Данная формула вернет значение ДАТА 23:59:59 для текущих суток пользователя, вне зависимости от того, где физически расположен сервер баз данных.

Способ 2. Решение проблемы «последней секунды» для виртуальных таблиц остатков

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

Допустим, мы строим отчет по остаткам товаров на складах. Если мы передадим в параметр виртуальной таблицы остатков СКД значение 31.12.2023 23:59:59, то система построит срез остатков на начало этой секунды. Это означает, что все приходные или расходные документы, которые были записаны и проведены ровно в секунду 23:59:59, **не войдут** в расчет остатков в этом отчете. Мы получим искаженные данные.

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

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

Вариант со смещением на секунду вперед:

ДобавитьКДате(КонецПериода(ТекущаяДатаСеанса(), "День"), "Секунда", 1)

Вариант с прибавлением дня и получением его начала:

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

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

Способ 3. Использование связанного параметра типа «Стандартный период»

Еще один удобный интерактивный способ автоматического заполнения параметров — использование механизма стандартных периодов платформы 1С. Этот метод позволяет элегантно связать пользовательский выбор периода с техническими параметрами запроса.

Проанализируем этот сценарий по шагам:

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

    &ПериодОтчета.ДатаОкончания

Платформа 1С спроектирована таким образом, что при извлечении свойства ДатаОкончания из объекта СтандартныйПериод, система автоматически приводит его к концу дня (то есть к 23:59:59). Благодаря этому, нам не требуется оборачивать выражение в дополнительные функции типа КонецПериода() — платформа всё сделает за нас.

Способ 4. Программная установка параметра через объект «Граница»

Иногда перевод времени на начало следующего дня (на 00:00:00) невозможен по логике отчета или из-за особенностей сложных соединений в запросах. В таких случаях самым правильным и точным решением является использование специального объекта платформы 1С — Граница.

Объект Граница позволяет явно указать системе, нужно ли включать документы, записанные в ту же самую конечную секунду, в выборку результатов. Мы используем вид границы Включая.

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

Для этого откроем модуль объекта нашего отчета и пропишем алгоритм в предопределенной процедуре ПриКомпоновкеРезультата:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    // Отключаем стандартный вывод, чтобы управлять процессом компоновки программно
    СтандартнаяОбработка = Ложь;
    
    // Получаем настройки компоновщика
    Настройки = КомпоновщикНастроек.Настройки;
    
    // Ищем наш параметр КонецПериода в схеме
    ПараметрКонец = Настройки.ПараметрыДанных.Элементы.Найти(Новый ПараметрКомпоновкиДанных("КонецПериода"));
    
    Если ПараметрКонец <> Неопределено Тогда
        // Рассчитываем конец текущего дня сеанса пользователя
        КонецДняСеанса = КонецДня(ТекущаяДатаСеанса());
        
        // Устанавливаем в качестве значения объект Граница с видом "Включая"
        ПараметрКонец.Значение = Новый Граница(КонецДняСеанса, ВидГраницы.Включая);
        ПараметрКонец.Использование = Истина;
    КонецЕсли;
    
    // Выполняем стандартную компоновку и вывод отчета на экран
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
КонецПроцедуры

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

Способ 5. Скрытие технического параметра от пользователя

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

Чтобы скрыть параметр из интерфейса, выполним следующие шаги:

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

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

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

← На главную