Разработка внешних печатных форм (ВПФ) — одна из самых частых задач, с которыми сталкивается начинающий разработчик в среде «1С:Предприятие 8». Особенно много нюансов возникает при работе с конфигурацией «1С:Зарплата и управление персоналом 3.1» (ЗУП 3.1). В этой статье мы подробно разберем, как правильно спроектировать внешнюю печатную форму для справочника Сотрудники, извлечь номер и дату трудового договора, а также почему стандартные запросы к документам приема на работу могут привести к критическим ошибкам в работе программы.
Начинающие разработчики часто пытаются получить данные договора напрямую из документа ПриемНаРаботу с помощью простого запроса, связывая таблицы по текстовому представлению ФИО. Рассмотрим исходный запрос, представленный автором темы:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПриемНаРаботу.Дата КАК Дата,
| ПриемНаРаботу.Номер КАК Номер,
| ПриемНаРаботу.Сотрудник КАК Сотрудник,
| Сотрудники.ФизическоеЛицо.ФИО КАК ФИО
|ИЗ
| Документ.ПриемНаРаботу КАК ПриемНаРаботу
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Сотрудники КАК Сотрудники
| ПО ПриемНаРаботу.Сотрудник.ФизическоеЛицо.ФИО = Сотрудники.ФизическоеЛицо.ФИО";
Проанализируем эту конструкцию и выясним, почему такой подход категорически не рекомендуется использовать в реальных базах данных:
ПО ПриемНаРаботу.Сотрудник = Сотрудники.Ссылка.ПриемНаРаботу. Сведения также могут храниться в регистре сведений КадроваяИсторияСотрудников, изменяться дополнительными соглашениями или кадровыми переводами. Прямой запрос к одному документу не гарантирует получение актуальных данных на текущую дату.Для решения подобных задач в конфигурациях на базе Библиотеки стандартных подсистем (БСП) предусмотрены специальные экспортные методы. Наиболее стабильным, оптимизированным и безопасным способом получения кадровых данных в ЗУП 3.1 является использование встроенной функции КадровыйУчет.КадровыеДанныеСотрудников.
Этот метод самостоятельно обращается к нужным регистрам сведений, учитывает все изменения законодательства и структуры метаданных при обновлениях конфигурации, а также автоматически накладывает права доступа (RLS) текущего пользователя.
Рассмотрим по шагам, как устроена работа внешней печатной формы справочника Сотрудники.
Любая внешняя печатная форма, подключаемая через механизм «Дополнительные отчеты и обработки», должна содержать в модуле объекта стандартную экспортную процедуру Печать. В эту процедуру платформа передает список объектов, для которых запущена печать.
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
// Проверяем, нужно ли выводить нашу печатную форму
УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "НашаВнешняяПечатнаяФорма");
// Получаем табличный документ
ТабличныйДокумент = СформироватьПечатнуюФорму(МассивОбъектов, ОбъектыПечати);
// Связываем объекты печати с результатом
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
КоллекцияПечатныхФорм,
"НашаВнешняяПечатнаяФорма",
"Трудовой договор (внешний)",
ТабличныйДокумент
);
КонецПроцедуры
Обратите внимание на параметр МассивОбъектов. Он содержит массив ссылок на выбранные элементы справочника Сотрудники. Ошибка «Переменная неопределенна» у начинающих разработчиков возникает именно потому, что они пытаются использовать единичную переменную Сотрудник, которой нет в контексте процедуры. Работать необходимо именно с переданным массивом.
Теперь напишем функцию формирования печатной формы, где применим встроенный метод получения кадровых данных. Мы передадим в него весь МассивОбъектов целиком, чтобы избежать выполнения запросов в цикле (что является грубым нарушением стандартов разработки 1С).
Функция СформироватьПечатнуюФорму(МассивОбъектов, ОбъектыПечати)
ТабличныйДокумент = Новый ТабличныйДокумент;
ТабличныйДокумент.КлючПараметровПечати = "ПараметрыПечати_ТрудовойДоговор";
// Получаем макет печатной формы (должен быть создан в обработке)
Макет = ПолучитьМакет("Макет");
// Определяем список необходимых нам полей
КадровыеДанные = "ТрудовойДоговорНомер, ТрудовойДоговорДата, ФИОПолные, Подразделение, Должность";
// Указываем дату, на которую актуальны данные (обычно текущая дата сеанса)
ДатаПолученияДанных = ТекущаяДатаСеанса();
// Вызываем типовой метод ЗУП 3.1
ТаблицаКадровыхДанных = КадровыйУчет.КадровыеДанныеСотрудников(
Истина,
МассивОбъектов,
КадровыеДанные,
ДатаПолученияДанных
);
// Проанализируем полученную таблицу данных и выведем ее в макет
Для Каждого СтрокаКадровыхДанных Из ТаблицаКадровыхДанных Цикл
// Получаем область макета
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
// Заполняем параметры области макета данными из полученной строки ТЗ
ОбластьСтрока.Параметры.Заполнить(СтрокаКадровыхДанных);
// Форматируем вывод даты трудового договора
Если ЗначениеЗаполнено(СтрокаКадровыхДанных.ТрудовойДоговорДата) Тогда
ОбластьСтрока.Параметры.ДоговорДата = Формат(
СтрокаКадровыхДанных.ТрудовойДоговорДата,
"ДФ='дд ММММ гггг ""г.""'"
);
Иначе
ОбластьСтрока.Параметры.ДоговорДата = "________ г.";
EndIf;
// Если номер договора не заполнен, выводим заглушку
Если Не ЗначениеЗаполнено(СтрокаКадровыхДанных.ТрудовойДоговорНомер) Тогда
ОбластьСтрока.Параметры.ТрудовойДоговорНомер = "б/н";
КонецЕсли;
// Фиксируем связь выводимой области с конкретным объектом справочника
// Это необходимо для возможности расшифровки и навигации в табличном документе
ОбъектыПечати.Добавить(СтрокаКадровыхДанных.Сотрудник, "УникальноеИмяОбласти");
// Выводим заполненную область в итоговый печатный документ
ТабличныйДокумент.Вывести(ОбластьСтрока);
КонецЦикла;
Возврат ТабличныйДокумент;
КонецФункции
Давайте подробно разберем параметры функции КадровыйУчет.КадровыеДанныеСотрудников, чтобы понимать логику ее работы:
ТолькоРазрешенные. Если передано значение Истина, функция автоматически отфильтрует данные сотрудников, на которые у текущего пользователя нет прав доступа (например, ограничение по группам доступа или физическим лицам). Это защищает систему от утечки конфиденциальной информации.МассивОбъектов. Функция может принимать как одиночную ссылку на сотрудника, так и массив сотрудников любой длины."ТрудовойДоговорНомер, ТрудовойДоговорДата, ФИОПолные". Имена полей соответствуют стандартным реквизитам кадрового учета конфигурации.ТекущаяДатаСеанса() или НачалоДня(ТекущаяДата()).Использование функции КадровыеДанныеСотрудников вместо прямого написания сложных SQL-подобных запросов к таблицам СУБД дает разработчику несколько важных преимуществ:
Таким образом, мы детально разобрали правильную архитектуру построения внешней печатной формы в 1С:ЗУП 3.1. Использование встроенных механизмов БСП позволяет создавать надежные и быстрые алгоритмы, которые будут стабильно работать даже на сильно измененных или крупных корпоративных базах данных.