К статье
Практический материал

Разработка и Конфигурация · 13 мин

1С 8: как открыть форму выбора с отбором

Как в 1С 8.3 открыть форму выбора с отбором: параметры формы, ОткрытьФорму, ОповеститьОВыборе, работа с динамическим списком и типичные ошибки разработчика.

Открытие формы выбора с отбором — одна из самых частых задач при доработке конфигураций на управляемых формах 1С 8.3. Типовой сценарий: пользователь выбирает контрагента в документе, а в списке должны быть видны только поставщики, только контрагенты конкретной организации или только непомеченные на удаление элементы. Реализуется это через параметры формы, которые передаются при вызове ОткрытьФорму() или ОткрытьФормуМодально().

Ключевой механизм — параметр Отбор, который платформа автоматически применяет к динамическому списку формы выбора. Дополнительно используются параметры РежимВыбора, МножественныйВыбор, ЗакрыватьПриВыборе и ТекущаяСтрока. Важно понимать: отбор, переданный через параметры, пользователь не сможет снять стандартными средствами, если не предусмотреть это отдельно — именно этим параметрический отбор отличается от пользовательских настроек списка.

Ниже разобраны рабочие варианты кода: передача отбора из формы документа, открытие выбора из командной панели, обработка результата выбора через ОповещениеОВыборе и ОписаниеОповещения, а также программная установка отбора внутри самой формы выбора. Примеры приведены для управляемого приложения; для обычных форм синтаксис отличается и рассматривается отдельно.

Базовый способ: ОткрытьФорму с параметром «Отбор»

Самый простой вариант — передать отбор при открытии формы выбора справочника. Платформа сама применит его к динамическому списку, и пользователь увидит уже отфильтрованные данные:

&НаКлиенте

Процедура ВыбратьПоставщика(Команда)

ПараметрыФормы = Новый Структура;

ПараметрыФормы.Вставить("Отбор", Новый Структура("Поставщик", Истина));

ПараметрыФормы.Вставить("РежимВыбора", Истина);

ПараметрыФормы.Вставить("ЗакрыватьПриВыборе", Истина);

ОткрытьФорму("Справочник.Контрагенты.ФормаВыбора",

ПараметрыФормы, ЭтотОбъект, УникальныйИдентификатор);

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

Структура внутри ключа Отбор работает по принципу «И»: все указанные условия применяются одновременно. Например, Новый Структура("Поставщик, ПометкаУдаления", Истина, Ложь) покажет только поставщиков без пометки удаления. Значения могут быть примитивных типов, ссылками, а также массивами или списками значений — тогда отбор сработает по условию «в списке».

Параметр РежимВыбора = Истина переводит форму в режим выбора: у списка появляется кнопка выбора, а двойной щелчок по строке возвращает ссылку. Если форма открывается только для просмотра отфильтрованного списка, этот параметр можно опустить.

Получение результата выбора в вызывающей форме

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

Через событие ОбработкаВыбора

Если при вызове ОткрытьФорму() владельцем указана текущая форма (второй параметр — ЭтотОбъект), то при выборе в ней сработает событие ОбработкаВыбора:

&НаКлиенте

Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)

Если ТипЗнч(ВыбранноеЗначение) = Тип("СправочникСсылка.Контрагенты") Тогда

Объект.Контрагент = ВыбранноеЗначение;

Модифицированность = Истина;

КонецЕсли;

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

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

Через ОписаниеОповещения

Более гибкий вариант — передать описание оповещения, которое выполнится после закрытия формы выбора. Для этого форму открывают с режимом блокировки окна владельца:

&НаКлиенте

Процедура ВыбратьПоставщика(Команда)

ПараметрыФормы = Новый Структура;

ПараметрыФормы.Вставить("Отбор", Новый Структура("Поставщик", Истина));

ПараметрыФормы.Вставить("РежимВыбора", Истина);

Оповещение = Новый ОписаниеОповещения("ПослеВыбораКонтрагента", ЭтотОбъект);

