При разработке отчетов на базе Системы компоновки данных (СКД) в 1С программисты и пользователи часто сталкиваются с крайне неприятной ошибкой: «Ошибка в элементе отбора: глобальные элементы отбора обязательно должны использовать поля...». Эта проблема особенно часто проявляется при работе с отчетами по виртуальным таблицам (например, срезам последних регистров сведений, оборотам регистров накопления), где используются параметры дат и периодов.
В этой статье мы подробно разберем, почему возникает данная ошибка, в чем заключается ее глубинная техническая суть, и как правильно настроить схему компоновки данных, чтобы отчет работал стабильно как в конфигураторе, так и в пользовательском режиме.
Для того чтобы понять природу этой ошибки, проанализируем, как СКД обрабатывает отборы. В Системе компоновки данных элемент отбора (объект ЭлементОтбораКомпоновкиДанных) состоит из трех ключевых частей:
Платформа 1С:Предприятие накладывает жесткое технологическое ограничение на глобальные (корневые) отборы отчета. На этом уровне левым значением обязательно должно выступать реальное поле компоновки данных (объект типа ПолеКомпоновкиДанных), которое физически присутствует в выборке или наборе данных (запросе).
Если в глобальном отборе левое значение не является полем выборки, а представляет собой константу или параметр данных (например, ПараметрыДанных.НаДату), система считает такой отбор некорректным. С точки зрения СКД, фильтрация параметров между собой или сопоставление констант не имеет смысла на уровне фильтрации строк результирующего набора данных, из-за чего платформа блокирует выполнение отчета и выводит ошибку.
Чаще всего к этой ошибке приводит некорректное проектирование схемы компоновки данных разработчиком, из-за которого пользователь в режиме «1С:Предприятие» совершает ошибочное действие. Выясним, как это происходит.
В схеме компоновки данных на вкладке «Параметры» для каждого параметра (например, для параметра НаДату или Период) есть колонка «Включать в доступные поля». Если этот флаг установлен, то параметр начинает отображаться в дереве доступных полей отчета наравне с обычными реквизитами (такими как Организация, Контрагент или Сумма).
Когда пользователь открывает настройки отчета и пытается установить отбор, он видит этот параметр в списке доступных полей и перетаскивает его в табличную часть отборов. В результате СКД пытается применить условие вида:
ПараметрыДанных.НаДату Равно [ВыбранноеЗначение]
Так как левое значение здесь — это параметр, а не поле компоновки, отчет мгновенно выдает ошибку.
Как исправить эту ситуацию по шагам:
НаДату).После этого параметр будет отображаться на форме отчета в виде удобного отдельного поля ввода, а не в списке отборов, и СКД обработает его корректно. Для правильной связи элементов формы с настройками компоновки можно использовать решение для стыковки элементов управляемой формы и пользовательских настроек СКД.
Довольно часто разработчики наступают на эти же грабли при написании кода для программного формирования отчетов, расшифровок или при динамической настройке компоновщика перед выводом формы. Для упрощения программной работы и предотвращения ошибок при создании настроек можно использовать модуль-обёртку над объектной моделью СКД.
Рассмотрим пример типичной ошибки, которую совершают программисты при программном добавлении отбора:
// НЕПРАВИЛЬНЫЙ КОД (Вызовет ошибку при выполнении компоновки)
НовыйЭлемент = КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НовыйЭлемент.ЛевоеЗначение = "Организация"; // Здесь передана обычная строка!
НовыйЭлемент.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
НовыйЭлемент.ПравоеЗначение = СсылкаНаОрганизацию;
НовыйЭлемент.Использование = Истина;
Проанализируем этот код. Передавая в свойство ЛевоеЗначение простую строку "Организация", разработчик заставляет систему воспринимать левую часть сравнения как текстовую константу. СКД видит это как отбор вида "Организация" Равно СсылкаНаОрганизацию. Поскольку левая часть не является объектом метаданных компоновки, платформа генерирует ошибку глобального отбора.
Чтобы решить эту проблему, левое значение обязательно нужно инициализировать через специальный объект платформы — ПолеКомпоновкиДанных. Посмотрим на правильный пример программного кода:
// ПРАВИЛЬНЫЙ КОД
НовыйЭлемент = КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
// Инициализируем левое значение как Поле Компоновки Данных:
НовыйЭлемент.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Организация");
НовыйЭлемент.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
НовыйЭлемент.ПравоеЗначение = СсылкаНаОрганизацию;
НовыйЭлемент.Использование = Истина;
Существует важный нюанс в поведении движка СКД, о котором знают далеко не все разработчики. Ограничение на обязательное использование полей компоновки данных проверяется платформой строго на уровне глобального (корневого) отбора отчета.
Если вам действительно необходимо выполнить сравнение параметров данных или констант (например, при сложной логике построения внешних наборов данных, когда нужно динамически отключать определенные ветки расчетов в зависимости от параметров пользователя), этот отбор можно перенести во внутреннюю структуру отчета:
ДетальныеЗаписи или по полю Организация).С этой же ошибкой можно столкнуться при разработке динамических списков документов, справочников или регистров на управляемых формах, поскольку они функционируют на тех же механизмах СКД.
Важное предупреждение: Будьте предельно осторожны при настройке отборов динамического списка в свойствах конфигуратора или программно через свойство формы Список.Отбор. Если вы укажете в качестве левого значения не поле динамического списка, а константу или параметр, система может повести себя непредсказуемо. В старых релизах платформы 1С v8.3 это приводило не просто к выводу сообщения об ошибке, а к мгновенному аварийному завершению работы («вылету») всего клиентского приложения 1С:Предприятие.
Всегда проверяйте, чтобы левая часть отбора динамического списка ссылалась на реквизит, присутствующий в запросе этого списка.