Как программно установить отбор в динамическом списке при открытии формы

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

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

Способ 1. Использование стандартного параметра «Отбор»

Начнем с самого простого и правильного с точки зрения платформы метода — передачи структуры Отбор через параметры метода ОткрытьФорму. Рассмотрим ситуацию: у нас есть список контрагентов, и мы хотим по кнопке открыть список документов «Расход товара», отфильтрованный по текущему контрагенту.

Проанализируем код вызова на стороне клиента:


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

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

Почему стандартный отбор может не работать?

Если вы написали код выше, но форма открылась без фильтра, давайте проанализируем настройки самой формы списка документа РасходТовара. Стандартный механизм работает только при выполнении следующих условий:

  1. Реквизит динамического списка (обычно с именем Список) назначен основным реквизитом формы. В окне редактора формы он выделен жирным шрифтом.
  2. В свойствах динамического списка заполнена Основная таблица (например, Документ.РасходТовара). Если список построен на произвольном запросе без указания основной таблицы, платформа «не знает», к каким полям применять автоматический фильтр.
  3. Имена полей в структуре Отбор (ключи структуры) в точности совпадают с именами полей в динамическом списке или в схеме компоновки данных.

Если хотя бы одно условие не соблюдено, нам придется устанавливать отбор вручную «на той стороне» — в открываемой форме.

Способ 2. Ручная установка отбора в «ПриСозданииНаСервере»

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


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

Этот метод универсален. Он будет работать даже в том случае, если список сложный, построен на произвольном запросе или не является основным реквизитом формы.

Способ 3. Работа с фиксированными настройками

Рассмотрим ситуацию, когда отбор должен быть «жестким». Если мы устанавливаем отбор через Список.Отбор.Элементы, пользователь может зайти в настройки списка и отключить этот фильтр. Если же наша задача — жестко ограничить данные (например, по соображениям прав доступа или логики процесса), мы должны использовать ФиксированныеНастройки.

Проанализируем пример использования фиксированных настроек:


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

Преимущество: такие отборы не видны в стандартном окне «Настроить список», и пользователь не сможет их случайно или намеренно сбросить.

Способ 4. Использование параметра «ЗначениеЗаполнения»

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

Посмотрим на код:


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

В этом случае платформа сделает две вещи одновременно:

  1. Установит визуальный отбор в списке по указанному контрагенту.
  2. При нажатии кнопки «Создать» в открывшейся форме нового документа поле Контрагент будет заполнено автоматически.

Это значительно повышает удобство работы пользователя (UX).

Типичные ошибки и советы

Проанализируем основные причины неудач:

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

Подводя итог, можно сказать: наиболее надежный и гибкий способ — это передача параметров в структуру ОткрытьФорму и их последующая обработка в ПриСозданииНаСервере. Это гарантирует корректную работу фильтров независимо от сложности структуры вашего динамического списка.

← На главную