Как программно установить отбор «В списке» при открытии формы выбора в 1С?

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

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

Разбор ошибок при ручном формировании отбора

Начнем с разбора ситуации, когда отбор добавляется напрямую в элементы отбора списка формы. В приведенном примере программист столкнулся с двумя проблемами: отбор не работал (список был пуст), а при ручном выборе элемент не переносился в поле ввода документа.

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


Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    СписокДляОтбора.Добавить("Ссылка", ВыборкаДетальныеЗаписи.Номенклатура);
КонецЦикла;

Метод Добавить у объекта СписокЗначений принимает первым параметром само значение, а вторым — представление. В данном коде в качестве значения во все элементы списка записывалась строка "Ссылка", а сама ссылка на номенклатуру уходила в строковое представление. Из-за этого отбор искал элементы по строке "Ссылка" и, естественно, ничего не находил. Правильный вариант заполнения:


Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    СписокДляОтбора.Добавить(ВыборкаДетальныеЗаписи.Номенклатура);
КонецЦикла;

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

ФормаВыбора = ПолучитьФорму("Справочник.Номенклатура.ФормаВыбора", , Элемент);

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

Оптимальные способы передачи отборов (Управляемые формы)

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

  1. Использование параметра «Отбор» в методе ОткрытьФорму

    Самый простой способ — передать структуру отбора непосредственно при открытии. Если в качестве значения свойства структуры передается коллекция (Массив или СписокЗначений), платформа 1С автоматически установит вид сравнения ВСписке. При этом для программного отбора не обязательно конструировать именно список значений, достаточно использовать обычный Массив (его можно быстро получить методом ВыгрузитьКолонку у таблицы значений).

    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("Отбор", Новый Структура("Ссылка", МассивРазрешеннойНоменклатуры));
    ОткрытьФорму("Справочник.Номенклатура.ФормаВыбора", ПараметрыФормы, Элемент);
    
  2. Передача через ФиксированныеНастройки

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

  3. Использование события ОбработкаПолученияДанныхВыбора

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

Ограничения платформы и производительность

Проанализируем подводные камни при работе с видом сравнения ВСписке. При обращении платформы к базе данных этот отбор транслируется в SQL-конструкцию IN (...). Если массив или список значений для отбора содержит сотни или тысячи элементов, это может вызвать сильную деградацию производительности динамического списка или даже привести к ошибке СУБД (из-за ограничений на количество параметров в запросе).

Если список номенклатуры документа-основания велик, оптимальнее отказаться от передачи массива с сервера на клиент и обратно. В таких случаях следует изменять сам текст запроса динамического списка в открываемой форме. Наиболее производительный вариант — модифицировать запрос динамического списка, добавив ВНУТРЕННЕЕ СОЕДИНЕНИЕ с табличной частью документа-основания, из которого необходимо брать разрешенную номенклатуру.

← На главную