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

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

1С: как из формы выбора передать выбор в форму списка

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

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

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

Ниже разобраны рабочие сценарии с примерами кода для управляемых форм (режим «Такси»), а также типичные ошибки, из-за которых выбор «теряется» по пути между формами.

Как устроено взаимодействие форм выбора и списка

Когда вы открываете форму выбора через ОткрытьФорму() или она открывается автоматически при вводе в поле, платформа запоминает владельца — форму или элемент, инициировавшие открытие. Именно владельцу адресовано оповещение о выборе. Если форма списка не является владельцем формы выбора, стандартное оповещение до неё просто не дойдёт.

Второй важный момент — режим открытия. Если форма выбора открыта не модально (обычный режим управляемого приложения), то ОповеститьОВыборе() — основной способ вернуть результат. Если открытие выполнено через ОткрытьФормуМодально() или с описанием оповещения о закрытии, результат можно получить в обработчике закрытия через Закрыть(Значение).

Практическое следствие: сначала определите, кто владелец формы выбора. Если форму выбора открывает сама форма списка — задача решается штатным ОбработкаВыбора. Если форму выбора открывает третья форма (например, рабочий стол или другая форма), а результат нужен списку — потребуется общее оповещение через Оповестить().

Сценарий 1: форма списка сама открывает форму выбора

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

В форме выбора при выборе элемента (или в команде «Выбрать») вызовите:

&НаКлиенте

Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)

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

ОповеститьОВыборе(ВыбраннаяСтрока);

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

В форме списка, которая открывала выбор, объявите обработчик:

&НаКлиенте

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

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

УстановитьОтборПоНоменклатуре(ВыбранноеЗначение);

КонецЕсли;

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

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

Порядок действий для штатного сценария
  1. 1
    В форме списка откройте форму выбора через ОткрытьФорму() — владелец установится автоматически
  2. 2
    В форме выбора в обработчике выбора строки вызовите ОповеститьОВыборе(Значение)
  3. 3
    В форме списка добавьте обработчик ОбработкаВыбора и проверьте тип полученного значения
  4. 4
    В обработчике установите отбор динамического списка или обновите данные
  5. 5
    Проверьте: выбор в форме выбора сразу меняет содержимое списка без закрытия форм

Сценарий 2: выбор открывается из другой формы, а результат нужен списку

Если форму выбора открывает не форма списка, а, например, форма обработки или командный интерфейс, то ОповеститьОВыборе() уйдёт не тому получателю. В этом случае используйте глобальное оповещение Оповестить() с уникальным именем события.

В форме выбора:

&НаКлиенте

Процедура Выбрать(Команда)

ТекущиеДанные = Элементы.Список.ТекущиеДанные;

Если ТекущиеДанные = Неопределено Тогда

Возврат;

КонецЕсли;

Оповестить("ВыбранаНоменклатураДляОтбора", ТекущиеДанные.Ссылка, ЭтотОбъект);

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

В форме списка подпишитесь на событие через обработчик ОбработкаОповещения:

&НаКлиенте

Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)

Если ИмяСобытия = "ВыбранаНоменклатураДляОтбора" Тогда

УстановитьОтборПоНоменклатуре(Параметр);

КонецЕсли;

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

Имя события выбирайте уникальным, чтобы не пересечься со стандартными оповещениями платформы (например, «Запись_Номенклатура») и с событиями других механизмов конфигурации. Хорошая практика — включать в имя краткий смысл и объект, например «ОтборСпискаДокументов_ВыбранКонтрагент».

Сценарий 3: передать отбор при открытии формы списка

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

&НаКлиенте

Процедура ОткрытьСписокСОтбором(Команда)

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

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

ОткрытьФорму("Документ.РасходнаяНакладная.ФормаСписка", ПараметрыФормы);

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

Стандартные формы списков типовых объектов автоматически применяют параметр «Отбор» к динамическому списку. Условие: поле, по которому строится отбор, должно быть доступно в запросе динамического списка. Если список построен на произвольном запросе и поле там не выбрано, отбор молча не сработает.

Если нужно не только установить отбор, но и запретить пользователю его снять, добавьте параметр "РежимОтбораИзРасширенногоЗапроса" не поможет — вместо этого в форме списка в обработчике ПриСозданииНаСервере установите элемент отбора программно со свойством РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный.

Установка отбора в динамическом списке программно

Когда значение получено (любым из способов выше), его нужно применить к списку. Работа идёт с коллекцией Список.КомпоновщикНастроек.Настройки.Отбор.Элементы. Чтобы не плодить дубли при повторном выборе, сначала удаляйте старый элемент отбора по тому же полю.

