Как программно запустить отчет СКД с передачей параметров и использованием внешних наборов данных

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

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

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

Анализ проблемы: почему параметры не применяются

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

Основная причина заключается в архитектуре СКД. У компоновщика настроек есть три уровня:

  1. Общие настройки (Настройки): Те, что заданы в схеме компоновки или изменены программно.
  2. Пользовательские настройки: Те, которые пользователь видит на форме (флажки, поля ввода).
  3. Фиксированные настройки: Настройки, которые нельзя изменить через интерфейс.

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

Шаг 1. Программный вызов формы и установка параметров

Для начала разберем, как правильно подготовить форму отчета к запуску. Вместо того чтобы просто присваивать значение через НайтиЗначениеПараметра, лучше использовать метод УстановитьЗначениеПараметра. Он автоматически включает использование параметра.

Проанализируем правильный подход к инициализации формы:


// В коде вызова (например, в обработке)
Форма = ПолучитьФорму("Отчет.ТабельБН.Форма");

// Устанавливаем параметр непосредственно в настройках компоновщика формы
ИмяПараметра = "Подразделение";
ЗначениеПараметра = Справочники.Подразделения.НайтиПоНаименованию("Отдел ИТ");

Форма.Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра(ИмяПараметра, ЗначениеПараметра);

// Открываем форму и запускаем формирование
Форма.Открыть();
Форма.СкомпоноватьРезультат();

Обратите внимание: если параметр выведен в пользовательские настройки на форме, после установки значения в Настройки.ПараметрыДанных рекомендуется убедиться, что эти изменения отразились в ПользовательскиеНастройки, иначе визуально пользователь увидит старое значение.

Шаг 2. Реализация процедуры ПриКомпоновкеРезультата в модуле объекта

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

Разберем по шагам код процедуры ПриКомпоновкеРезультата:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    // 1. Отключаем стандартный механизм, так как будем выводить результат вручную
    СтандартнаяОбработка = Ложь;
    ДокументРезультат.Очистить();
    
    // 2. Получаем настройки из компоновщика. 
    // Важно: на этом этапе может произойти потеря программно установленных параметров,
    // если они не были синхронизированы с пользовательскими настройками.
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();
    
    // 3. Решение проблемы "потери" параметра (так называемый "костыль")
    // Проверяем, есть ли значение в основных настройках компоновщика
    ЭлементПараметра = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("Подразделение");
    Если ЭлементПараметра <> Неопределено И ЗначениеЗаполнено(ЭлементПараметра.Значение) Тогда
        // Принудительно устанавливаем значение в объект настроек, который пойдет в макет
        ПараметрОбъекта = Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("Подразделение"));
        Если ПараметрОбъекта <> Неопределено Тогда
            ПараметрОбъекта.Значение = ЭлементПараметра.Значение;
            ПараметрОбъекта.Использование = Истина;
        КонецЕсли;
    КонецЕсли;
    
    // 4. Подготовка внешних наборов данных
    ВнешниеНаборыДанных = Новый Структура;
    // Предположим, функции ПользователиИБ() и КонтактнаяИнформация() возвращают Таблицы Значений
    ВнешниеНаборыДанных.Вставить("ПользователиИБ", ПолучитьТаблицуПользователей()); 
    ВнешниеНаборыДанных.Вставить("КонтактнаяИнформация", ПолучитьТаблицуКонтактов(Настройки));
    
    // 5. Создание макета компоновки
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
    
    // 6. Инициализация процессора компоновки с передачей внешних наборов
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки, Истина);
    
    // 7. Вывод результата в табличный документ
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
КонецПроцедуры

Почему это работает?

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

Использование конструкции Настройки = КомпоновщикНастроек.ПолучитьНастройки() критически важно, так как именно этот метод собирает воедино отборы, группировки и параметры, установленные пользователем "здесь и сейчас". Однако, как показала практика, параметры, установленные кодом КомпоновщикНастроек.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра(...), иногда не попадают в результат ПолучитьНастройки(), если они перекрываются пустыми пользовательскими настройками. Наш метод «ручной дозаписи» параметра в объект Настройки гарантирует, что КомпоновщикМакета увидит нужное значение.

Дополнительные рекомендации

Для того чтобы сделать ваш код более надежным и чистым, придерживайтесь следующих правил:

  1. Используйте Фиксированные настройки: Если параметр отчета является обязательным и не должен меняться пользователем (например, фильтр по организации в специализированном АРМ), устанавливайте его в КомпоновщикНастроек.ФиксированныеНастройки. Эти настройки имеют высший приоритет и никогда не теряются при вызове ПолучитьНастройки().
  2. Проверяйте Использование: Всегда устанавливайте свойство Использование = Истина для параметров, которые вы задаете программно. Без этого флага значение будет проигнорировано процессором компоновки, даже если оно заполнено.
  3. Передача через параметры формы: В современной платформе 8.3 самый изящный способ — передавать настройки в структуру параметров при открытии формы. Ключ ПользовательскиеНастройки или Отбор в параметрах формы позволяет системе самой инициализировать компоновщик правильно еще до момента отображения окна пользователю.

Таким образом, мы выяснили причину проблемы и нашли эффективный способ её решения. Программное управление процессом компоновки СКД — мощный инструмент, требующий внимательного отношения к коллекциям настроек и понимания жизненного цикла объектов компоновки.

← На главную