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