Разработка отчетов типа "Табель учета рабочего времени" в системе компоновки данных (СКД) часто вызывает трудности у начинающих разработчиков. Типичная ошибка — попытка написать сложный запрос напрямую к табличной части документа ТабельУчетаРабочегоВремени, в котором жестко прописана 31 колонка для каждого дня месяца. Такой подход делает схему громоздкой, лишает отчет гибкости и приводит к проблемам при подсчете итогов, особенно если сотрудник работал на разных должностях или по разным специальностям в течение одного дня.
В этой статье мы подробно разберем, почему запрос к табличной части документа является тупиковым решением, как правильно спроектировать схему СКД с использованием регистров накопления и как настроить автоматический расчет итогов по дням (колонкам) и сотрудникам (строкам) с помощью механизма кросс-таблиц.
Проанализируем ситуацию, с которой столкнулся автор темы. В исходном запросе выбираются поля ПервыйЧасов1, ПервыйЧасов2 ... ПервыйЧасов31 из табличной части документа. Для получения итогов автор использует конструкцию СУММА(ПервыйЧасов1 + ПервыйЧасов2 + ...) и добавляет группировку СГРУППИРОВАТЬ ПО по всем детальным полям, включая часы и виды времени за каждый день.
Такой подход ломает логику работы СКД по нескольким причинам:
Чтобы табель работал быстро, правильно считал итоги и автоматически подстраивался под количество дней в выбранном месяце (28, 30 или 31 день), мы должны отказаться от запроса к документу и обратиться к виртуальной таблице оборотов регистра накопления РабочееВремяСотрудников (или аналогичного регистра в вашей конфигурации).
Рассмотрим по шагам, как построить правильный запрос. Основной секрет кроется в использовании параметра Периодичность виртуальной таблицы оборотов. Если мы оставим периодичность по умолчанию, система выдаст нам общие обороты за весь период одной строкой. Нам же необходимо указать периодичность День.
Посмотрим на пример правильного запроса для схемы компоновки данных:
ВЫБРАТЬ
РабочееВремяОбороты.Сотрудник КАК Сотрудник,
РабочееВремяОбороты.Подразделение КАК Подразделение,
РабочееВремяОбороты.ВидИспользованияРабочегоВремени КАК ВидВремени,
РабочееВремяОбороты.Период КАК Период,
РабочееВремяОбороты.ДнейОборот КАК Дни,
РабочееВремяОбороты.ЧасовОборот КАК Часы
ИЗ
РегистрНакопления.РабочееВремяСотрудников.Обороты(&НачалоПериода, &КонецПериода, День, ) КАК РабочееВремяОбороты
В этом запросе поле Период будет содержать конкретную дату (каждый день месяца, в котором у сотрудника были движения по регистру). Обратите внимание, что мы не группируем данные в самом запросе с помощью СГРУППИРОВАТЬ ПО. Всю агрегацию и подсчет итогов мы полностью делегируем механизму СКД.
После того как запрос написан, нам необходимо объяснить системе компоновки данных, какие поля являются числовыми показателями, требующими суммирования. Для этого мы переходим на вкладку "Ресурсы" в конструкторе схемы компоновки данных.
Выполним следующие настройки:
Часы в список ресурсов. В колонке "Выражение" укажем стандартную агрегатную функцию: СУММА(Часы).Дни в список ресурсов. Выражение для расчета также зададим как СУММА(Дни).Благодаря этому, в каких бы разрезах и группировках мы ни выводили отчет, СКД автоматически просуммирует отработанные часы и дни.
Чтобы получить классический вид табеля, где сотрудники расположены в строках, а дни месяца — в колонках, нам нужно использовать тип элемента структуры СКД "Таблица" вместо обычного списка.
Разберем по шагам настройку структуры на вкладке "Настройки" в СКД:
Сотрудник. При необходимости над сотрудником можно добавить группировку по полю Подразделение.Период.Часы и ВидВремени.При такой структуре СКД выполнит транспонирование данных: для каждого уникального значения поля Период (то есть для каждого дня) будет создана отдельная колонка. На пересечении строки сотрудника и колонки периода система выведет количество часов и вид времени.
По умолчанию в шапке колонок табеля будет выводиться полная дата со временем, например, "01.04.2018 00:00:00". Это делает таблицу слишком широкой и нечитаемой. Мы можем легко исправить это с помощью оформления.
Рассмотрим, как настроить отображение только номера дня (1, 2, 3...):
Период.ДФ=д (для вывода только числа дня) или ДФ=дд (для двузначного представления, например, "01", "02").Теперь в шапке колонок нашего табеля будут аккуратные числа месяца, при этом СКД сохранит правильную хронологическую сортировку дат.
Возвращаясь к проблеме автора: "допустим 2 число и там две записи так как сотрудник работал по двум специальностям в этот день. Так вот эти две записи он не суммирует".
Когда мы используем предложенную структуру с регистром накопления и ресурсами, эта проблема решается автоматически за счет механизма группировок СКД:
Сотрудник, а поле Специальность не выведено, то СКД автоматически сложит все часы сотрудника за этот день (например, 12 часов по одной специальности + 12 часов по другой = 24 часа в одной ячейке за 2-е число).Специальность (или ВидРабот) внутрь группировки Сотрудник в строках таблицы. Тогда строка сотрудника развернется на две детальные строки с указанием должностей, в каждой из которых будут свои часы, а в общей строке сотрудника выведется корректный суммарный итог по дням и за месяц в целом.Таким образом, использование регистра накопления в сочетании с гибким механизмом кросс-таблиц и ресурсов СКД позволяет полностью отказаться от громоздкого "ручного" кодирования колонок и переложить всю работу по расчету итогов на платформу 1С.