При разработке сложных отчетов в системе компоновки данных (СКД) нередко возникает необходимость комбинировать несколько источников данных: например, Набор данных – Объект (внешняя таблица значений, сформированная программно) и Набор данных – Запрос (выборка данных из базы 1С). При попытке вывести в отчет одновременно несколько дочерних реквизитов через точку из ссылочных полей набора-объекта (например, ЗаказПокупателя.Ответственный и ЗаказПоставщику.Номер) система может аварийно прервать компоновку с ошибкой: «Использование полей из не связанных наборов данных не допустимо».
Разберем детально механизм возникновения этой ошибки и рассмотрим надежные варианты ее устранения.
Проанализируем внутреннюю архитектуру работы СКД со ссылочными типами данных:
ЗаказПокупателя.Ответственный, СКД на этапе компоновки автоматически создает скрытый (служебный) набор данных – запрос, довыбирающий реквизиты из базы.ЗаказПокупателя и ЗаказПоставщику), СКД пытается сгенерировать независимые служебные запросы для каждого из них. При наличии внешнего соединения с другим набором платформа не может корректно связать эти динамические служебные наборы между собой в рамках одной строки отчета, что и приводит к ошибке.Наиболее архитектурно правильный способ решения проблемы — отказаться от разделения на набор-объект и набор-запрос. Если передать исходную таблицу значений во временную таблицу, всю схему можно построить на единственном наборе данных — запросе.
Рассмотрим по шагам программную реализацию передачи таблицы через МенеджерВременныхТаблиц:
// Создаем менеджер временных таблиц и помещаем в него готовую Таблицу Значений
МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос.Текст =
"ВЫБРАТЬ
| ТЗ.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
| ТЗ.ЗаказПокупателя КАК ЗаказПокупателя,
| ТЗ.ЗаказПоставщику КАК ЗаказПоставщику
|ПОМЕСТИТЬ ВТ_ДанныеОбъекта
|ИЗ
| &ВнешняяТаблица КАК ТЗ";
Запрос.УстановитьПараметр("ВнешняяТаблица", ТаблицаЗначений);
Запрос.Выполнить();
// Передаем МенеджерВТ в настройки процессора компоновки
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
ПроцессорКомпоновки.УстановитьМенеджерВременныхТаблиц(МенеджерВТ);
В самой схеме СКД создаем единственный Набор данных – Запрос, где соединяем ВТ_ДанныеОбъекта с реальными таблицами базы. В этом случае любое обращение через точку будет выполнено силами СУБД без скрытых служебных наборов.
Если структура выгрузки фиксирована, выясним причину довыборки и устраним ее на этапе формирования таблицы. Добавим все необходимые реквизиты отдельными колонками в исходную таблицу значений до ее передачи в СКД.
Посмотрим на пример: вместо передачи чистой ссылки ЗаказПокупателя добавим колонки ОтветственныйЗаказа и НомерЗаказаПоставщика непосредственно в структуру таблицы. Тогда в СКД не потребуется раскрывать реквизиты через точку, и конфликт служебных наборов будет исключен.
Если пользователям необходим произвольный доступ к реквизитам документов, но переделывать структуру отчета на менеджер временных таблиц нецелесообразно, используем механизм вычисляемых полей СКД.
Разберем по шагам настройку вычисляемого поля:
ОтветственныйЗаказаПокупателя.ОбщегоНазначения.ПолучитьЗначениеРеквизита(ЗаказПокупателя, "Ответственный") (или аналогичной функции БСП).При таком подходе СКД не генерирует скрытые наборы данных, а значение реквизита вычисляется точечно для каждой строки через программный интерфейс.
Проанализируем типы данных колонок в схеме компоновки. Если колонкам набора-объекта не задан строгий тип (остался составной или неопределенный), СКД не может корректно построить цепочку неявных связей.
ЗаказПокупателя в колонке Тип значения снимем все лишние типы и оставим строго ДокументСсылка.ЗаказПокупателя.ЗаказПоставщику.Платформенное ограничение срабатывает только тогда, когда взаимоисключающие дочерние поля выводятся в рамках одной строки детальных записей или одной группировки. Если бизнес-логика отчета допускает иерархическое отображение, вынесем ЗаказПокупателя.Ответственный в вышестоящую группировку строк, а ЗаказПоставщику.ВидОперации — во вложенную. В этом случае СКД выполнит компоновку без ошибок.