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

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

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

Проблема отсутствующих данных в периоде

Рассмотрим ситуацию: нам нужно получить количество дней в месяце, разделенных на категории (например, «Понедельник-Среда», «Четверг-Пятница» и «Суббота-Воскресенье»). Если мы будем строить запрос напрямую к таблице документов, то получим только те дни, в которых были движения. Если за месяц было всего три документа, запрос покажет три дня, хотя в периоде их тридцать. Для решения этой задачи нам необходимо сначала создать «сетку» из всех дат периода, а уже к ней присоединять данные документов.

Метод 1: Генерация последовательности дат с помощью таблицы цифр

Проанализируем классический способ генерации последовательности чисел, который позволяет получить любое количество строк в запросе без обращения к реальным таблицам базы данных. Мы создаем временную таблицу из десяти цифр (от 0 до 9) и перемножаем её саму на себя несколько раз.

Разберем по шагам создание такой таблицы:


ВЫБРАТЬ 0 КАК Цифра ПОМЕСТИТЬ ТабЦифр ОБЪЕДИНИТЬ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВЫБРАТЬ 2 
ОБЪЕДИНИТЬ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВЫБРАТЬ 5 
ОБЪЕДИНИТЬ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВЫБРАТЬ 9;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, т1.Цифра + 10 * т2.Цифра + 100 * т3.Цифра) КАК Дата
ПОМЕСТИТЬ ВТ_ВсеДаты
ИЗ
    ТабЦифр КАК т1,
    ТабЦифр КАК т2,
    ТабЦифр КАК т3
ГДЕ
    ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, т1.Цифра + 10 * т2.Цифра + 100 * т3.Цифра) <= &КонецПериода

В данном примере мы соединяем три таблицы цифр, что дает нам 1000 комбинаций (строк). Этого достаточно, чтобы покрыть период почти в три года. Функция ДОБАВИТЬКДАТЕ последовательно прибавляет к начальной дате количество дней, равное порядковому номеру строки. Важно: не забудьте ограничить выборку условием ГДЕ, чтобы не выйти за рамки конечной даты периода.

Метод 2: Использование производственного календаря

Если в вашей конфигурации (ЗУП, ERP, КА, БП) ведется производственный календарь, задачу можно решить еще проще. Существует регистр сведений ДанныеПроизводственногоКалендаря, который уже содержит все даты. Рассмотрим пример запроса к нему:


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

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

Объединение календаря с данными документов

Теперь, когда у нас есть временная таблица со всеми датами и их категориями, мы должны выполнить Левое Соединение нашей таблицы дат с таблицей документов. Проанализируем структуру итогового запроса:

  1. Выбираем поле Дата и КатегорияДня из нашей временной таблицы календаря.
  2. Присоединяем таблицу документов по условию НАЧАЛОПЕРИОДА(Документ.Дата, ДЕНЬ) = ВТ_ВсеДаты.Дата.
  3. Группируем результат по полю КатегорияДня.
  4. Для подсчета дней используем агрегатную функцию КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Дата).

Такой подход гарантирует, что даже если за категорию "Сб-Вс" не было ни одного документа, в отчете все равно отобразится количество выходных дней в этом месяце (например, 8 или 9), а сумма по документам будет равна нулю.

Настройка разных формул ресурсов для группировок в СКД

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

Выясним, как настроить индивидуальные расчеты:

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

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

Управление сортировкой в СКД

Иногда при использовании вычисляемых категорий (как "Пн-Ср") нарушается порядок вывода колонок или строк. Посмотрим, почему стандартная сортировка может не работать. СКД часто игнорирует УПОРЯДОЧИТЬ ПО в тексте запроса, отдавая приоритет настройкам на вкладке Настройки - Сортировка.

Чтобы зафиксировать порядок категорий:

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

← На главную