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

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

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

Анализ проблемы: почему месяца идут не по порядку?

Рассмотрим стандартную ситуацию: программист создает запрос, в котором через конструкцию ВЫБОР КОГДА... присваивает каждому числу месяца его текстовое название. В результате в отчет выводятся колонки "Апрель", "Август", "Декабрь" и так далее. Система воспринимает эти значения как обычные строки и сортирует их по алфавиту. Чтобы этого избежать, нам необходимо передать системе числовой признак порядка или использовать встроенные механизмы форматирования дат.

Другая проблема — группировка. Если мы просто выводим дату рождения, то сотрудники, родившиеся 15 марта 1980 года и 10 марта 1995 года, попадут в разные категории, так как их даты не совпадают. Даже использование функции НАЧАЛОПЕРИОДА(ДатаРождения, МЕСЯЦ) не поможет, так как результат будет содержать разные годы (01.03.1980 и 01.03.1995).

Решение 1: Использование числового номера месяца для сортировки

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

Для реализации этого метода в запросе необходимо выделить номер месяца с помощью функции МЕСЯЦ(). Посмотрим на пример преобразования финального запроса:


ВЫБРАТЬ
    ВТ_Заключение.Диапозон КАК Диапозон,
    МЕСЯЦ(ВТ_Заключение.ДатаРождения) КАК НомерМесяца,
    ВЫБОР
        КОГДА МЕСЯЦ(ВТ_Заключение.ДатаРождения) = 1 ТОГДА "Январь"
        КОГДА МЕСЯЦ(ВТ_Заключение.ДатаРождения) = 2 ТОГДА "Февраль"
        // ... остальные месяцы
        ИНАЧЕ "Декабрь"
    КОНЕЦ КАК Период,
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВТ_Заключение.Сотрудник) КАК Количество
ИЗ
    ВТ_Заключение КАК ВТ_Заключение
СГРУППИРОВАТЬ ПО
    ВТ_Заключение.Диапозон,
    МЕСЯЦ(ВТ_Заключение.ДатаРождения)
УПОРЯДОЧИТЬ ПО
    НомерМесяца

Важный нюанс: если вы используете СКД, просто добавить УПОРЯДОЧИТЬ ПО в запросе может быть недостаточно, так как компоновщик часто переопределяет порядок по своим правилам. В этом случае в настройках поля Период на вкладке "Наборы данных" нужно указать в колонке "Выражение упорядочивания" поле НомерМесяца.

Решение 2: Группировка без учета года (метод "фиктивной даты")

Чтобы все сотрудники, родившиеся в марте (независимо от года), попали в одну колонку, нам нужно привести их даты рождения к одному общему году в тексте запроса. Это позволит функции группировки "схлопнуть" записи.

Рассмотрим подробнее, как создать такое поле. Мы можем использовать функцию ДОБАВИТЬКДАТЕ, чтобы установить всем сотрудникам, например, 2000-й год. Это позволит нам сохранить тип данных Дата, что критически важно для последующего форматирования.


ВЫБРАТЬ
    ВТ_Заключение.Диапозон КАК Диапозон,
    ДОБАВИТЬКДАТЕ(
        ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(2000, 1, 1), МЕСЯЦ, МЕСЯЦ(ВТ_Заключение.ДатаРождения) - 1),
        ДЕНЬ, ДЕНЬ(ВТ_Заключение.ДатаРождения) - 1
    ) КАК МесяцБезГода,
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВТ_Заключение.Сотрудник) КАК Количество
ИЗ
    ВТ_Заключение КАК ВТ_Заключение
СГРУППИРОВАТЬ ПО
    ВТ_Заключение.Диапозон,
    МЕСЯЦ(ВТ_Заключение.ДатаРождения) // Группируем по номеру месяца

После этого в настройках СКД для поля МесяцБезГода мы устанавливаем оформление: Формат = "ДФ=ММММ". Это заставит систему выводить только название месяца (например, "Март"), при этом физически в поле будет храниться дата, и сортировка будет работать безупречно с января по декабрь.

Решение 3: Расчет возраста и возрастных диапазонов

Выясним причину, по которой расчет возраста в запросе может быть громоздким. Автор темы использовал длинную конструкцию ВЫБОР. Однако в 1С есть более изящный способ определить, исполнилось ли человеку полное количество лет в текущем году. Разберем этот пример:


(ГОД(&ТекущаяДата) - ГОД(Сотрудники.ДатаРождения)) 
- ВЫБОР 
    КОГДА ДОБАВИТЬКДАТЕ(Сотрудники.ДатаРождения, ГОД, ГОД(&ТекущаяДата) - ГОД(Сотрудники.ДатаРождения)) > &ТекущаяДата 
    ТОГДА 1 
    ИНАЧЕ 0 
КОНЕЦ КАК Возраст

Эта формула работает по принципу: "Вычесть разницу лет, и если день рождения в этом году еще не наступил — вычесть единицу". После того как мы получили числовое значение возраста, мы можем классифицировать его по диапазонам. Вместо того чтобы писать это в основном запросе, рекомендуется использовать Вычисляемые поля в СКД. Это сделает ваш запрос чище и позволит быстрее менять границы диапазонов (например, изменить "от 20 до 30" на "от 20 до 25") без изменения структуры БД.

Настройка структуры отчета в СКД

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

  1. Перейдем на вкладку "Настройки".
  2. Создадим новую группировку типа "Таблица".
  3. В "Строки" добавим наше поле Диапазон.
  4. В "Колонки" добавим поле МесяцБезГода (с настроенным форматом "ДФ=ММММ").
  5. В "Выбранные поля" добавим ресурс КоличествоСотрудников (рассчитывается как Количество(Сотрудник) на вкладке "Ресурсы").

Полезный совет: Чтобы в отчете выводились даже те месяцы, в которых ни у кого нет дня рождения, используйте функцию "Дополнение периодов". В настройках группировки колонок выберите тип дополнения "Месяц" и укажите границы периода (начало и конец года). Это создаст красивую, заполненную структуру отчета.

Резюме: основные правила работы с периодами

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

  1. Никогда не сортируйте месяца по их текстовым названиям. Всегда используйте числовой индекс или дату-ориентир.
  2. Используйте возможности форматной строки ДФ=ММММ для отображения полных названий месяцев.
  3. Если нужно сгруппировать данные по цикличным периодам (дни недели, месяцы года), приводите их к одной базовой дате в прошлом.
  4. Логику классификации (возрастные группы, категории товаров) лучше выносить в вычисляемые поля СКД, а не жестко кодировать в SQL-запросе.

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

← На главную