Как исправить ошибку СКД «Использование полей из не связанных наборов данных не допустимо» при выводе реквизитов через точку?

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

При разработке сложных отчетов в системе компоновки данных (СКД) нередко возникает необходимость комбинировать несколько источников данных: например, Набор данных – Объект (внешняя таблица значений, сформированная программно) и Набор данных – Запрос (выборка данных из базы 1С). При попытке вывести в отчет одновременно несколько дочерних реквизитов через точку из ссылочных полей набора-объекта (например, ЗаказПокупателя.Ответственный и ЗаказПоставщику.Номер) система может аварийно прервать компоновку с ошибкой: «Использование полей из не связанных наборов данных не допустимо».

Разберем детально механизм возникновения этой ошибки и рассмотрим надежные варианты ее устранения.

Почему возникает эта ошибка

Проанализируем внутреннюю архитектуру работы СКД со ссылочными типами данных:

  1. Разыменование в наборе-запросе: когда поле раскрывается через точку в обычном запросе, платформа 1С на уровне СУБД формирует левое соединение с соответствующей таблицей базы данных. Все данные извлекаются за один SQL-запрос.
  2. Разыменование в наборе-объекте (ТаблицаЗначений): данные таблицы значений уже загружены в оперативную память. Сама таблица не содержит свойств и реквизитов ссылочных объектов. Чтобы получить значение ЗаказПокупателя.Ответственный, СКД на этапе компоновки автоматически создает скрытый (служебный) набор данных – запрос, довыбирающий реквизиты из базы.
  3. Конфликт служебных связей: если в одной группировке или в детальных записях отчета пользователь выбирает реквизиты сразу от двух разных ссылок (например, от ЗаказПокупателя и ЗаказПоставщику), СКД пытается сгенерировать независимые служебные запросы для каждого из них. При наличии внешнего соединения с другим набором платформа не может корректно связать эти динамические служебные наборы между собой в рамках одной строки отчета, что и приводит к ошибке.

Способ 1. Использование менеджера временных таблиц вместо набора-объекта

Наиболее архитектурно правильный способ решения проблемы — отказаться от разделения на набор-объект и набор-запрос. Если передать исходную таблицу значений во временную таблицу, всю схему можно построить на единственном наборе данных — запросе.

Рассмотрим по шагам программную реализацию передачи таблицы через МенеджерВременныхТаблиц:


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

Запрос.УстановитьПараметр("ВнешняяТаблица", ТаблицаЗначений);
Запрос.Выполнить();

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

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

В самой схеме СКД создаем единственный Набор данных – Запрос, где соединяем ВТ_ДанныеОбъекта с реальными таблицами базы. В этом случае любое обращение через точку будет выполнено силами СУБД без скрытых служебных наборов.

Способ 2. Предварительная выборка требуемых полей в таблицу значений

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

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

Способ 3. Вызов функций общих модулей в вычисляемых полях

Если пользователям необходим произвольный доступ к реквизитам документов, но переделывать структуру отчета на менеджер временных таблиц нецелесообразно, используем механизм вычисляемых полей СКД.

Разберем по шагам настройку вычисляемого поля:

  1. Перейдем на вкладку Вычисляемые поля в схеме компоновки данных.
  2. Добавим новое поле, например, ОтветственныйЗаказаПокупателя.
  3. В колонке Выражение пропишем вызов серверной функции: ОбщегоНазначения.ПолучитьЗначениеРеквизита(ЗаказПокупателя, "Ответственный") (или аналогичной функции БСП).

При таком подходе СКД не генерирует скрытые наборы данных, а значение реквизита вычисляется точечно для каждой строки через программный интерфейс.

Способ 4. Проверка типизации полей в наборе данных

Проанализируем типы данных колонок в схеме компоновки. Если колонкам набора-объекта не задан строгий тип (остался составной или неопределенный), СКД не может корректно построить цепочку неявных связей.

  1. Откроем вкладку Наборы данных.
  2. В строке поля ЗаказПокупателя в колонке Тип значения снимем все лишние типы и оставим строго ДокументСсылка.ЗаказПокупателя.
  3. Аналогично строго ограничим тип для поля ЗаказПоставщику.

Способ 5. Разнесение полей по разным уровням группировок

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

← На главную