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