Как правильно получить данные о графике отпусков и настроить склонение ФИО во внешней печатной форме ЗУП 3.1

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

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

Анализ структуры внешней печатной формы

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


Функция СведенияОВнешнейОбработке() Экспорт
    МассивНазначений = Новый Массив;
    МассивНазначений.Добавить("Документ.ПереносОтпуска"); 
    
    ПараметрыРегистрации = Новый Структура;
    ПараметрыРегистрации.Вставить("Вид", "ПечатнаяФорма");
    ПараметрыРегистрации.Вставить("Назначение", МассивНазначений);
    ПараметрыРегистрации.Вставить("Наименование", "Приказ о переносе отпуска (ООО Визир)");
    ПараметрыРегистрации.Вставить("БезопасныйРежим", Истина);
    ПараметрыРегистрации.Вставить("Версия", "1.1"); 
    
    ТаблицаКоманд = ПолучитьТаблицуКоманд();
    ДобавитьКоманду(ТаблицаКоманд, "Приказ о переносе отпуска", "ПереносОтпускаПриказ", "ВызовСерверногоМетода", Истина, "ПечатьMXL");
    
    ПараметрыРегистрации.Вставить("Команды", ТаблицаКоманд);
    Возврат ПараметрыРегистрации;
КонецФункции

Обратите внимание, что мы установили параметр БезопасныйРежим в значение Истина. Это стандартная практика для печатных форм, которые не требуют доступа к внешним файловым ресурсам или COM-объектам. Теперь проанализируем процедуру Печать. В исходном коде часто встречается ошибка обработки только первого элемента массива: МассивОбъектов[0]. Выясним, как сделать обработку универсальной для массовой печати.

Оптимизация процедуры Печать для массовой обработки

Если пользователь выделит несколько документов в списке и нажмет кнопку «Печать», система передаст в процедуру весь массив ссылок. Нам необходимо передать этот массив в запрос целиком, а затем в цикле формировать табличные документы. Рассмотрим правильный подход:


Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
    ПараметрыПечати = Новый Структура;
    
    Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "ПереносОтпускаПриказ") Тогда
        ТабличныйДокумент = СформироватьПечатнуюФорму(МассивОбъектов, ОбъектыПечати);
        УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, "ПереносОтпускаПриказ", "Приказ о переносе отпуска", ТабличныйДокумент);
    КонецЕсли;
КонецПроцедуры

Исправление ошибок в запросе и получение данных о графике отпусков

Основная проблема исходного кода заключалась в использовании ПОЛНОЕ СОЕДИНЕНИЕ и отсутствии фильтрации по периодам. Когда мы связываем Документ.ПереносОтпуска с Документ.ГрафикОтпусков только по сотруднику, система находит все графики за всю историю работы. Выясним, как получить актуальные данные.

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

