Почему программно установленные параметры в отчете СКД не заполняют данные и как это исправить?

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

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

В этой статье мы подробно разберем, почему возникает такое поведение, проанализируем неочевидные ловушки платформы 1С и СКД, а также рассмотрим правильные методы программной установки параметров.

Ловушка №1: Использование метода НайтиПоНаименованию()

Выясним первопричину проблемы на примере реального кейса. Очень часто для заполнения параметров программисты используют поиск элементов «в лоб» по строковому представлению. Рассмотрим типичный пример кода:


КомпоновщикНастроек.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("ГлБух", Справочники.Должности.НайтиПоНаименованию("Главный бухгалтер"));

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

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

Как правильно решать проблему поиска данных:

  1. Откажитесь от жесткого кодирования строк. Поиск по наименованию — это плохой тон в разработке 1С. Любое изменение названия пользователем в режиме «1С:Предприятие» (например, сокращение «Гл. бухгалтер» вместо «Главный бухгалтер») мгновенно сломает ваш отчет.
  2. Используйте предопределенные элементы. Если сущность заложена в логику конфигурации, обращайтесь к ней через предопределенные данные: ПредопределенноеЗначение("Справочник.Должности.ГлавныйБухгалтер").
  3. Используйте регистры сведений и настройки. Получайте ответственных лиц программно через специализированные срезы регистров сведений (например, ответственные лица организации на дату отчета).

Ловушка №2: Конфликт настроек и пользовательских настроек СКД

Вторая и наиболее частая причина, по которой программно установленные параметры игнорируются системой — это архитектура работы компоновщика настроек СКД. В СКД существует три уровня настроек:

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

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


// Установка значения в основных настройках
ПараметрГлБух = КомпоновщикНастроек.Настройки.ПараметрыДанных.Найти("ГлБух");
Если ПараметрГлБух <> Неопределено Тогда
    ПараметрГлБух.Значение = ИскомаяДолжность;
    ПараметрГлБух.Использование = Истина;
    
    // Проверяем, выведен ли параметр в пользовательские настройки
    Если ПараметрГлБух.ИдентификаторПользовательскойНастройки <> "" Тогда
        // Ищем параметр в пользовательских настройках и устанавливаем значение туда
        ЭлементПользовательскойНастройки = КомпоновщикНастроек.ПользовательскиеНастройки.Элементы.Найти(ПараметрГлБух.ИдентификаторПользовательскойНастройки);
        Если ЭлементПользовательскойНастройки <> Неопределено Тогда
            ЭлементПользовательскойНастройки.Значение = ИскомаяДолжность;
            ЭлементПользовательскойНастройки.Использование = Истина;
        КонецЕсли;
    КонецЕсли;
КонецЕсли;

Использование функций БСП

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


СтандартныеОтчетыКлиентСервер.УстановитьПараметр(КомпоновщикНастроек, "ГлБух", ИскомаяДолжность);

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

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

Переопределение стандартной обработки в ПриКомпоновкеРезультата

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

Разберем этот алгоритм по шагам:


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

Такой подход полностью исключает непредвиденное поведение платформы. Передавая в КомпоновщикМакета.Выполнить настройки, полученные через метод КомпоновщикНастроек.ПолучитьНастройки(), мы гарантируем, что система объединит основные настройки и пользовательские изменения в один результирующий пакет параметров, который будет передан в запрос СКД без каких-либо потерь. Для упрощения подобного программного взаимодействия с объектами СКД подойдёт библиотека-обёртка над объектной моделью СКД.

← На главную