Как в 1С:ЗУП 3.1 выгрузить количество сотрудников по подразделениям с помощью запроса?

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

При разработке отчетов или выгрузок в 1С:Зарплата и управление персоналом 3.1 (ЗУП) программисты часто сталкиваются с тем, что стандартные запросы к срезу последних регистра сведений КадроваяИсторияСотрудников выдают некорректные данные. Типичная ситуация: сотрудник был временно переведен в другое подразделение, срок перевода истек, и он вернулся на основное место работы. Однако в регистре последней записью остается именно этот временный перевод, из-за чего отчет показывает неактуальное место работы. Разберем подробно, как решить эту задачу правильно и получить точные данные для выгрузки в CSV.

Проблема использования «Среза последних» в ЗУП 3.1

Проанализируем, почему обычный подход через виртуальную таблицу СрезПоследних не работает. В системе 1С:ЗУП 3.1 кадровые события записываются последовательно. При временном переводе создается запись с указанием нового подразделения. Когда срок перевода заканчивается, система методологически предполагает «возврат», но в обычном регистре сведений не всегда автоматически появляется новая запись «текущей датой», если не было проведено новое кадровое событие. В итоге СрезПоследних просто находит хронологически последнюю запись, которая может быть уже не актуальна по срокам действия.

Решение №1: Использование интервальных регистров

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

Рассмотрим структуру запроса к этому регистру. Чтобы получить актуальное подразделение на нужную нам дату (например, на сегодня), нам не нужен срез последних. Нам нужно найти запись, в интервал которой попадает искомая дата.


ВЫБРАТЬ
    КадроваяИстория.Подразделение КАК Подразделение,
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ КадроваяИстория.Сотрудник) КАК КоличествоСотрудников
ИЗ
    РегистрСведений.КадроваяИсторияСотрудниковИнтервальный КАК КадроваяИстория
ГДЕ
    КадроваяИстория.ДатаНачала <= &ДатаСреза
    И КадроваяИстория.ДатаОкончания >= &ДатаСреза
    И КадроваяИстория.Сотрудник.ПометкаУдаления = ЛОЖЬ
СГРУППИРОВАТЬ ПО
    КадроваяИстория.Подразделение

Важно помнить про нюанс со временем: в ЗУП кадровые события могут фиксироваться с точностью до секунд (например, 00:00:05 или 00:00:20). Чтобы не «потерять» сотрудника, всегда используйте в параметре &ДатаСреза конец дня или ту конкретную точку времени, которую использует система для актуализации кадровых данных.

Решение №2: Использование программного интерфейса (API) конфигурации

Посмотрим на ситуацию шире. Если вы пишете код во внешней обработке, наиболее надежным и методологически верным способом будет использование встроенных функций ЗУП. В типовом решении есть модуль КадровыйУчет, который содержит мощные инструменты для подготовки временных таблиц. Метод СоздатьВТКадровыеДанныеСотрудников самостоятельно учитывает все нюансы: временные переводы, подработки, совмещения и даже исправления документов.

Разберем по шагам, как использовать этот механизм в коде для подготовки данных к выгрузке:

  1. Создадим менеджер временных таблиц и запрос.
  2. Вызовем программный метод для формирования таблицы актуальных данных.
  3. Выполним итоговый запрос по этой временной таблице.

// 1. Подготовка менеджера и параметров
МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;

// 2. Формирование временной таблицы с кадровыми данными
// Метод сам выберет нужные регистры и обработает временные переводы
КадровыйУчет.СоздатьВТКадровыеДанныеСотрудников(
    МенеджерВТ, 
    Истина, // Признак формирования таблицы
    ПараметрыПолученияДанных // Здесь указываем Дату и нужные поля (Подразделение)
);

// 3. Итоговый запрос для агрегации
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ВТКадровыеДанные.Подразделение КАК Подразделение,
    |	КОЛИЧЕСТВО(ВТКадровыеДанные.Сотрудник) КАК Количество
    |ИЗ
    |	ВТКадровыеДанныеСотрудников КАК ВТКадровыеДанные
    |СГРУППИРОВАТЬ ПО
    |	ВТКадровыеДанные.Подразделение";

РезультатЗапроса = Запрос.Выполнить();

Этот способ гарантирует, что ваша «тыква» не превратится в карету (и наоборот) после очередного обновления конфигурации, так как вы используете официальный программный интерфейс вендора.

Разберем нюансы подсчета: «Головы» или «Ставки»?

Проанализируем важный методологический момент. В ЗУП 3.1 у одного физического лица может быть несколько карточек Сотрудник (основное место работы, внутреннее совместительство, подработка). Если ваша задача — выгрузить количество «физических лиц» по подразделениям, то группировать данные нужно не по полю Сотрудник, а по полю ФизическоеЛицо.

Кроме того, обратите внимание на следующие фильтры в запросе:

Как не потерять подразделения с нулевой численностью

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

Для решения этой задачи необходимо строить запрос от справочника ПодразделенияОрганизаций и использовать ЛЕВОЕ СОЕДИНЕНИЕ с таблицей кадровых данных. В этом случае в колонке количества для пустых подразделений вы получите NULL, который легко заменить на 0 с помощью функции ЕСТЬNULL.


ВЫБРАТЬ
    Подразделения.Ссылка КАК ПодразделениеНаименование,
    ЕСТЬNULL(ДанныеКадров.Количество, 0) КАК КоличествоСотрудников
ИЗ
    Справочник.ПодразделенияОрганизаций КАК Подразделения
ЛЕВОЕ СОЕДИНЕНИЕ (
    // Здесь ваш вложенный запрос или ВТ с подсчетом сотрудников
) КАК ДанныеКадров
ПО Подразделения.Ссылка = ДанныеКадров.Подразделение
ГДЕ
    Подразделения.ПометкаУдаления = ЛОЖЬ

Подготовка данных к выгрузке в CSV

После того как мы получили таблицу результатов запроса, нам необходимо сформировать текстовый файл в формате CSV. Проанализируем простую схему реализации:


ТекстCSV = Новый ТекстовыйДокумент;
ТекстCSV.ДобавитьСтроку("Подразделение;Количество");

Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
    СтрокаДляЗаписи = Строка(Выборка.ПодразделениеНаименование) + ";" + Формат(Выборка.КоличествоСотрудников, "ЧГ=0");
    ТекстCSV.ДобавитьСтроку(СтрокаДляЗаписи);
КонецЦикла;

ТекстCSV.Записать("C:\Export\EmployeesCount.csv", КодировкаТекста.ANSI);

Используя предложенные методы — особенно работу с интервальными регистрами и программными методами модуля КадровыйУчет — вы сможете создать надежный инструмент для выгрузки, который будет корректно обрабатывать даже самые сложные случаи временных перемещений сотрудников в 1С:ЗУП 3.1.

← На главную