Разработка и Конфигурация · 13 мин
1С 8: как открыть форму выбора с отбором
Как в 1С 8.3 открыть форму выбора с отбором: параметры формы, ОткрытьФорму, ОповеститьОВыборе, работа с динамическим списком и типичные ошибки разработчика.
Открытие формы выбора с отбором — одна из самых частых задач при доработке конфигураций на управляемых формах 1С 8.3. Типовой сценарий: пользователь выбирает контрагента в документе, а в списке должны быть видны только поставщики, только контрагенты конкретной организации или только непомеченные на удаление элементы. Реализуется это через параметры формы, которые передаются при вызове ОткрытьФорму() или ОткрытьФормуМодально().
Ключевой механизм — параметр Отбор, который платформа автоматически применяет к динамическому списку формы выбора. Дополнительно используются параметры РежимВыбора, МножественныйВыбор, ЗакрыватьПриВыборе и ТекущаяСтрока. Важно понимать: отбор, переданный через параметры, пользователь не сможет снять стандартными средствами, если не предусмотреть это отдельно — именно этим параметрический отбор отличается от пользовательских настроек списка.
Ниже разобраны рабочие варианты кода: передача отбора из формы документа, открытие выбора из командной панели, обработка результата выбора через ОповещениеОВыборе и ОписаниеОповещения, а также программная установка отбора внутри самой формы выбора. Примеры приведены для управляемого приложения; для обычных форм синтаксис отличается и рассматривается отдельно.
Базовый способ: ОткрытьФорму с параметром «Отбор»
Самый простой вариант — передать отбор при открытии формы выбора справочника. Платформа сама применит его к динамическому списку, и пользователь увидит уже отфильтрованные данные:
&НаКлиенте
Процедура ВыбратьПоставщика(Команда)
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Отбор", Новый Структура("Поставщик", Истина));
ПараметрыФормы.Вставить("РежимВыбора", Истина);
ПараметрыФормы.Вставить("ЗакрыватьПриВыборе", Истина);
ОткрытьФорму("Справочник.Контрагенты.ФормаВыбора",
ПараметрыФормы, ЭтотОбъект, УникальныйИдентификатор);
КонецПроцедуры
Структура внутри ключа Отбор работает по принципу «И»: все указанные условия применяются одновременно. Например, Новый Структура("Поставщик, ПометкаУдаления", Истина, Ложь) покажет только поставщиков без пометки удаления. Значения могут быть примитивных типов, ссылками, а также массивами или списками значений — тогда отбор сработает по условию «в списке».
Параметр РежимВыбора = Истина переводит форму в режим выбора: у списка появляется кнопка выбора, а двойной щелчок по строке возвращает ссылку. Если форма открывается только для просмотра отфильтрованного списка, этот параметр можно опустить.
Получение результата выбора в вызывающей форме
После того как пользователь выбрал элемент, ссылку нужно получить и обработать. Есть два подхода, и выбор между ними зависит от того, кто является владельцем открываемой формы.
Через событие ОбработкаВыбора
Если при вызове ОткрытьФорму() владельцем указана текущая форма (второй параметр — ЭтотОбъект), то при выборе в ней сработает событие ОбработкаВыбора:
&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
Если ТипЗнч(ВыбранноеЗначение) = Тип("СправочникСсылка.Контрагенты") Тогда
Объект.Контрагент = ВыбранноеЗначение;
Модифицированность = Истина;
КонецЕсли;
КонецПроцедуры
Этот способ прост, но у него есть ограничение: событие одно на форму, поэтому при нескольких разных вызовах выбора приходится различать источники по типу значения или по дополнительным признакам.
Через ОписаниеОповещения
Более гибкий вариант — передать описание оповещения, которое выполнится после закрытия формы выбора. Для этого форму открывают с режимом блокировки окна владельца:
&НаКлиенте
Процедура ВыбратьПоставщика(Команда)
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Отбор", Новый Структура("Поставщик", Истина));
ПараметрыФормы.Вставить("РежимВыбора", Истина);
Оповещение = Новый ОписаниеОповещения("ПослеВыбораКонтрагента", ЭтотОбъект);
ОткрытьФорму("Справочник.Контрагенты.ФормаВыбора", ПараметрыФормы,
ЭтотОбъект, , , , Оповещение, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораКонтрагента(Результат, ДополнительныеПараметры) Экспорт
Если Результат <> Неопределено Тогда
Объект.Контрагент = Результат;
КонецЕсли;
КонецПроцедуры
Если пользователь закрыл форму без выбора, в обработчик придёт Неопределено — эту ситуацию нужно обрабатывать обязательно, иначе в реквизит можно записать пустое значение или получить ошибку при обращении к полям результата.
- 1Сформируйте структуру параметров с ключом «Отбор» и условиями по реквизитам
- 2Добавьте РежимВыбора = Истина и при необходимости ЗакрыватьПриВыборе = Истина
- 3Вызовите ОткрытьФорму с указанием владельца и описания оповещения
- 4В обработчике оповещения проверьте результат на Неопределено
- 5Запишите выбранную ссылку в реквизит и установите признак модифицированности
Отбор по нескольким значениям и сложные условия
Условие «в списке» передаётся массивом или списком значений. Например, показать контрагентов только двух конкретных групп:
СписокГрупп = Новый Массив;
СписокГрупп.Добавить(ГруппаПоставщики);
СписокГрупп.Добавить(ГруппаПартнеры);
ПараметрыФормы.Вставить("Отбор", Новый Структура("Родитель", СписокГрупп));
Ограничение параметрического отбора — он умеет только равенство и «в списке». Условия «больше», «содержит», «не равно» через структуру Отбор не передаются. Для таких случаев есть два пути.
Первый — открыть форму без параметра отбора, а в обработчике ПриСозданииНаСервере самой формы выбора программно добавить элемент отбора в динамический список через Список.КомпоновщикНастроек.Настройки.Отбор с нужным видом сравнения. Второй — передать в параметрах произвольные значения и в ПриСозданииНаСервере по ним построить отбор. Оба варианта требуют доработки модуля формы выбора, что в типовой конфигурации означает расширение или заимствование формы.
Открытие выбора из поля ввода: событие НачалоВыбора
Когда выбор нужен из поля ввода на форме документа, стандартную кнопку выбора часто заменяют собственной логикой в обработчике НачалоВыбора. Стандартную обработку при этом отключают:
&НаКлиенте
Процедура КонтрагентНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Отбор", Новый Структура("Покупатель", Истина));
ПараметрыФормы.Вставить("РежимВыбора", Истина);
ПараметрыФормы.Вставить("ТекущаяСтрока", Объект.Контрагент);
ОткрытьФорму("Справочник.Контрагенты.ФормаВыбора", ПараметрыФормы, Элемент);
КонецПроцедуры
Обратите внимание на владельца: здесь передан Элемент, а не вся форма. Тогда результат выбора платформа сама поместит в связанные с полем данные — писать ОбработкаВыбора не потребуется. Параметр ТекущаяСтрока позиционирует список на уже выбранном элементе, что удобно пользователю.
Альтернатива без кода — связь параметров выбора. Свойство СвязиПараметровВыбора у поля ввода позволяет декларативно задать отбор по значению другого реквизита формы, например показывать только договоры выбранного контрагента. Этот механизм работает без переопределения НачалоВыбора и предпочтителен там, где условие зависит от другого поля той же формы.
Сравнение вариантов
Быстро и без доработки формы выбора; подходит для равенства и «в списке». Не поддерживает сложные виды сравнения.
Декларативно, без кода; работает только для выбора из поля ввода и зависит от реквизитов той же формы.
Полная гибкость, любые виды сравнения; требует доработки формы выбора или расширения.
Отбор внутри формы выбора и работа с динамическим списком
Когда параметрического отбора недостаточно, условие накладывают программно в модуле формы выбора. Типовой приём — принять данные через параметры и построить отбор компоновки:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Параметры.Свойство("Организация") Тогда
ЭлементОтбора = Список.КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(
Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Организация");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = Параметры.Организация;
ЭлементОтбора.Использование = Истина;
ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
КонецЕсли;
КонецПроцедуры
Режим отображения Недоступный скрывает условие из пользовательских настроек — пользователь не сможет снять этот отбор через «Ещё — Настроить список». Если отбор должен быть видимым, но защищённым от отключения, используют фиксированные настройки: Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор.
Ещё один приём — установить свойство динамического списка ПроизвольныйЗапрос и написать собственный текст запроса с условиями и соединениями. Это оправдано, когда отбор зависит от данных других таблиц, например «только номенклатура с положительным остатком на складе». Минус — произвольный запрос сложнее сопровождать, а при неаккуратном написании он может замедлить открытие формы на больших таблицах.
Множественный выбор, подбор и модальный режим
Для подбора нескольких элементов в табличную часть используют параметры МножественныйВыбор = Истина и ЗакрыватьПриВыборе = Ложь. Тогда форма остаётся открытой, а каждый выбор приходит отдельным событием — удобно для подбора товаров в документ:
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("МножественныйВыбор", Истина);
ПараметрыФормы.Вставить("ЗакрыватьПриВыборе", Ложь);
ПараметрыФормы.Вставить("РежимВыбора", Истина);
ПараметрыФормы.Вставить("Отбор", Новый Структура("ТипНоменклатуры",
Перечисления.ТипыНоменклатуры.Товар));
В ОбработкаВыбора при этом приходит либо массив выбранных ссылок (при множественном выделении и нажатии «Выбрать»), либо одна ссылка при каждом двойном щелчке. Обработчик должен уметь принимать оба варианта и проверять дубли в табличной части.
Метод ОткрытьФормуМодально() считается устаревшим: в веб-клиенте и при отключённой модальности он может не работать. Вместо него используют ОткрытьФорму() с режимом БлокироватьОкноВладельца и описанием оповещения — поведение для пользователя то же, но код совместим со всеми клиентами.
Как проверить результат
Видны только элементы, удовлетворяющие условию отбора
Список полный — параметр Отбор не применился, проверьте имя реквизита и ключ структуры
Реквизит формы не изменился
Реквизит очищается — нет проверки результата на Неопределено
Служебный отбор не отображается или недоступен для снятия
Пользователь может снять отбор и увидеть лишние данные
Список позиционируется на текущем значении (ТекущаяСтрока)
Курсор всегда в начале списка
Частые вопросы
Как открыть форму выбора с отбором в обычном приложении (не управляемом)?
В обычных формах используют метод ПолучитьФорму() или ОткрытьФормуМодально() с передачей структуры отбора, а отбор накладывают через свойство Отбор списка справочника внутри формы: ФормаВыбора.СправочникСписок.Отбор.Реквизит.Установить(Значение). Синтаксис параметрического отбора управляемых форм там не работает.
Можно ли передать отбор по реквизиту табличной части?
Напрямую через параметр «Отбор» — нет, потому что динамический список строится по основной таблице объекта. Варианты решения: произвольный запрос динамического списка с соединением к табличной части или программный отбор внутри формы выбора по предварительно вычисленному списку ссылок.
Почему отбор не применяется, хотя параметр передан?
Чаще всего причина в опечатке в имени реквизита в структуре отбора — платформа не сообщает об этом явно. Также проверьте, что открывается именно форма выбора с динамическим списком, а не произвольная форма, и что у списка не переопределён запрос без нужного поля.
Как запретить пользователю снимать установленный отбор?
Отбор, переданный через параметр «Отбор», пользователь снять не может — он не отображается в настройках списка. Если отбор добавлен программно в форме, установите элементу отбора РежимОтображения = Недоступный либо добавьте условие в ФиксированныеНастройки компоновщика настроек списка.
Чем отличается ОткрытьФорму от ОткрытьФормуМодально для выбора?
ОткрытьФормуМодально возвращает результат прямо в точке вызова и блокирует интерфейс, но не поддерживается в веб-клиенте без режима модальности и считается устаревшим. ОткрытьФорму с описанием оповещения и режимом БлокироватьОкноВладельца даёт тот же пользовательский эффект и работает во всех клиентах.
Как открыть выбор документа с отбором по периоду?
Для журналов документов отбор по дате обычно задаётся стандартной настройкой периода списка, а не структурой «Отбор». Программно можно передать в параметрах значения и в ПриСозданииНаСервере установить отбор по полю «Дата» с видом сравнения «БольшеИлиРавно» и «МеньшеИлиРавно», либо использовать стандартный период динамического списка.
Что важно запомнить
Отбор при открытии формы выбора передаётся структурой в параметре «Отбор» и поддерживает равенство и «в списке». Результат получайте через ОписаниеОповещения с обязательной проверкой на Неопределено. Сложные условия реализуйте программным отбором внутри формы выбора через расширение, а не изменением типовой конфигурации.