В практике расчета заработной платы часто возникает потребность сформировать расчетные листки (или другие кадрово-расчетные отчеты) не по всем сотрудникам и не по конкретному подразделению, а по специфическому критерию. Например, нужно распечатать "расчетки" только для тех, кто в этом месяце получил "Доплату за разъездной характер работы" или "Сдельную оплату".
На первый взгляд задача кажется тривиальной, но стандартные настройки отчетов в 1С:Зарплата и Управление Персоналом (ЗУП 3.1) могут сбить с толку. Рассмотрим подробно, почему обычный отбор не работает так, как ожидается, и разберем эффективные способы решения этой задачи — как для уверенных пользователей, так и для программистов.
Многие пользователи пытаются решить задачу "в лоб": заходят в настройки отчета Расчетный листок, добавляют отбор по полю Вид расчета (или Начисление) и указывают нужное значение.
Давайте проанализируем, к чему это приводит. Отчеты на базе Системы Компоновки Данных (СКД) при наложении такого отбора фильтруют не сотрудников, а строки записей регистра.
Результат:
Наша цель иная: нам нужно отобрать список людей, у которых было это начисление, но сам расчетный листок вывести полностью (со всеми окладами, налогами и выплатами).
Если задача возникает нечасто (например, раз в месяц или квартал), нет смысла писать сложный код. Мы можем воспользоваться комбинацией двух отчетов. Разберем этот алгоритм по шагам.
Шаг 1. Получаем список сотрудников.
Нам подойдет любой отчет, где можно увидеть начисления, например, Анализ зарплаты по сотрудникам (в целом за период) или Полный свод начислений.
Вид расчета Равно <Нужное начисление>.Теперь перед нами список только тех людей, у кого было это начисление (и только эта сумма, но сейчас нам нужны только фамилии).
Шаг 2. Копируем список.
Выделяем колонку с ФИО сотрудников в сформированном отчете и копируем их в буфер обмена (Ctrl+C).
Шаг 3. Формируем расчетные листки.
Сотрудник (или Физическое лицо).После нажатия кнопки "Сформировать" мы получим полноценные расчетные листки, но строго для нужной группы лиц.
Если бухгалтерия требует автоматизации этого процесса ("хотим одну кнопку"), нам потребуется вмешательство в код. Оптимальный вариант для современных конфигураций на базе БСП — создание расширения с командой или внешнего отчета-обертки.
Суть метода заключается в следующем:
Для начала напишем запрос, который вернет нам массив физических лиц. Лучше всего обращаться к виртуальной таблице оборотов регистра накопления НачисленияУдержанияПоСотрудникам.
&НаСервере
Функция ПолучитьМассивФизЛицСНачислением(НачалоПериода, КонецПериода, Организация, ВидРасчетаОтбор)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| НачисленияУдержания.ФизическоеЛицо КАК ФизическоеЛицо
|ИЗ
| РегистрНакопления.НачисленияУдержанияПоСотрудникам.Обороты(
| &НачалоПериода,
| &КонецПериода,
| ,
| НачислениеУдержание = &ВидРасчетаОтбор
| И Организация = &Организация) КАК НачисленияУдержания";
Запрос.УстановитьПараметр("НачалоПериода", НачалоПериода);
Запрос.УстановитьПараметр("КонецПериода", КонецПериода);
Запрос.УстановитьПараметр("Организация", Организация);
Запрос.УстановитьПараметр("ВидРасчетаОтбор", ВидРасчетаОтбор);
Возврат Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("ФизическоеЛицо");
КонецФункции
Теперь, когда у нас есть массив, нам нужно открыть форму отчета или сформировать табличный документ, передав этот массив в отбор СКД. Разберем пример кода, который можно использовать в команде внешней обработки или расширения.
Обратите внимание: в ЗУП 3.1 отчет называется Отчеты.РасчетныйЛисток. Использование Отчеты.АнализНачисленийИУдержаний (как предлагалось в некоторых старых примерах) с вариантом "РасчетныйЛисток" может привести к ошибкам, так как это разные объекты метаданных.
&НаСервере
Процедура СформироватьРасчетныеЛисткиНаСервере(ТабДок, РеквизитыСобытия)
// 1. Получаем список нужных людей
МассивФизЛиц = ПолучитьМассивФизЛицСНачислением(
НачалоМесяца(РеквизитыСобытия.МесяцНачисления),
КонецМесяца(РеквизитыСобытия.МесяцНачисления),
РеквизитыСобытия.Организация,
РеквизитыСобытия.НужныйВидРасчета
);
Если МассивФизЛиц.Количество() = 0 Тогда
Сообщить("Сотрудников с таким начислением не найдено.");
Возврат;
КонецЕсли;
// 2. Создаем объект отчета
КлючВарианта = "РасчетныйЛисток"; // Имя варианта в СКД
ОтчетОбъект = Отчеты.РасчетныйЛисток.Создать();
// Важно: инициализируем настройки по умолчанию для данного варианта
// В ЗУП 3.1 варианты хранятся в схеме или в хранилище вариантов
СхемаКД = ОтчетОбъект.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
// Ищем вариант настройки по ключу (или берем настройки по умолчанию, если вариант один)
Для Каждого Вариант Из СхемаКД.ВариантыНастроек Цикл
Если Вариант.Имя = КлючВарианта Тогда
Настройки = Вариант.Настройки;
Прервать;
КонецЕсли;
КонецЦикла;
Если Настройки = Неопределено Тогда
Настройки = СхемаКД.НастройкиПоУмолчанию;
КонецЕсли;
ОтчетОбъект.КомпоновщикНастроек.ЗагрузитьНастройки(Настройки);
// 3. Устанавливаем параметры периода
// В Расчетном листке параметры часто называются "Период" (СтандартныйПериод) или "НачалоПериода"/"КонецПериода"
ПараметрПериод = Настройки.ПараметрыДанных.Элементы.Найти("Период");
Если ПараметрПериод <> Неопределено Тогда
ПараметрПериод.Значение = Новый СтандартныйПериод(
НачалоМесяца(РеквизитыСобытия.МесяцНачисления),
КонецМесяца(РеквизитыСобытия.МесяцНачисления)
);
ПараметрПериод.Использование = Истина;
КонецЕсли;
// 4. Программно устанавливаем отбор
// Сначала очистим старые отборы по Сотруднику/ФизЛицу, если они есть
// (для простоты примера опустим этот шаг, предполагая чистые настройки)
// Добавляем отбор по Организации
ЭлементОтбораОрг = Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбораОрг.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Организация");
ЭлементОтбораОрг.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбораОрг.ПравоеЗначение = РеквизитыСобытия.Организация;
ЭлементОтбораОрг.Использование = Истина;
// Добавляем ключевой отбор по Списку ФизЛиц
ЭлементОтбораФЛ = Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
// В зависимости от настройки отчета поле может называться "Сотрудник" или "ФизическоеЛицо"
// В типовом РЛ часто используется группировка по ФизЛицу
ЭлементОтбораФЛ.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ФизическоеЛицо");
ЭлементОтбораФЛ.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
ЭлементОтбораФЛ.ПравоеЗначение = МассивФизЛиц; // Передаем наш массив
ЭлементОтбораФЛ.Использование = Истина;
// 5. Компонуем результат
ОтчетОбъект.КомпоновщикНастроек.ЗагрузитьНастройки(Настройки);
ОтчетОбъект.СкомпоноватьРезультат(ТабДок);
КонецПроцедуры
При реализации программного метода стоит учитывать несколько особенностей платформы и конфигурации:
ОбщегоНазначенияКлиентСервер. Например, метод ИзменитьЭлементыОтбора(...) позволяет сократить код установки отборов и сделать его более читаемым.Отбор (структура) передается в ОткрытьФорму. Однако для сложных отборов (типа "В Списке") может потребоваться передача настроек компоновщика через пользовательские параметры или использование обработчика ПриСозданииНаСервере в расширении формы.РАЗЛИЧНЫЕ. Это критично, так как в регистре может быть несколько записей по одному сотруднику за месяц (например, если начисление вводилось разными документами). Если не свернуть список, массив будет содержать дубли, что не страшно для СКД, но неаккуратно.Используя эти методы, вы сможете гибко управлять выводом расчетных листков, не ограничиваясь стандартными возможностями интерфейса.