При разработке отчетов на базе системы компоновки данных (СКД) разработчики нередко сталкиваются с ситуацией, когда добавленное в текст запроса поле отображается в конструкторе, но отсутствует в списке доступных полей при выполнении отчета или не выводится в детальных записях. Особенно часто эта проблема проявляется при программном формировании отчета и использовании сложных конструкций с объединением запросов и составными типами данных. Разберем по шагам ключевые причины такого поведения и способы их устранения.
Проанализируем структуру запроса. При использовании конструкции ОБЪЕДИНИТЬ ВСЕ крайне важно соблюдать идентичность типов и порядка полей во всех объединяемых ветках. Если в первой части запроса поле возвращает ссылку на справочник или результат сложного выражения ВЫБОР, а во второй части возвращается несовместимый тип (например, пустая ссылка на документ другого вида), СКД не может корректно определить тип данных результирующего поля.
Посмотрим на типичную ошибку в объединении, когда в первой выборке вычисляется контрагент, а во второй — передается пустая ссылка на документ:
// Ошибочный вариант: типы в колонках не совпадают
ВЫБРАТЬ
...
Контрагент КАК Контрагент
ИЗ
РегистрНакопления.СвободныеОстатки.Обороты(...)
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
...
ЗНАЧЕНИЕ(Документ.ЗаказКлиента.ПустаяСсылка)
ИЗ
РегистрНакопления.ТоварыКОтгрузке.Остатки(...)
Чтобы компоновщик данных однозначно определил тип поля во всех наборах, приведем пустые значения во второй части запроса к правильному ссылочному типу:
// Корректный вариант: типизация пустой ссылки
ВЫБРАТЬ
...
Контрагент КАК Контрагент
ИЗ
РегистрНакопления.СвободныеОстатки.Обороты(...)
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
...
ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка) КАК Контрагент
ИЗ
РегистрНакопления.ТоварыКОтгрузке.Остатки(...)
Рассмотрим блок расширения СКД {ВЫБРАТЬ ...}. Если поле формируется конструкцией ВЫБОР и в разных условиях возвращает принципиально разные объекты метаданных (например, в одной ветке Справочник.Контрагенты, а в другой — Справочник.Склады), указание модификатора разыменования .* вызывает ошибку генерации структуры полей. СКД пытается построить дерево дочерних реквизитов, но сталкивается с несовместимыми ссылочными типами.
Для исправления ситуации выполним следующие действия:
.* для составного поля, оставив только его имя: {ВЫБРАТЬ Контрагент} вместо {ВЫБРАТЬ Контрагент.*}.Контрагент и отдельно СкладПолучатель).При обращении через точку к реквизитам поля составного типа (например, Регистратор.ЗаказКлиента.Контрагент) платформа генерирует множественные неявные левые соединения ко всем возможным таблицам документов регистратора. Если тип не ограничен, СКД может потерять информацию о составе реквизитов.
Разберем, как правильно типизировать составные ссылки с помощью функции ВЫРАЗИТЬ или использовать явные соединения с таблицами метаданных:
ВЫБОР
КОГДА СвободныеОстаткиОбороты.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
ТОГДА ВЫРАЗИТЬ(СвободныеОстаткиОбороты.Регистратор КАК Документ.РеализацияТоваровУслуг).ЗаказКлиента.Контрагент
ИНАЧЕ NULL
КОНЕЦ КАК Контрагент
В конфигурациях «1С:ERP Управление предприятием» и «1С:Управление торговлей 11» оптимальным решением является получение партнера напрямую и последующее явное левое соединение со справочником контрагентов:
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты
ПО ЗаказКлиента.Партнер = Контрагенты.Партнер
Выясним причину, почему при полностью программном формировании отчета поле может отсутствовать в доступных полях, даже если запрос составлен корректно. Список доступных полей формируется на основе объекта ИсточникДоступныхНастроекКомпоновкиДанных. Если схема компоновки или ее наборы данных модифицируются динамически в коде, компоновщик настроек требует обязательной повторной инициализации.
Посмотрим на правильный порядок программной инициализации и добавления поля в выбранные поля вывода:
// 1. Инициализируем компоновщик настроек схемой
КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновкиДанных));
КомпоновщикНастроек.ЗагрузитьНастройки(СхемаКомпоновкиДанных.НастройкиПоУмолчанию);
// 2. Явно добавляем поле в выбранные поля группировки или детальных записей
Настройки = КомпоновщикНастроек.Настройки;
ВыбранноеПоле = Настройки.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("Контрагент");
ВыбранноеПоле.Использование = Истина;
// 3. Выполняем компоновку макета
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
Важный момент: если текст запроса набора данных формируется программно, коллекция СхемаКомпоновкиДанных.НаборыДанных.НаборДанных1.Поля не обновляется автоматически. В этом случае необходимо либо вручную создать и описать экземпляр ПолеНабораДанныхСхемыКомпоновкиДанных, либо инициализировать структуру через конструктор схемы компоновки.