Как вывести подразделение сотрудника в табличную часть ведомости на выплату в ЗУП 3.1

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

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

Анализ структуры данных документа выплаты

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

  1. Состав — это то, что пользователь видит на первой вкладке. Здесь перечислены физические лица (сотрудники) и общие суммы.
  2. Зарплата — скрытая или вспомогательная таблица, в которой хранится детальная аналитика: периоды, документы-основания и, что самое важное, Подразделение.

Важно понимать, что один сотрудник может получать выплаты по нескольким подразделениям сразу (например, при внутреннем совместительстве). Поэтому просто вывести "текущее подразделение" из кадрового учета может быть методологически неверно — правильнее брать данные из аналитики самого документа (ТЧ Зарплата).

Способ 1. Программное добавление колонки и заполнение по кнопке

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

Рассмотрим пример кода, который можно разместить в расширении формы документа. Сначала создадим процедуру на сервере для сопоставления данных:


&НаСервере
Функция ПолучитьСоответствиеПодразделений()
    соотПодразделений = Новый Соответствие;
    
    // Перебираем строки основной таблицы
    Для каждого стр Из Объект.Состав Цикл
        Поиск = Новый Структура("ФизическоеЛицо", стр.ФизическоеЛицо);
        // Ищем аналитику в таблице Зарплата этого же документа
        мСтрокиПодразделений = Объект.Зарплата.НайтиСтроки(Поиск);
        
        Если мСтрокиПодразделений.Количество() > 0 Тогда
            // Берем подразделение из первой найденной строки аналитики
            соотПодразделений.Вставить(стр.ПолучитьИдентификатор(), мСтрокиПодразделений[0].Подразделение);
        КонецЕсли;
    КонецЦикла;
    
    Возврат соотПодразделений;
КонецФункции

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


&НаКлиенте
Процедура ПоказатьПодразделенияСотрудников(Команда)
    соотПодразделений = ПолучитьСоответствиеПодразделений();
    
    Если соотПодразделений.Количество() > 0 Тогда
        ТекСтрока = Элементы.Состав.ТекущаяСтрока;
        
        // ВАЖНО: Нам нужно заполнить программную колонку "Подразделение", 
        // которая добавлена на форму как элемент таблицы "Состав"
        Для каждого элемент Из соотПодразделений Цикл
            // Идентификатор строки позволяет точно обратиться к данным на клиенте
            Элементы.Состав.ТекущаяСтрока = элемент.Ключ;
            Элементы.Состав.ТекущиеДанные.Подразделение = элемент.Значение;
        КонецЦикла;
        
        Элементы.Состав.ТекущаяСтрока = ТекСтрока;
    КонецЕсли;
КонецПроцедуры

Важное примечание: Перебор через ТекущаяСтрока на клиенте может визуально "дергать" курсор в таблице. Это не самый изящный способ, но он работает для небольших ведомостей без изменения метаданных.

Способ 2. Динамическое заполнение через обработчики отрисовки формы

В ЗУП 3.1 заполнение таблиц часто вынесено в специализированные общие модули. В частности, можно обратить внимание на модуль ВзаиморасчетыССотрудникамиФормы. Проанализируем возможность внедрения в процедуру ВедомостьПриПолученииДанныхСтростава.

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

  1. В расширении формы добавляем в таблицу Состав поле формы с типом СправочникСсылка.ПодразделенияОрганизаций.
  2. Используем программный интерфейс общего модуля КадровыйУчет для получения данных.

Пример функции для массового получения подразделений:


// В модуле формы или в расширении
&НаСервере
Процедура ЗаполнитьПодразделенияНаСервере()
    МассивСотрудников = Объект.Состав.ВыгрузитьКолонку("Сотрудник");
    // Используем оптимизированный метод ЗУП для получения кадровых данных
    ТаблицаДанных = КадровыйУчет.КадровыеДанныеСотрудников(Истина, МассивСотрудников, "Подразделение", Объект.Дата);
    
    // Кэшируем данные для быстрой подстановки
    Для каждого СтрСостава Из Объект.Состав Цикл
        СтрокаДанных = ТаблицаДанных.Найти(СтрСостава.Сотрудник, "Сотрудник");
        Если СтрокаДанных <> Неопределено Тогда
             // Присваиваем значение реквизиту формы (не путать с реквизитом объекта!)
             СтрСостава.Подразделение = СтрокаДанных.Подразделение;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Способ 3. Использование расширений метаданных (Платформа 8.3.15+)

Если ваша конфигурация работает на современной платформе (8.3.15 и выше), наиболее правильным решением будет добавление реквизита Подразделение непосредственно в табличную часть Состав через расширение конфигурации.

Преимущества этого подхода:

Рассмотрим шаги реализации:

  1. Создаем новое расширение, добавляем в него документ (например, ВедомостьВБанк).
  2. Добавляем в табличную часть Состав новый реквизит Подразделение (тип СправочникСсылка.ПодразделенияОрганизаций).
  3. В модуле объекта документа в расширении переопределяем процедуру ПередЗаписью или ОбработкаЗаполнения, чтобы данные подтягивались автоматически при формировании ведомости.

Пример кода заполнения при записи в расширении модуля объекта:


&После("ПередЗаписью")
Процедура Расш_ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    Если ЭтотОбъект.ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

    // Заполняем подразделения из ТЧ Зарплата для обеспечения актуальности аналитики
    Для каждого СтрСостав Из ЭтотОбъект.Состав Цикл
        Отбор = Новый Структура("ФизическоеЛицо", СтрСостав.ФизическоеЛицо);
        СтрокиЗарплаты = ЭтотОбъект.Зарплата.НайтиСтроки(Отбор);
        Если СтрокиЗарплаты.Количество() > 0 Тогда
            СтрСостав.Подразделение = СтрокиЗарплаты[0].Подразделение;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Проблема производительности и пути её решения

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

Рекомендации по оптимизации:

В заключение отметим, что выбор метода зависит от ваших требований к чистоте конфигурации. Если критично не менять структуру БД — используйте временные реквизиты формы и заполнение через Соответствие. Если же важна стабильность и возможность работы с этими данными в будущем — используйте механизм реквизитов расширений.

← На главную