Как в построителе отчета сделать отбор по полю составного типа без ошибок

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

При работе с объектом ПостроительОтчета в среде 1С:Предприятие 8 часто возникает задача использования в качестве источника данных не запроса, а внешней таблицы значений. Это особенно актуально в различных обработках, таких как "Клиент-Банк", где данные сначала загружаются из файла, обрабатываются, а затем должны быть отфильтрованы пользователем перед финальной записью в базу данных. Однако при использовании полей составного типа (например, когда в одной колонке могут быть и ссылки на справочники, и произвольные строки) разработчики часто сталкиваются с ошибкой: "Неверные параметры в операции сравнения. Нельзя сравнивать поля неограниченной длины и поля несовместимых типов". Разберем детально причины этого поведения и способы исправления ситуации.

Анализ причины возникновения ошибки

Для начала проанализируем, почему ПостроительОтчета выдает подобную ошибку. Несмотря на то, что источником данных является объект ТаблицаЗначений, построитель внутри себя формирует механизмы, аналогичные языку запросов 1С. В языке запросов существует строгое ограничение: поля неограниченной длины (строки с длиной 0 в метаданных) нельзя использовать в условиях сравнения (в предложениях ГДЕ, СОЕДИНЕНИЕ или в параметрах отбора).

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

Решение №1: Явное указание типов при создании таблицы значений

Самый правильный и надежный метод — это корректное описание типов колонок таблицы значений еще на этапе ее создания. Если ваша таблица создается программно, необходимо использовать объект ОписаниеТипов с заданными квалификаторами.

Рассмотрим пример правильного создания колонки с составным типом:


// Определим массив типов для составного поля
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("СправочникСсылка.Контрагенты"));
МассивТипов.Добавить(Тип("СправочникСсылка.Организации"));
МассивТипов.Добавить(Тип("Строка"));

// Важно: создаем квалификаторы строки с ограниченной длиной
КвалификаторыСтроки = Новый КвалификаторыСтроки(150); // Длина 150 символов
ОписаниеСоставногоТипа = Новый ОписаниеТипов(МассивТипов, , КвалификаторыСтроки);

// Добавляем колонку в ТЗ с явно заданным типом
ДокументыКИмпортуДляОтбора.Колонки.Добавить("Контрагент", ОписаниеСоставногоТипа, "Контрагент");

В данном случае, ограничив длину строки (например, до 150 или 1024 символов), мы убираем техническое ограничение на сравнение, и ПостроительОтчета сможет корректно отрабатывать условия фильтрации.

Решение №2: Использование конструкции ВЫРАЗИТЬ в запросе

Если по каким-то причинам вы решили перевести построитель с использования таблицы значений на работу с запросом (например, поместив ТЗ во временную таблицу), вам поможет функция ВЫРАЗИТЬ. Она позволяет принудительно привести поле составного типа к конкретному типу в момент сравнения.

Рассмотрим, как это может выглядеть в тексте запроса построителя:


// В тексте запроса для построителя
"ВЫБРАТЬ
|    ТЗ.НомерДокумента,
|    ВЫРАЗИТЬ(ТЗ.Контрагент КАК Справочник.Контрагенты) КАК КонтрагентСсылка,
|    ВЫРАЗИТЬ(ТЗ.Контрагент КАК СТРОКА(150)) КАК КонтрагентСтрока
|ИЗ
|    &ВнешняяТаблица КАК ТЗ"

Разделение на две колонки или явное приведение типов позволяет избежать конфликтов при сравнении разных типов данных внутри одного поля.

Решение №3: Ручное управление доступными полями в ОписанииИсточникаДанных

Иногда бывает полезно программно вмешаться в то, как ПостроительОтчета воспринимает поля источника. У объекта ОписаниеИсточникаДанных есть коллекция Поля, которую можно настроить до того, как передать её построителю.

Проанализируем следующий подход:


Источник = Новый ОписаниеИсточникаДанных(ДокументыКИмпортуДляОтбора);
// Ограничим состав типов для поля отбора вручную, если это необходимо
ПолеКонтрагент = Источник.Поля.Контрагент;
ПолеКонтрагент.ТипЗначения = Новый ОписаниеТипов("СправочникСсылка.Контрагенты"); 
// Теперь в отборе будет доступен только тип Контрагент, что снимет проблему со строками

ПостроительОтчета.ИсточникДанных = Источник;

Этот метод хорош тем, что позволяет оставить в самой таблице значений "грязные" данные (например, строки), но в интерфейсе отбора для пользователя оставить только возможность фильтрации по ссылочному типу.

Важные нюансы при работе с "Неопределено" и пустыми значениями

В полях составного типа часто встречаются пустые значения. Выясним одну важную деталь: ПостроительОтчета может вести себя нестабильно, если в одной колонке перемешаны значения Неопределено и пустые ссылки (например, Справочник.Контрагенты.ПустаяСсылка()).

Для стабильной работы рекомендуется:

  1. Перед передачей таблицы в построитель пройти циклом по данным и заменить все значения Неопределено на пустую ссылку одного из основных типов, входящих в состав.
  2. Если в составе типов есть строка, убедиться, что вместо NULL или Неопределено там находится пустая строка "".

Переход на Систему компоновки данных (СКД)

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

Преимущества СКД в данной ситуации:

Подводя итог, можно сказать, что в 90% случаев проблема с отбором в построителе решается именно установкой КвалификаторыСтроки при создании колонок таблицы значений. Это простое действие позволяет избежать сложной отладки запросов и гарантирует корректную работу пользовательских фильтров.

← На главную