Как программно установить отбор в динамическом списке по текущему пользователю и исправить ошибку сравнения полей неограниченной длины

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

В практике разработки на платформе 1С:Предприятие 8.3 часто возникает задача ограничить видимость данных в форме списка. Один из наиболее распространенных сценариев — установка фильтра по текущему пользователю. Однако при работе со строковыми полями (например, «Краткий состав», где перечислены участники документа) разработчики часто сталкиваются с неочевидными ошибками платформы. В этой статье мы подробно разберем, почему возникает ошибка «Нельзя сравнивать поля неограниченной длины» и как правильно реализовать программный отбор.

Анализ проблемы: почему стандартный отбор не работает

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

Ошибка выполнения запроса: «Неверные параметры в операции сравнения. Нельзя сравнивать поля неограниченной длины и поля несовместимых типов». Это происходит потому, что в базе данных тип «Строка» может быть ограниченной длины (например, 100 символов) или неограниченной (тип TEXT или MEMO в SQL). Платформа 1С не позволяет выполнять операции сравнения (равенство, вхождение) непосредственно над полями неограниченной длины в запросах динамического списка.

Шаг 1: Подготовка запроса динамического списка

Прежде чем писать программный код установки отбора, нам необходимо изменить схему компоновки данных самого динамического списка. Нам нужно «объяснить» системе, что поле КраткийСоставДок имеет конечную длину. Проанализируем, как это сделать правильно.

  1. Откроем свойства динамического списка в конфигураторе.
  2. Перейдем в настройку Произвольный запрос.
  3. В тексте запроса найдем наше поле и обернем его в функцию ВЫРАЗИТЬ.

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


ВЫБРАТЬ
    ДокументПродажи.Ссылка,
    ДокументПродажи.Дата,
    ДокументПродажи.Номер,
    ВЫРАЗИТЬ(ДокументПродажи.КраткийСоставДок КАК СТРОКА(1000)) КАК КраткийСоставДок
ИЗ
    Документ.Продажи КАК ДокументПродажи

Важный момент: Мы ограничили длину строки до 1000 символов. Этого обычно достаточно для перечисления имен пользователей, и это позволяет SQL-серверу эффективно индексировать и сравнивать эти данные. Теперь поле перестало быть «неограниченным», и ошибка сравнения исчезнет.

Шаг 2: Программная установка отбора в форме

Теперь перейдем к написанию кода в модуле формы списка. Лучшим местом для этого является процедура ПриСозданииНаСервере. Мы будем использовать типовую функцию из библиотеки стандартных подсистем (БСП), чтобы обеспечить корректную работу с компоновщиком настроек.

Проанализируем ситуацию: если мы используем вид сравнения Содержит, нам нужно передать строковое значение. Выясним, как правильно получить имя текущего пользователя.


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

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

КонецПроцедуры

В данном коде Список — это основное имя реквизита формы с типом ДинамическийСписок. Если в вашем случае список называется иначе, подставьте соответствующее имя.

Шаг 3: Оптимизация через параметры запроса (Альтернативный способ)

Если документов в базе сотни тысяч, использование отбора с видом сравнения Содержит может замедлить работу формы, так как такой поиск сложно оптимизировать индексами. Рассмотрим более профессиональный и быстрый подход — использование параметров запроса и оператора ПОДОБНО.

Для этого в тексте запроса динамического списка добавим условие ГДЕ:


ВЫБРАТЬ
    ...
ИЗ
    Документ.Продажи КАК ДокументПродажи
ГДЕ
    ВЫРАЗИТЬ(ДокументПродажи.КраткийСоставДок КАК СТРОКА(1000)) ПОДОБНО &ИмяПользователяПараметр

Теперь в программном коде нам не нужно устанавливать элемент отбора, достаточно задать значение параметра:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    ЗначениеПоиска = "%" + ПараметрыСеанса.ТекущийПользователь.Наименование + "%";
    Список.Параметры.УстановитьЗначениеПараметра("ИмяПользователяПараметр", ЗначениеПоиска);

КонецПроцедуры

Символы % указывают системе, что искомая подстрока может находиться в любом месте поля КраткийСоставДок.

Разбор типичных ошибок при установке отбора

Рассмотрим несколько ситуаций, которые могут помешать корректной работе кода, описанного выше:

Итоги

Мы выяснили, что для успешной фильтрации динамического списка по текстовому составу участников необходимо:

  1. Ограничить длину строкового поля в запросе с помощью ВЫРАЗИТЬ.
  2. Использовать правильный вид сравнения (Содержит для вхождения или Равно для полного совпадения).
  3. Учитывать типы данных (сравнивать строку со строкой, а ссылку со ссылкой).

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

← На главную