В практике разработки на платформе 1С:Предприятие 8.3 часто возникает задача предоставить пользователю гибкий интерфейс для настройки отборов по данным информационной базы (подобно отчетам СКД), но результат обработки вывести не в табличный документ, а в программную коллекцию — ТаблицаЗначений или реквизит формы. При реализации этого сценария разработчики нередко сталкиваются с ситуацией, когда инициализированный макет компоновки возвращает пустую таблицу или элементы отбора на форме работают некорректно.
Разберем подробно, как правильно инициализировать КомпоновщикНастроекКомпоновкиДанных на управляемой форме, связать его со схемой компоновки и программно получить готовые данные в коллекцию значений.
Проанализируем основные причины, по которым процессор вывода может возвращать пустую таблицу значений даже при наличии данных в информационной базе:
ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений критически важно, чтобы в коллекции Структура передаваемых настроек присутствовала хотя бы одна группировка (например, детальные записи). Если структура пуста, компоновщик не создает узлы данных, и вывод завершается без ошибок, но с пустой таблицей.ВЫБРАТЬ *, СКД оптимизирует исполнение и включает в результирующий запрос только те поля, которые явно указаны в коллекции ВыбранныеПоля группировки или настроек. Без выбранных полей выборка не вернет строк.Компоновщик.ПолучитьНастройки() гарантирует получение результирующих настроек с учетом всех интерактивных изменений. Если же отбор менялся напрямую в свойстве Настройки, вызов ПолучитьНастройки() может вернуть базовое состояние без изменений. В таком случае следует передавать свойство Компоновщик.Настройки напрямую.Рассмотрим, как правильно связать реквизит формы типа КомпоновщикНастроекКомпоновкиДанных с макетом схемы компоновки данных. На управляемых формах контекст схемы должен передаваться через временное хранилище с созданием объекта ИсточникДоступныхНастроекКомпоновкиДанных.
Разберем реализацию в обработчике создания формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Получаем макет схемы компоновки данных из объекта или метаданных
ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
СхемаКомпоновкиДанных = ОбработкаОбъект.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
// Помещаем схему во временное хранилище формы
АдресСхемы = ПоместитьВоВременноеХранилище(СхемаКомпоновкиДанных, УникальныйИдентификатор);
// Создаем источник настроек на основании адреса схемы
ИсточникНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(АдресСхемы);
// Инициализируем реквизит формы КомпоновщикНастроек
КомпоновщикНастроек.Инициализировать(ИсточникНастроек);
// Загружаем настройки по умолчанию из схемы
КомпоновщикНастроек.ЗагрузитьНастройки(СхемаКомпоновкиДанных.НастройкиПоУмолчанию);
КонецПроцедуры
Для отображения отбора пользователю на форму добавляется таблица, свойство ПутьКДанным которой связывается либо с КомпоновщикНастроек.Настройки.Отбор, либо с КомпоновщикНастроек.ПользовательскиеНастройки.
Посмотрим на стандартный механизм вывода результата компоновки в ТаблицаЗначений. Этот способ полностью задействует механизм СКД, включая вычисляемые поля, пользовательские поля и условное оформление:
&НаСервере
Функция ПолучитьТаблицуДанныхСКД()
ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
Схема = ОбработкаОбъект.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
// Получаем актуальные настройки компоновщика
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
// Создаем макет компоновки с указанием генератора для коллекций значений
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновщика = КомпоновщикМакета.Выполнить(
Схема,
Настройки,
,
,
Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений")
);
// Инициализируем процессор компоновки
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновщика);
// Выводим результат в ТаблицуЗначений
ТаблицаДанных = Новый ТаблицаЗначений;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(ТаблицаДанных);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
Возврат ТаблицаДанных;
КонецФункции
В некоторых случаях требуется получить максимальную производительность без прогона данных через процессоры вывода СКД. Для этого можно скомпоновать макет, извлечь из него итоговый сгенерированный текст запроса с учетом всех пользовательских отборов и выполнить его напрямую объектом Запрос.
Рассмотрим пример реализации:
&НаСервере
Функция ВыполнитьСгенерированныйЗапросСКД()
ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
Схема = ОбработкаОбъект.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, КомпоновщикНастроек.ПолучитьНастройки());
// Извлекаем текст запроса первого набора данных
Запрос = Новый Запрос(МакетКомпоновки.НаборыДанных.НаборДанных1.Запрос);
// Переносим значения параметров, сгенерированных компоновщиком
Для Каждого ТекПараметр Из Запрос.НайтиПараметры() Цикл
ИмяПараметра = ТекПараметр.Имя;
Если МакетКомпоновки.ЗначенияПараметров.Найти(ИмяПараметра) <> Неопределено Тогда
Запрос.УстановитьПараметр(ИмяПараметра, МакетКомпоновки.ЗначенияПараметров[ИмяПараметра].Значение);
КонецЕсли;
КонецЦикла;
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Если требуется сохранять и восстанавливать пользовательские настройки отбора (например, в регистре сведений через ХранилищеЗначений), инициализация выполняется следующим образом:
&НаСервере
Процедура ЗагрузитьСохраненныеНастройки(СохраненныеНастройки)
Если ТипЗнч(СохраненныеНастройки) = Тип("НастройкиКомпоновкиДанных") Тогда
// Загружаем настройки напрямую в компоновщик
КомпоновщикНастроек.ЗагрузитьНастройки(СохраненныеНастройки);
КонецЕсли;
КонецПроцедуры
Важный момент: перед загрузкой сохраненных настроек компоновщик обязательно должен быть предварительно проинициализирован объектом ИсточникДоступныхНастроекКомпоновкиДанных, иначе структура типов полей и доступных сравнений не восстановится корректно.