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

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

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

Разбор типовой ошибки: конфликт приоритетов настроек

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

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

Решение №1: Прямая работа с пользовательскими настройками

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


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

    // Аналогично поступаем со вторым параметром (Склады)
    // ... (код для Склады) ...

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

Решение №2: Использование Компоновщика настроек (рекомендуемый метод)

Выясним причину, по которой работа напрямую со схемой через НастройкиПоУмолчанию не всегда удобна. Лучшей практикой считается использование объекта КомпоновщикНастроекКомпоновкиДанных. Даже если вы формируете отчет полностью программно в обработке, компоновщик берет на себя всю «черную магию» по синхронизации основных и пользовательских настроек.

Посмотрим на пример реализации через компоновщик:


&НаСервере
Функция СформироватьСИспользованиемКомпоновщика()
    
    Схема = РеквизитФормыВЗначение("Объект").ПолучитьМакет("СКД");
    
    // Создаем и инициализируем компоновщик
    Компоновщик = Новый КомпоновщикНастроекКомпоновкиДанных;
    Компоновщик.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(Схема));
    Компоновщик.ЗагрузитьНастройки(Схема.НастройкиПоУмолчанию);
    
    // Используем метод УстановитьЗначениеПараметра - это самый безопасный способ
    // Он сам найдет параметр и в основных, и в пользовательских настройках
    Настройки = Компоновщик.Настройки;
    
    ПараметрНоменклатура = Настройки.ПараметрыДанных.Элементы.Найти("Номенклатура");
    Если ПараметрНоменклатура <> Неопределено Тогда
         Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Номенклатура", Номенклатура);
    КонецЕсли;
    
    // Для складов (массив или список значений)
    Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Склады", Склады.ВыгрузитьЗначения());

    // Формируем макет
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки); // Передаем объект настроек из компоновщика
    
    // ... дальнейший вывод в ТабличныйДокумент ...
КонецФункции

Особенности передачи коллекций: Массивы и Списки

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

  1. Тип сравнения в запросе: Если в тексте запроса СКД написано ГДЕ Склад = &Склады, а вы передаете массив, отчет будет пустым или выдаст ошибку типа. Для массива в запросе должен использоваться оператор В (&Склады).
  2. Доступные типы: Убедитесь, что в параметрах СКД для поля «Склады» разрешен список значений или массив.

Если вы хотите передать список значений для выбора в СКД, лучше использовать тип СписокЗначений, так как он более нативен для интерфейса 1С. Однако для программной передачи внутрь запроса Массив подходит идеально.

Дополнительные советы для стабильной работы СКД

Разберем еще несколько важных моментов, которые могут влиять на результат:

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

← На главную