Почему не формируется внешний отчет, сохраненный из конфигурации ЗУП 3.1, и как это исправить?

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

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

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

Причина проблемы: Скрытая логика формирования запроса

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

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

Логика работы следующая:

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

Рассмотрим способы, как заставить внешний отчет работать.

Способ 1. Получение "истинного" запроса через отладчик

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

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

  1. Запустите режим 1С:Предприятие с включенной отладкой.
  2. Откройте типовой отчет внутри конфигурации (тот, который работает).
  3. Откройте Конфигуратор и перейдите в Отладка - Подключение, убедитесь, что сеанс подключен.
  4. Нам нужно найти момент, когда запрос уже сформирован, но компоновка еще не выполнена. В большинстве отчетов на БСП используется общая форма отчета. Однако проще всего перехватить запрос в общем модуле, отвечающем за выполнение отчета в фоне.
  5. Поставьте точку останова в общем модуле (например, в процедуре формирования отчета в модуле менеджера или в момент компоновки). Часто помогает поиск по строке КомпоновщикМакета.Выполнить.

Более простой вариант для типовых отчетов ЗУП — найти место, где вызывается фоновое задание. Обычно это происходит в общей форме отчета:


РезультатФоновогоЗадания = ДлительныеОперации.ВыполнитьВФоне(
    "ВариантыОтчетов.СформироватьОтчетВФоне", 
    ПараметрыФормированияОтчета, 
    ПараметрыЗапуска);

В этой точке в переменной ПараметрыФормированияОтчета уже содержится схема компоновки данных с модифицированным запросом. Нам нужно "вытащить" текст запроса:

  1. Когда сработает точка останова, выделите переменную со схемой или настройками.
  2. Нажмите Shift+F9 (Вычислить выражение).
  3. Раскройте дерево объекта: ПараметрыФормированияОтчета.СхемаКД.НаборыДанных.Данные.Запрос (путь может немного отличаться в зависимости от структуры наборов данных).
  4. Скопируйте полученный текст запроса.

Теперь вернемся к нашему внешнему отчету:

  1. Откройте схему компоновки данных внешнего отчета.
  2. Замените текст запроса в наборе данных на тот, который вы скопировали из отладчика.
  3. Сохраните отчет.

Важно: При таком подходе отчет станет статичным. Если в будущем в базе включат новую функциональную опцию (например, начнут использовать новые начисления), ваш внешний отчет об этом "не узнает", так как запрос в нем жестко зафиксирован.

Способ 2. Правильная настройка модуля объекта (Рекомендуемый)

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

Проблема пустого результата часто связана с тем, что для внешних отчетов не вызывается процедура ПередЗагрузкойНастроекВКомпоновщик, где и происходит магия подмены запроса.

Чтобы исправить это, выполним следующие шаги в модуле объекта внешнего отчета:

Шаг 1. Настройка сведений о внешней обработке

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


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

    // КЛЮЧЕВОЙ МОМЕНТ:
    ПараметрыРегистрации.ОпределитьНастройкиФормы = Истина;
    
    Возврат ПараметрыРегистрации;
    
КонецФункции

Параметр ОпределитьНастройкиФормы = Истина сообщает системе, что при открытии формы отчета нужно обратиться к модулю объекта за инструкциями.

Шаг 2. Реализация процедуры определения настроек

Теперь добавим в модуль объекта процедуру ОпределитьНастройкиФормы. В ней мы должны "подсказать" системе, как инициализировать наш отчет. Часто достаточно просто указать имя схемы компоновки или вызвать инициализацию событий.


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

В некоторых случаях (как указано в обсуждении), проблема решается тем, что внешний отчет начинает восприниматься системой корректно, и срабатывают стандартные подписки на события формирования отчетов ЗУП.

Способ 3. Перенос логики в Модуль Объекта

Бывает, что типовой отчет полностью полагается на код в своем Модуле Менеджера. У внешнего отчета, как известно, модуль менеджера работает ограниченно (к нему трудно обратиться извне в том же контексте). Поэтому код инициализации нужно перенести в Модуль Объекта внешнего отчета.

Рассмотрим пример. В типовом отчете есть событие ПриКомпоновкеРезультата. В нем часто вызывается общий модуль:


// Код в типовом отчете
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    ЗарплатаКадрыОтчеты.ПриКомпоновкеРезультата(ЭтотОбъект, ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка);
    
КонецПроцедуры

Если во внешнем отчете этот код есть, но он не отрабатывает корректно (отчет пустой), значит, общий модуль ЗарплатаКадрыОтчеты не может правильно определить метаданные вашего внешнего файла.

В этом случае вам придется продублировать логику инициализации внутри модуля объекта внешнего отчета. Проанализируйте, что именно делает общий модуль для вашего отчета. Часто он заполняет временные таблицы или параметры.

Например, можно попробовать явно вызвать настройку вариантов отчета в событии ПриКомпоновкеРезультата, имитируя поведение типового:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // Здесь мы можем вручную инициализировать настройки компоновщика, 
    // если типовой механизм не сработал.
    // Часто требуется программно установить текст запроса, 
    // взяв логику из типового модуля менеджера.
    
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();
    
    // ... Ваш код по модификации запроса или настроек ...
    
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
КонецПроцедуры

Альтернативный подход: Расширения конфигурации

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

Если вы добавите отчет в расширение, он останется "частью конфигурации" с точки зрения платформы. В этом случае:

Поэтому, если есть возможность, рекомендуем создавать доработку через механизм расширений, заимствуя типовой отчет и внося изменения непосредственно в расширении.

Резюме

Если внешний отчет из ЗУП 3.1 выдает пустой результат:

  1. Быстрое решение: Запустите типовой отчет в отладке, скопируйте финальный текст запроса из переменной схемы компоновки и вставьте его в макет внешнего отчета.
  2. Правильное решение для внешних файлов: Используйте функцию СведенияОВнешнейОбработке с параметром ОпределитьНастройкиФормы = Истина и реализуйте соответствующую процедуру в модуле объекта.
  3. Современное решение: Используйте расширения конфигурации вместо внешних отчетов.
← На главную