Как включить последний день периода в отчет СКД, если он не попадает?

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

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

Анализируем исходную проблему: почему последний день не попадает?

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

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


ВыручкаИСебестоимостьПродажОбороты.ЗаказКлиента КАК ЗаказКлиента,
    ВыручкаИСебестоимостьПродажОбороты.Менеджер КАК Менеджер,
    ВыручкаИСебестоимостьПродажОбороты.АналитикаУчетаПоПартнерам.Партнер КАК АналитикаУчетаПоПартнерамПартнер,
    ВыручкаИСебестоимостьПродажОбороты.СуммаВыручкиОборот КАК СуммаВыручкиОборот
ИЗ
    РегистрНакопления.ВыручкаИСебестоимостьПродаж.Обороты(, НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&КонецПериода, ДЕНЬ, 1), ДЕНЬ), , ) КАК ВыручкаИСебестоимостьПродажОбороты

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

Выясняем причины некорректного поведения

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

  1. Точность даты: Параметры даты в 1С всегда хранят не только день, но и время. Если параметр КонецПериода передается как 01.01.2024 0:00:00 (что часто происходит при ручном выборе даты в календаре без указания времени), то виртуальная таблица Обороты не включит операции, произошедшие в течение этого дня. Для корректной работы необходимо, чтобы конечная дата была 01.01.2024 23:59:59.
  2. Влияние автозаполнения СКД: Механизм автозаполнения в СКД призван упростить разработку, автоматически анализируя запрос и создавая соответствующие параметры, поля и настройки. Однако иногда он может конфликтовать с нашими явными инструкциями в запросе или в параметрах. Если вы вручную прописываете сложное выражение для параметра периода в запросе, но затем позволяете автозаполнению СКД или стандартному обработчику периода переопределить его, могут возникнуть несоответствия. СКД может игнорировать ваши уточнения в тексте запроса (например, ДОБАВИТЬКДАТЕ) в пользу своей стандартной обработки границ периода.
  3. Особенности типа СтандартныйПериод: Объект СтандартныйПериод в 1С (который мы часто используем в отчетах) имеет поля ДатаНачала и ДатаОкончания. Если период выбирается через типовой диалог, то ДатаОкончания обычно уже содержит значение 23:59:59. Однако при других способах заполнения параметра, например, просто как значение типа «Дата», время может быть установлено в 00:00:00 по умолчанию.
  4. Различия между Обороты и ОстаткиИОбороты:
    • Виртуальная таблица Обороты: Параметры «Начало» и «Конец» принимают тип Дата. Чтобы захватить весь день, дата окончания должна быть строго 23:59:59.
    • Виртуальная таблица ОстаткиИОбороты: Здесь используются Границы (объект Граница). В СКД это обрабатывается более автоматически. Если вы используете эту таблицу, важно следить за ролью поля «Период» в настройках набора данных (роль «Период», «НачалоПериода», «КонецПериода»), так как от этого зависит корректность расчета остатков на последнюю секунду.

Решаем проблему: отключаем автозаполнение и настраиваем параметры

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

1. Отключаем автозаполнение и заполняем поля вручную

Если вы столкнулись с подобной проблемой, первым делом попробуйте следующий подход:

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

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

2. Корректное указание параметров периода в запросе

После отключения автозаполнения важно убедиться, что параметры в вашем запросе указаны максимально просто и однозначно.

Для виртуальной таблицы Обороты вполне достаточно указать НачалоПериода и КонецПериода напрямую:


ВЫБРАТЬ
    ВыручкаИСебестоимостьПродажОбороты.ЗаказКлиента КАК ЗаказКлиента,
    ВыручкаИСебестоимостьПродажОбороты.Менеджер КАК Менеджер,
    ВыручкаИСебестоимостьПродажОбороты.АналитикаУчетаПоПартнерам.Партнер КАК АналитикаУчетаПоПартнерамПартнер,
    ВыручкаИСебестоимостьПродажОбороты.СуммаВыручкиОборот КАК СуммаВыручкиОборот
ИЗ
    РегистрНакопления.ВыручкаИСебестоимостьПродаж.Обороты(
        &НачалоПериода, // Или &СтандартныйПериод.ДатаНачала
        &КонецПериода,  // Или &СтандартныйПериод.ДатаОкончания
        ,
        ,
    ) КАК ВыручкаИСебестоимостьПродажОбороты

В этом случае мы полагаемся на то, что параметры &НачалоПериода и &КонецПериода будут корректно заполнены извне (например, из настроек СКД).

3. Используем функции для границ периода в выражениях параметров СКД (Золотой стандарт)

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

Рассмотрим по шагам, как это сделать:

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

    Эта функция гарантирует, что даже если ДатаНачала придет с временем, отличным от 00:00:00 (например, 10:30:00), она будет приведена к началу дня (00:00:00).

  6. Для параметра КонецПериода в колонке «Выражение» (Expression) укажите: КонецПериода(&СтандартныйПериод.ДатаОкончания, "ДЕНЬ")

    Это выражение является критически важным. Оно принудительно установит время конечной даты на 23:59:59, даже если в &СтандартныйПериод.ДатаОкончания придет значение 00:00:00. Это гарантирует, что все записи за последний день будут включены в выборку.

  7. Включите параметры НачалоПериода и КонецПериода для использования (флажок «Включать в пользовательские настройки»).

Такой подход сохраняет текст запроса чистым и легко читаемым, а вся логика обработки границ периода инкапсулируется в настройки СКД.

Дополнительные проверки и рекомендации

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

  1. Проверка данных в регистре: Убедитесь, что в регистре накопления ВыручкаИСебестоимостьПродаж действительно есть записи за последний день периода, который вы пытаетесь включить в отчет. Иногда проблема может быть не в СКД, а в отсутствии данных.
  2. Пересчет итогов: Если речь идет о регистрах накопления, особенно тех, где используются итоги, попробуйте выполнить пересчет итогов для регистра. Это можно сделать через консоль запросов или стандартными средствами платформы (например, «Все функции» -> «Стандартные» -> «Управление итогами»). Иногда повреждение итогов может приводить к некорректным данным в виртуальных таблицах.
  3. Настройки ролей полей: Если отчет строится не только по виртуальной таблице, но и по другим данным, где есть поле типа «Период», важно в наборе данных на вкладке «Связи» или в настройках полей указать правильную роль для периода. Если СКД не понимает, что поле является датой периода, она может применять к нему обычное сравнение (равенство или вхождение в интервал), что также может привести к потере данных из-за различий в микросекундах или типах данных в СУБД.
  4. Тестирование с фиксированными датами: Для отладки попробуйте установить фиксированные даты для НачалоПериода и КонецПериода прямо в запросе СКД или в пользовательских настройках, убедившись, что КонецПериода имеет время 23:59:59. Например:
    
    ...
    РегистрНакопления.ВыручкаИСебестоимостьПродаж.Обороты(
        ДАТА(2024,1,1,0,0,0), // Начало периода
        ДАТА(2024,1,31,23,59,59), // Конец периода
        ,
        ,
    )
    ...
    
    Если при этом данные появляются, значит проблема точно в передаче параметров из настроек СКД.

Итоги и рекомендации

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

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

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

← На главную