Как правильно установить отбор по договору в динамическом списке 1С

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

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

Выясняем причину ошибки отображения типов

Проанализируем ситуацию, описанную в сообщении №10. При попытке установить отбор возникает ошибка: Ошибка отображения типов: Отсутствует отображение для типа 'ПолеФормы'. Это происходит потому, что в свойство ПравоеЗначение элемента отбора передается элемент управления формы (визуальный объект), а не само значение, которое в нем содержится.

В управляемом приложении 1С объекты интерфейса (элементы формы) существуют только на клиенте и не могут быть переданы на сервер «как есть». Настройки динамического списка (Компоновщик настроек) требуют передачи конкретных ссылок, строк или чисел. Если вы обращаетесь к значению через Элементы.Договор, вы обращаетесь к полю формы. Для корректной работы следует обращаться напрямую к реквизиту формы, к которому привязано это поле (например, просто Договор или Объект.Договор).

Способ 1: Использование коллекции элементов отбора

Рассмотрим стандартный способ установки отбора через обращение к элементам компоновки данных динамического списка. Этот метод универсален и подходит для списков, работающих как на основе основной таблицы, так и на основе произвольного запроса.

Процедуру установки отбора лучше всего выносить на сервер. Разберем по шагам создание нового элемента отбора:


&НаСервере
Процедура УстановитьОтборНаСервере()
    
    // 1. Очищаем старые отборы по этому полю, чтобы избежать дублирования
    ПолеОтбора = Новый ПолеКомпоновкиДанных("Договор");
    
    Индекс = 0;
    Пока Индекс < Список.Отбор.Элементы.Количество() Цикл
        Элемент = Список.Отбор.Элементы[Индекс];
        Если ТипЗнч(Элемент) = Тип("ЭлементОтбораКомпоновкиДанных") 
            И Элемент.ЛевоеЗначение = ПолеОтбора Тогда
            Список.Отбор.Элементы.Удалить(Элемент);
        Иначе
            Индекс = Индекс + 1;
        КонецЕсли;
    КонецЦикла;

    // 2. Добавляем новый элемент отбора
    НовыйОтбор = Список.Отбор.Эelements.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    НовыйОтбор.ЛевоеЗначение  = ПолеОтбора;
    НовыйОтбор.ВидСравнения   = ВидСравненияКомпоновкиДанных.Равно;
    НовыйОтбор.Использование  = Истина;
    
    // Важно: передаем реквизит (ссылку), а не элемент формы!
    НовыйОтбор.ПравоеЗначение = Объект.Договор; 

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

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

Способ 2: Фиксированные настройки против пользовательских

Выясним, в чем разница между различными коллекциями компоновщика настроек, так как это критично для интерфейса пользователя:

  1. ФиксированныеНастройки (FixedSettings): Если мы установим отбор здесь, пользователь не увидит его в стандартном окне «Настройка списка» и не сможет отключить. Это «жесткий» программный фильтр.
  2. ПользовательскиеНастройки (UserSettings): Отбор появится в пользовательском интерфейсе. Это удобно, если вы хотите подставить значение по умолчанию, но оставить пользователю возможность его изменить или сбросить.
  3. Настройки (Settings): Текущие настройки сеанса, которые могут объединять оба предыдущих типа.

Посмотрим на пример установки «жесткого» отбора, который нельзя отключить через интерфейс:


&НаСервере
Процедура УстановитьФиксированныйОтбор()
    
    ГруппаОтбора = Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор;
    ГруппаОтбора.Элементы.Очистить(); // Осторожно: удалит все фиксированные отборы!
    
    НовыйЭлемент = ГруппаОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    НовыйЭлемент.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("Договор");
    НовыйЭлемент.ВидСравнения   = ВидСравненияКомпоновкиДанных.Равно;
    НовыйЭлемент.ПравоеЗначение = Объект.Договор;
    НовыйЭлемент.Использование  = Истина;
    
КонецПроцедуры

Способ 3: Параметры запроса динамического списка

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

Во-первых, в тексте запроса динамического списка должно быть условие:

ГДЕ Таблица.Договор = &ВыбранныйДоговор

Во-вторых, в коде модуля формы мы устанавливаем значение этого параметра:


&НаСервере
Процедура ОбновитьДанныеСписка()
    
    // Используем метод УстановитьЗначениеПараметра для коллекции Параметры
    Список.Параметры.УстановитьЗначениеПараметра("ВыбранныйДоговор", Объект.Договор);
    
КонецПроцедуры

Преимущество этого метода: Платформа оптимизирует выполнение запроса на уровне СУБД, что работает значительно быстрее на больших объемах данных, чем наложение фильтров поверх результата общего запроса.

Обработка динамического изменения отбора

Если нам нужно, чтобы список обновлялся сразу после того, как пользователь выбрал договор в поле на форме, выполним следующие шаги:

  1. Создадим на форме клиентское событие ПриИзменении для поля выбора договора.
  2. Внутри этого события вызовем серверную процедуру для обновления настроек списка.

&НаКлиенте
Процедура ДоговорПриИзменении(Элемент)
    // Вызываем серверный контекст для работы с динамическим списком
    ОбновитьОтборНаСервере();
КонецПроцедуры

&НаСервере
Процедура ОбновитьОтборНаСервере()
    // Используем упрощенный метод установки параметра, если он задан в запросе
    Список.Параметры.УстановитьЗначениеПараметра("Договор", Объект.Договор);
КонецПроцедуры

Важные рекомендации по работе с типами

Рассмотрим еще несколько важных моментов, которые помогут избежать ошибок:

Таким образом, мы разобрали основные способы программного управления отборами в динамическом списке. Главный секрет успеха — четкое понимание того, где находятся ваши данные (в реквизитах, а не в элементах формы) и какой механизм (параметры или отборы) лучше подходит для конкретной задачи производительности.

← На главную