При создании отчетов в 1С, особенно связанных с кадровым составом, часто возникает задача распределения сотрудников по месяцам их рождения. Основная сложность здесь заключается в том, что стандартная сортировка по строковым названиям месяцев (Январь, Февраль...) выстраивает их в алфавитном порядке, что нарушает логику отчета. Кроме того, разные годы рождения сотрудников мешают корректной группировке в рамках одного месяца. В этой статье мы подробно разберем, как решить эти проблемы с помощью запросов и Системы компоновки данных (СКД).
Рассмотрим стандартную ситуацию: программист создает запрос, в котором через конструкцию ВЫБОР КОГДА... присваивает каждому числу месяца его текстовое название. В результате в отчет выводятся колонки "Апрель", "Август", "Декабрь" и так далее. Система воспринимает эти значения как обычные строки и сортирует их по алфавиту. Чтобы этого избежать, нам необходимо передать системе числовой признак порядка или использовать встроенные механизмы форматирования дат.
Другая проблема — группировка. Если мы просто выводим дату рождения, то сотрудники, родившиеся 15 марта 1980 года и 10 марта 1995 года, попадут в разные категории, так как их даты не совпадают. Даже использование функции НАЧАЛОПЕРИОДА(ДатаРождения, МЕСЯЦ) не поможет, так как результат будет содержать разные годы (01.03.1980 и 01.03.1995).
Проанализируем самый простой и быстрый способ исправления сортировки. Мы можем добавить в запрос дополнительное поле, которое будет содержать порядковый номер месяца, и использовать его исключительно для упорядочивания.
Для реализации этого метода в запросе необходимо выделить номер месяца с помощью функции МЕСЯЦ(). Посмотрим на пример преобразования финального запроса:
ВЫБРАТЬ
ВТ_Заключение.Диапозон КАК Диапозон,
МЕСЯЦ(ВТ_Заключение.ДатаРождения) КАК НомерМесяца,
ВЫБОР
КОГДА МЕСЯЦ(ВТ_Заключение.ДатаРождения) = 1 ТОГДА "Январь"
КОГДА МЕСЯЦ(ВТ_Заключение.ДатаРождения) = 2 ТОГДА "Февраль"
// ... остальные месяцы
ИНАЧЕ "Декабрь"
КОНЕЦ КАК Период,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВТ_Заключение.Сотрудник) КАК Количество
ИЗ
ВТ_Заключение КАК ВТ_Заключение
СГРУППИРОВАТЬ ПО
ВТ_Заключение.Диапозон,
МЕСЯЦ(ВТ_Заключение.ДатаРождения)
УПОРЯДОЧИТЬ ПО
НомерМесяца
Важный нюанс: если вы используете СКД, просто добавить УПОРЯДОЧИТЬ ПО в запросе может быть недостаточно, так как компоновщик часто переопределяет порядок по своим правилам. В этом случае в настройках поля Период на вкладке "Наборы данных" нужно указать в колонке "Выражение упорядочивания" поле НомерМесяца.
Чтобы все сотрудники, родившиеся в марте (независимо от года), попали в одну колонку, нам нужно привести их даты рождения к одному общему году в тексте запроса. Это позволит функции группировки "схлопнуть" записи.
Рассмотрим подробнее, как создать такое поле. Мы можем использовать функцию ДОБАВИТЬКДАТЕ, чтобы установить всем сотрудникам, например, 2000-й год. Это позволит нам сохранить тип данных Дата, что критически важно для последующего форматирования.
ВЫБРАТЬ
ВТ_Заключение.Диапозон КАК Диапозон,
ДОБАВИТЬКДАТЕ(
ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(2000, 1, 1), МЕСЯЦ, МЕСЯЦ(ВТ_Заключение.ДатаРождения) - 1),
ДЕНЬ, ДЕНЬ(ВТ_Заключение.ДатаРождения) - 1
) КАК МесяцБезГода,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВТ_Заключение.Сотрудник) КАК Количество
ИЗ
ВТ_Заключение КАК ВТ_Заключение
СГРУППИРОВАТЬ ПО
ВТ_Заключение.Диапозон,
МЕСЯЦ(ВТ_Заключение.ДатаРождения) // Группируем по номеру месяца
После этого в настройках СКД для поля МесяцБезГода мы устанавливаем оформление: Формат = "ДФ=ММММ". Это заставит систему выводить только название месяца (например, "Март"), при этом физически в поле будет храниться дата, и сортировка будет работать безупречно с января по декабрь.
Выясним причину, по которой расчет возраста в запросе может быть громоздким. Автор темы использовал длинную конструкцию ВЫБОР. Однако в 1С есть более изящный способ определить, исполнилось ли человеку полное количество лет в текущем году. Разберем этот пример:
(ГОД(&ТекущаяДата) - ГОД(Сотрудники.ДатаРождения))
- ВЫБОР
КОГДА ДОБАВИТЬКДАТЕ(Сотрудники.ДатаРождения, ГОД, ГОД(&ТекущаяДата) - ГОД(Сотрудники.ДатаРождения)) > &ТекущаяДата
ТОГДА 1
ИНАЧЕ 0
КОНЕЦ КАК Возраст
Эта формула работает по принципу: "Вычесть разницу лет, и если день рождения в этом году еще не наступил — вычесть единицу". После того как мы получили числовое значение возраста, мы можем классифицировать его по диапазонам. Вместо того чтобы писать это в основном запросе, рекомендуется использовать Вычисляемые поля в СКД. Это сделает ваш запрос чище и позволит быстрее менять границы диапазонов (например, изменить "от 20 до 30" на "от 20 до 25") без изменения структуры БД.
Для того чтобы отчет выглядел как шахматка (диапазоны в строках, месяца в колонках), выполним следующие шаги в конструкторе настроек:
Диапазон.МесяцБезГода (с настроенным форматом "ДФ=ММММ").КоличествоСотрудников (рассчитывается как Количество(Сотрудник) на вкладке "Ресурсы").Полезный совет: Чтобы в отчете выводились даже те месяцы, в которых ни у кого нет дня рождения, используйте функцию "Дополнение периодов". В настройках группировки колонок выберите тип дополнения "Месяц" и укажите границы периода (начало и конец года). Это создаст красивую, заполненную структуру отчета.
Проанализировав ситуацию, мы можем выделить несколько золотых правил для разработчика отчетов:
ДФ=ММММ для отображения полных названий месяцев.Применяя эти методы, вы создадите профессиональный, гибкий и удобный для пользователя отчет, который будет работать корректно вне зависимости от входящих данных.