ОткрытьФорму("Справочник.Контрагенты.ФормаВыбора", ПараметрыФормы,

ЭтотОбъект, , , , Оповещение, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);

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

&НаКлиенте

Процедура ПослеВыбораКонтрагента(Результат, ДополнительныеПараметры) Экспорт

Если Результат <> Неопределено Тогда

Объект.Контрагент = Результат;

КонецЕсли;

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

Если пользователь закрыл форму без выбора, в обработчик придёт Неопределено — эту ситуацию нужно обрабатывать обязательно, иначе в реквизит можно записать пустое значение или получить ошибку при обращении к полям результата.

Порядок действий
  1. 1
    Сформируйте структуру параметров с ключом «Отбор» и условиями по реквизитам
  2. 2
    Добавьте РежимВыбора = Истина и при необходимости ЗакрыватьПриВыборе = Истина
  3. 3
    Вызовите ОткрытьФорму с указанием владельца и описания оповещения
  4. 4
    В обработчике оповещения проверьте результат на Неопределено
  5. 5
    Запишите выбранную ссылку в реквизит и установите признак модифицированности

Отбор по нескольким значениям и сложные условия

Условие «в списке» передаётся массивом или списком значений. Например, показать контрагентов только двух конкретных групп:

СписокГрупп = Новый Массив;

СписокГрупп.Добавить(ГруппаПоставщики);

СписокГрупп.Добавить(ГруппаПартнеры);

ПараметрыФормы.Вставить("Отбор", Новый Структура("Родитель", СписокГрупп));

Ограничение параметрического отбора — он умеет только равенство и «в списке». Условия «больше», «содержит», «не равно» через структуру Отбор не передаются. Для таких случаев есть два пути.

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

Открытие выбора из поля ввода: событие НачалоВыбора

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

&НаКлиенте

Процедура КонтрагентНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)

СтандартнаяОбработка = Ложь;

ПараметрыФормы = Новый Структура;

ПараметрыФормы.Вставить("Отбор", Новый Структура("Покупатель", Истина));

ПараметрыФормы.Вставить("РежимВыбора", Истина);

ПараметрыФормы.Вставить("ТекущаяСтрока", Объект.Контрагент);

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

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

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

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

Сравнение вариантов

Параметр «Отбор» при ОткрытьФорму

Быстро и без доработки формы выбора; подходит для равенства и «в списке». Не поддерживает сложные виды сравнения.

СвязиПараметровВыбора у поля ввода

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

Отбор внутри формы выбора (ПриСозданииНаСервере)

Полная гибкость, любые виды сравнения; требует доработки формы выбора или расширения.

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

Когда параметрического отбора недостаточно, условие накладывают программно в модуле формы выбора. Типовой приём — принять данные через параметры и построить отбор компоновки:

&НаСервере

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

Если Параметры.Свойство("Организация") Тогда

ЭлементОтбора = Список.КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(

Тип("ЭлементОтбораКомпоновкиДанных"));

ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Организация");

ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;

ЭлементОтбора.ПравоеЗначение = Параметры.Организация;

ЭлементОтбора.Использование = Истина;

ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;

КонецЕсли;

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

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

Ещё один приём — установить свойство динамического списка ПроизвольныйЗапрос и написать собственный текст запроса с условиями и соединениями. Это оправдано, когда отбор зависит от данных других таблиц, например «только номенклатура с положительным остатком на складе». Минус — произвольный запрос сложнее сопровождать, а при неаккуратном написании он может замедлить открытие формы на больших таблицах.

Типичные ошибки
01
Передача отбора по несуществующему реквизиту — форма открывается без отбора или с ошибкой, условие молча игнорируется
02
Отсутствие проверки результата на Неопределено в обработчике оповещения — при отмене выбора реквизит очищается или возникает ошибка
03
Открытие формы без владельца — событие ОбработкаВыбора не срабатывает, выбранное значение теряется
04
Попытка передать сложное условие («содержит», «не равно») через структуру Отбор — поддерживаются только равенство и «в списке»
05
Программный отбор без режима Недоступный — пользователь снимает условие через настройку списка и видит лишние данные