Рассмотрим оптимизированный текст запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|	ПереносОтпуска.Ссылка КАК Ссылка,
|	ПереносОтпуска.Номер КАК НомерДокумента,
|	ПереносОтпуска.Дата КАК ДатаДокумента,
|	ПереносОтпуска.Сотрудник КАК Сотрудник,
|	ПереносОтпуска.ФизическоеЛицо КАК ФизическоеЛицо,
|	ПереносОтпуска.ИсходнаяДатаНачала КАК ИсходнаяДатаНачала,
|	ПереносОтпуска.ДатаНачала КАК ДатаНачалаОтпуска,
|	ПереносОтпуска.КоличествоДней КАК КоличествоДней,
|	ПереносОтпуска.ПричинаПереноса КАК ПричинаПереноса,
|	ПереносОтпуска.Организация.НаименованиеПолное КАК ОрганизацияНаименование,
|	ПереносОтпуска.Руководитель КАК Руководитель,
|	ПереносОтпуска.ДолжностьРуководителя КАК ДолжностьРуководителя,
|	ГрафикОтпусков.Номер КАК НомерГрафика,
|	ГрафикОтпусков.Дата КАК ДатаГрафика,
|	КадроваяИстория.Должность КАК ДолжностьСотрудника,
|	КадроваяИстория.Подразделение КАК ПодразделениеСотрудника
|ИЗ
|	Документ.ПереносОтпуска КАК ПереносОтпуска
|		ЛЕВОЕ СОЕДИНЕНИЕ Документ.ГрафикОтпусков.Сотрудники КАК ГрафикОтпусковСотрудники
|			ЛЕВОЕ СОЕДИНЕНИЕ Документ.ГрафикОтпусков КАК ГрафикОтпусков
|			ПО ГрафикОтпусковСотрудники.Ссылка = ГрафикОтпусков.Ссылка
|				И (ГОД(ГрафикОтпусков.ДатаРегистрации) = ГОД(ПереносОтпуска.ИсходнаяДатаНачала))
|		ПО ПереносОтпуска.Сотрудник = ГрафикОтпусковСотрудники.Сотрудник
|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПараметрыПериодовСтажа.СрезПоследних(&ДатаСреза, ) КАК КадроваяИстория
|		ПО ПереносОтпуска.Сотрудник = КадроваяИстория.Сотрудник
|ГДЕ
|	ПереносОтпуска.Ссылка В(&МассивОбъектов)";

Запрос.УстановитьПараметр("МассивОбъектов", МассивОбъектов);
Запрос.УстановитьПараметр("ДатаСреза", ТекущаяДата()); // Или дата документа
РезультатЗапроса = Запрос.Выполнить();

Отказ от самописных падежей в пользу БСП

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

  1. Встроенные механизмы БСП учитывают пол физического лица, хранящийся в базе.
  2. Система корректно обрабатывает исключения и сложные фамилии.
  3. Код становится чище и легче в поддержке.

Рассмотрим пример того, как просклонять ФИО сотрудника в родительный падеж (кто? — сотрудник, нет кого? — сотрудника):


// Получаем ФИО в родительном падеже (Падеж номер 2)
ФИОСотрудника = ФизическиеЛицаЗарплатаКадры.ПросклонятьФИО(Выборка.ФизическоеЛицо.ФИО, 2, Выборка.ФизическоеЛицо.Пол);

// Если нужно просклонять должность или подразделение
ДолжностьВПадеже = СклонениеПредставленийОбъектов.ПросклонятьПредставление(Выборка.ДолжностьСотрудника, 2);

Формирование табличного документа

Разберем процесс вывода данных в макет. Важно помнить про разделение страниц, если мы печатаем несколько документов сразу. Проанализируем пример кода:


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

Выборка = РезультатЗапроса.Выбрать();
ПервыйДокумент = Истина;

Пока Выборка.Следующий() Цикл
    Если Не ПервыйДокумент Тогда
        ТабДок.ВывестиГоризонтальныйРазделительСтраниц();
    КонецЕсли;
    
    // Заполнение параметров
    ОбластьМакета.Параметры.Заполнить(Выборка);
    
    // Склонение через БСП
    ОбластьМакета.Параметры.ФИОСотрудника = ФизическиеЛицаЗарплатаКадры.ПросклонятьФИО(Выборка.ФизическоеЛицо.ФИО, 2, Выборка.ФизическоеЛицо.Пол);
    ОбластьМакета.Параметры.ДатаДокумента = Формат(Выборка.ДатаДокумента, "ДФ='""дд"" MMMM гггг ""г.""'");
    
    // Вывод в итоговый документ
    ТабДок.Вывести(ОбластьМакета);
    ПервыйДокумент = Ложь;
КонецЦикла;

Возврат ТабДок;

Подведем итоги

Разберем основные моменты, которые мы улучшили:

Используя эти методы, вы создадите надежную и быструю внешнюю печатную форму, которая будет соответствовать стандартам разработки фирмы 1С и корректно работать в любых условиях эксплуатации.

← На главную