&НаСервере

Процедура УстановитьОтборПоНоменклатуре(НоменклатураСсылка)

ПолеОтбора = Новый ПолеКомпоновкиДанных("Номенклатура");

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

Для Каждого ЭлементОтбора Из ЭлементыОтбора Цикл

Если ЭлементОтбора.ЛевоеЗначение = ПолеОтбора Тогда

ЭлементыОтбора.Удалить(ЭлементОтбора);

КонецЕсли;

КонецЦикла;

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

НовыйЭлемент.ЛевоеЗначение = ПолеОтбора;

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

НовыйЭлемент.ПравоеЗначение = НоменклатураСсылка;

НовыйЭлемент.Использование = Истина;

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

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

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

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

Отбор в списке
Норма

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

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

Список не меняется — оповещение не дошло или обработчик не вызвался

Повторный выбор
Норма

Новый выбор заменяет старый отбор, дублей в отборе нет

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

Отборы накапливаются, список становится пустым

Закрытие формы выбора
Норма

Форма выбора закрывается или остаётся открытой по замыслу, без ошибок в журнале

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

Ошибка «переданный параметр является обязательным» или обращение к закрытой форме

Типичные ошибки и ограничения

Самая частая причина «не работает» — форма выбора открыта без владельца. Это происходит, когда форму открывают из общего клиентского модуля или через ПолучитьФорму() без последующего указания владельца. Оповещение о выборе в этом случае уходит «в никуда», и ОбработкаВыбора в списке никогда не сработает.

Вторая группа ошибок — несовпадение типов. Если форма выбора передаёт строку табличной части или структуру, а обработчик ждёт ссылку, проверка типа молча отсекает значение. Всегда явно проверяйте ТипЗнч() полученного значения и на время отладки выводите его в сообщение.

Третий подводный камень — обращение к реквизитам закрытой формы. Если вы пытаетесь после закрытия формы выбора прочитать её реквизиты через сохранённую ссылку на форму, получите ошибку. Передавайте все нужные данные в момент выбора — в параметре оповещения или возвращаемом значении Закрыть().

Наконец, помните про безопасность данных: программно установленный отбор пользователь может снять через настройки списка, если вы не ограничили доступность элемента отбора. Если отбор является ограничением прав (например, пользователь должен видеть только свои документы), реализуйте его через RLS или параметры динамического списка, а не через видимый пользователю отбор.

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

Сравнение способов передачи выбора

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

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

ОповеститьОВыборе + ОбработкаВыбора

Подходит, когда форма списка сама открывает форму выбора. Штатный механизм, минимум кода. Не работает, если владелец — другая форма.

Оповестить + ОбработкаОповещения

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

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

Подходит, когда форма списка ещё не открыта. Самый надёжный вариант, но не применим к уже открытому списку.

Закрыть(Значение) с описанием оповещения

Подходит при модальном открытии или ОткрытьФорму с ОписаниеОповещения. Результат приходит в момент закрытия формы выбора.

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

Маршрут решения

Как выбрать действие

Форма списка сама открывает форму выбораИспользуйте ОповеститьОВыборе и ОбработкаВыбора
Форму выбора открывает другая форма, список уже открытИспользуйте Оповестить с уникальным именем события и ОбработкаОповещения в списке
Форма списка ещё не открытаПередайте Отбор через параметры ОткрытьФорму
Нужен результат именно после закрытия формы выбораОткройте с ОписаниеОповещения и верните значение через Закрыть(Значение)

Итог

Передача выбора из формы выбора в форму списка сводится к трём вопросам: кто владелец формы выбора, открыт ли уже список и как применить полученное значение к динамическому списку. Штатная связка ОповеститьОВыборе + ОбработкаВыбора закрывает большинство случаев, общее оповещение — нестандартные цепочки открытия, а параметр отбора — момент первого открытия списка.

Итог

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

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

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

Почему ОбработкаВыбора в форме списка не вызывается?

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

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

Да. Включите в форме выбора множественный выбор и передайте массив или список значений в ОповеститьОВыборе. В обработчике списка проверьте тип параметра и установите отбор с видом сравнения «В списке».

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

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

Отбор установился, но пользователь может его снять. Как запретить?

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

Чем ОповеститьОВыборе отличается от Оповестить?

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

Работает ли этот подход в обычных формах?

Механика похожа: в обычных формах также есть ОповеститьОВыборе и ОбработкаВыбора. Отличия в установке отбора — там вместо компоновщика настроек динамического списка используется объект Отбор списка справочника или документа.