Множественный выбор, подбор и модальный режим

Для подбора нескольких элементов в табличную часть используют параметры МножественныйВыбор = Истина и ЗакрыватьПриВыборе = Ложь. Тогда форма остаётся открытой, а каждый выбор приходит отдельным событием — удобно для подбора товаров в документ:

ПараметрыФормы = Новый Структура;

ПараметрыФормы.Вставить("МножественныйВыбор", Истина);

ПараметрыФормы.Вставить("ЗакрыватьПриВыборе", Ложь);

ПараметрыФормы.Вставить("РежимВыбора", Истина);

ПараметрыФормы.Вставить("Отбор", Новый Структура("ТипНоменклатуры",

Перечисления.ТипыНоменклатуры.Товар));

В ОбработкаВыбора при этом приходит либо массив выбранных ссылок (при множественном выделении и нажатии «Выбрать»), либо одна ссылка при каждом двойном щелчке. Обработчик должен уметь принимать оба варианта и проверять дубли в табличной части.

Метод ОткрытьФормуМодально() считается устаревшим: в веб-клиенте и при отключённой модальности он может не работать. Вместо него используют ОткрытьФорму() с режимом БлокироватьОкноВладельца и описанием оповещения — поведение для пользователя то же, но код совместим со всеми клиентами.

Контрольные точки

Как проверить результат

Содержимое списка после открытия
Норма

Видны только элементы, удовлетворяющие условию отбора

Тревожный признак

Список полный — параметр Отбор не применился, проверьте имя реквизита и ключ структуры

Поведение при отмене выбора
Норма

Реквизит формы не изменился

Тревожный признак

Реквизит очищается — нет проверки результата на Неопределено

Настройка списка пользователем
Норма

Служебный отбор не отображается или недоступен для снятия

Тревожный признак

Пользователь может снять отбор и увидеть лишние данные

Повторное открытие выбора
Норма

Список позиционируется на текущем значении (ТекущаяСтрока)

Тревожный признак

Курсор всегда в начале списка

Частые вопросы

Как открыть форму выбора с отбором в обычном приложении (не управляемом)?

В обычных формах используют метод ПолучитьФорму() или ОткрытьФормуМодально() с передачей структуры отбора, а отбор накладывают через свойство Отбор списка справочника внутри формы: ФормаВыбора.СправочникСписок.Отбор.Реквизит.Установить(Значение). Синтаксис параметрического отбора управляемых форм там не работает.

Можно ли передать отбор по реквизиту табличной части?

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

Почему отбор не применяется, хотя параметр передан?

Чаще всего причина в опечатке в имени реквизита в структуре отбора — платформа не сообщает об этом явно. Также проверьте, что открывается именно форма выбора с динамическим списком, а не произвольная форма, и что у списка не переопределён запрос без нужного поля.

Как запретить пользователю снимать установленный отбор?

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

Чем отличается ОткрытьФорму от ОткрытьФормуМодально для выбора?

ОткрытьФормуМодально возвращает результат прямо в точке вызова и блокирует интерфейс, но не поддерживается в веб-клиенте без режима модальности и считается устаревшим. ОткрытьФорму с описанием оповещения и режимом БлокироватьОкноВладельца даёт тот же пользовательский эффект и работает во всех клиентах.

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

Для журналов документов отбор по дате обычно задаётся стандартной настройкой периода списка, а не структурой «Отбор». Программно можно передать в параметрах значения и в ПриСозданииНаСервере установить отбор по полю «Дата» с видом сравнения «БольшеИлиРавно» и «МеньшеИлиРавно», либо использовать стандартный период динамического списка.

Итог

Что важно запомнить

Отбор при открытии формы выбора передаётся структурой в параметре «Отбор» и поддерживает равенство и «в списке». Результат получайте через ОписаниеОповещения с обязательной проверкой на Неопределено. Сложные условия реализуйте программным отбором внутри формы выбора через расширение, а не изменением типовой конфигурации.