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