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