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

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

При разработке аналитических отчетов в Системе компоновки данных (СКД) регулярно возникает необходимость вычисления точного количества календарных или рабочих дней в периоде. Типичный пример — расчет показателя оборачиваемости товаров, средних дневных продаж или показателей выработки. Использование усредненных значений (например, жестко заданных 30 дней в месяце) приводит к погрешностям, поскольку длительность месяцев варьируется от 28 до 31 дня.

Рассмотрим подробнее, как корректно настроить расчет дней в СКД с помощью вычисляемых полей и ресурсов, а также разберем тонкости обработки неполных («рваных») периодов.

Важное различие синтаксиса функции РазностьДат

Разбирая работу с датами, первоочередно обратим внимание на важный синтаксический нюанс 1С. Функция РАЗНОСТЬДАТ используется как в языке запросов, так и в выражениях СКД, однако правила записи третьего параметра (типа разности) отличаются:

  1. В языке запросов 1С: третий параметр указывается без кавычек. РАЗНОСТЬДАТ(Дата1, Дата2, ДЕНЬ)
  2. В выражениях СКД (вычисляемые поля и ресурсы): третий параметр обязательно передается как строка в кавычках. РазностьДат(Дата1, Дата2, "ДЕНЬ") Если в вычисляемом поле написать тип разности без кавычек, система выведет ошибку о том, что поле не найдено.

Шаг 1. Создание вычисляемого поля для расчета дней в месяце

Проанализируем базовый сценарий: в отчете присутствует группировка по месяцам (поле ПериодМесяц или Период, приведенное к началу месяца). Нам требуется определить количество дней для каждого месяца.

Перейдем на вкладку «Вычисляемые поля» в схеме компоновки данных и добавим новое поле:

  1. Путь к данным: КоличествоДней
  2. Выражение: РазностьДат(ПериодМесяц, КонецПериода(ПериодМесяц, "МЕСЯЦ"), "ДЕНЬ") + 1

Почему требуется прибавлять +1? Функция РазностьДат рассчитывает интервал между датами. Например, разность между 01.01.2018 0:00:00 и 31.01.2018 23:59:59 при отсечении времени (или сравнении по дням) вернет 30. Чтобы получить фактическое количество дней в месяце (31 день для января), к результату добавляется единица.

Шаг 2. Учет «рваных» периодов (пересечение с параметрами отчета)

Вышеописанная формула отлично работает, если отчет всегда формируется строго с 1-го по последнее число месяца. Однако если пользователь сформирует отчет, например, с 15 марта по 10 апреля, простой расчет дней месяца даст неверный результат за краевые месяцы.

Выясним, как учесть пересечение месяца с пользовательскими параметрами &НачалоПериода и &КонецПериода. Нам необходимо вычислить фактическую дату начала и конца отрезка в рамках рассматриваемого месяца.

В вычисляемом поле КоличествоДней пропишем следующее выражение:


РазностьДат(
    ВЫБОР 
        КОГДА ПериодМесяц < &НачалоПериода ТОГДА &НачалоПериода 
        ИНАЧЕ ПериодМесяц 
    КОНЕЦ,
    ВЫБОР 
        КОГДА КонецПериода(ПериодМесяц, "МЕСЯЦ") > &КонецПериода ТОГДА &КонецПериода 
        ИНАЧЕ КонецПериода(ПериодМесяц, "МЕСЯЦ") 
    КОНЕЦ, 
    "ДЕНЬ"
) + 1

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

Шаг 3. Настройка агрегации в вкладке «Ресурсы»

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

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

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

  1. Перейдем на вкладку «Ресурсы».
  2. Добавим поле КоличествоДней.
  3. В графе **«Выражение»** для обычных группировок укажем: Максимум(КоличествоДней) (также допускается использовать Среднее(КоличествоДней)).
  4. Для итоговой строки (общие итоги) пропишем вычисление общей длительности периода отчета: РазностьДат(&НачалоПериода, &КонецПериода, "ДЕНЬ") + 1

Шаг 4. Расчет показателя оборачиваемости

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

Оборачиваемость (в днях) = (Средний остаток × Количество дней) / Продажи (в себестоимости или количествах)

На вкладке «Ресурсы» создаем вычисляемый показатель ОборачиваемостьДни и прописываем выражение с обязательной проверкой деления на ноль:


ВЫБОР 
    КОГДА Сумма(ПродажиОборот) = 0 ТОГДА 0 
    ИНАЧЕ (Сумма(СреднийОстаток) * Максимум(КоличествоДней)) / Сумма(ПродажиОборот) 
КОНЕЦ

Альтернативный подход: Использование производственного календаря

Если специфика бизнес-логики требует учета не календарных, а исключительно **рабочих дней** (без учета выходных и праздников), формулы СКД с функцией РазностьДат не подойдут.

В таком случае в запросе схемы компоновки данных выполняется соединение с регистром сведений РегламентированныйПроизводственныйКалендарь или ГрафикиРаботы по условию:


Календарь.Дата МЕЖДУ НачалоПериода И КонецПериода
И Календарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий)

Подсчет количества записей из производственного календаря даст точное число рабочих дней за выбранный интервал времени с учетом переносов праздничных дней.

← На главную