Как рассчитать количество рабочих дней между датами в СКД 1С

Программист 1С v8.3 (Обычные формы) 1C:Бухгалтерия IT и автоматизация бизнеса
← На главную

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

Ограничения функции РАЗНОСТЬДАТ и языка выражений СКД

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

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

Способ 1. Использование регистра сведений производственного календаря в запросе

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

Посмотрим на пример запроса, который суммирует только необходимые дни из диапазона между строгими границами периода:


ВЫБРАТЬ
    СУММА(ВЫБОР
        КОГДА Календарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий)
          ИЛИ Календарь.ВидДня = ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Предпраздничный)
            ТОГДА 1
        ИНАЧЕ 0
    КОНЕЦ) КАК КоличествоРабочихДней
ИЗ
    РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК Календарь
ГДЕ
    Календарь.ДатаКалендаря МЕЖДУ &НачалоПериода И &КонецПериода

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

Способ 2. Вызов экспортной функции общего модуля из вычисляемого поля

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

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

Пример формулы для вычисляемого поля СКД:

ИмяСерверногоМодуля.ПосчитатьРабочиеДни(ДатаНачала, ДатаОкончания)

Внутри функции общего модуля вы можете описать алгоритм считывания данных из производственного календаря или вызова программного интерфейса БСП.

Способ 3. Математический расчет без обращения к регистру (без учета праздников)

Рассмотрим ситуацию, когда требуется быстро исключить только субботы и воскресенья, а точный учет государственных праздников и переносов не требуется. В этом случае можно обойтись математическим расчетом на языке запросов с использованием функции ДЕНЬНЕДЕЛИ:

  1. Вычисляем количество полных недель между датами и умножаем его на 5 (количество рабочих дней в неделе).
  2. С помощью функции ДЕНЬНЕДЕЛИ(Дата) определяем дни недели для начала и конца периода и корректируем остаток неполной недели.

Оптимизация производительности при больших объемах данных

Выясним возможные проблемы со скоростью выполнения отчета. Если связывать основную таблицу отчета с регистром календаря напрямую по условию ДатаКалендаря МЕЖДУ ДатаНачала И ДатаОкончания для каждой детальной записи, возникает неточное соединение (Non-Equi Join). На больших массивах данных (десятки тысяч строк) такой подход существенно снижает скорость работы отчета.

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

  1. Во временную таблицу помещаем уникальные пары (ДатаНачала, ДатаОкончания) с использованием группировки СГРУППИРОВАТЬ ПО.
  2. Соединяем только таблицу уникальных пар с производственным календарем и рассчитываем для них число дней.
  3. Итоговую таблицу соединяем с основными данными отчета по точному равенству дат.
← На главную