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