Почему не срабатывает процедура ПриКомпоновкеРезультата() в отчете СКД и что делать?

Программист 1С v8.3 (Обычные формы)
← На главную

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

Проанализируем типичную ситуацию: вы хотите программно управлять результатом компоновки, например, свернуть все группы строк до определенного уровня. Вы добавляете в модуль объекта отчета следующий код, но он игнорируется системой. Для упрощения написания подобных конструкций и сокращения объема кода можно использовать СКДБилдер: специальный модуль-обертку, который делает работу с объектной моделью СКД более лаконичной.


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;

    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(ЭтотОбъект.СхемаКомпоновкиДанных, ЭтотОбъект.КомпоновщикНастроек.ПолучитьНастройки(), ДанныеРасшифровки);

    ВнешниеНаборыДанных = Новый Структура;
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки, Истина);

    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);

    ПроцессорВывода.НачатьВывод();
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    ПроцессорВывода.ЗакончитьВывод();

    // Цель: свернуть все группировки при открытии
    ДокументРезультат.ПоказатьУровеньГруппировокСтрок(0);
    
    // И другие доработки...
    РасчетШириныКолонок(ДокументРезультат);
КонецПроцедуры

Несмотря на кажущуюся корректность, этот код не работает. Выясним причину.

Причина №1: Пользовательская команда формирования отчета в форме

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

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

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

Решение 1: Модифицировать код в модуле формы

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

Посмотрим на шаги:

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

Пример доработки в форме:


Процедура ПоКнопкеСформироватьОтчет(Кнопка)
    // ... здесь идет код инициализации компоновщика,
    // процессора компоновки и процессора вывода ...

    ТабличныйДокумент = ЭлементыФормы.Результат;
    ТабличныйДокумент.Очистить();
    
    ПроцессорВывода.УстановитьДокумент(ТабличныйДокумент);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);

    // ВОТ ЗДЕСЬ ВАШ КОД
    ТабличныйДокумент.ПоказатьУровеньГруппировокСтрок(0);
    ТабличныйДокумент.АвтоМасштаб = Истина;
    
    // ... дальнейшие действия ...
КонецПроцедуры

Решение 2: Использовать событие ОбработкаПроверкиЗаполнения()

Это более универсальный подход, который особенно полезен, когда отчеты используют общие формы (в "УТ", "ERP", "Альфа-Авто"). Событие ОбработкаПроверкиЗаполнения() вызывается до начала компоновки. Это отличное место для динамической настройки параметров, даже если у вас реализованы две разных схемы в одном отчете СКД и нужно переключаться между ними программно — для этого подойдёт консоль запросов и СКД для отладки отчетов.

Что можно сделать в этом обработчике:

Пример установки заголовка:


Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
    Заголовок = "Реестр требований-накладных";
    Период = НайтиПользовательскийПараметр(КомпоновщикНастроек, Новый ПараметрКомпоновкиДанных("Период"));
    
    Если Период <> Неопределено Тогда
        Заголовок = Заголовок + " с " + Формат(Период.Значение.ДатаНачала, "ДФ=dd.MM.yyyy") 
                              + " по " + Формат(Период.Значение.ДатаОкончания, "ДФ=dd.MM.yyyy");
    КонецЕсли;

    КомпоновщикНастроек.Настройки.ПараметрыВывода.УстановитьЗначениеПараметра("Заголовок", Заголовок);
КонецПроцедуры

Важный нюанс: Фоновое выполнение отчетов

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

Для логирования в фоновых заданиях следует использовать ЗаписьВЖурналРегистрации(). Если ваш код в ПриКомпоновкеРезультата() не отрабатывает, проверьте, не падает ли он из-за попытки вызвать клиентский метод на сервере.

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

← На главную