Форма выбора с отбором в 1С нужна, когда в поле нельзя выбрать что угодно: договор — только контрагента из шапки, номенклатуру — без услуг, характеристику — только своей номенклатуры. Ограничивают выбор параметрами и связями параметров выбора (в конфигураторе, в форме или кодом), отбором при программном открытии формы и кодом самой формы выбора. Ниже — где что настраивается, готовые процедуры для управляемых форм 8.3 и частые ошибки.
На этом механизме держатся типовые конфигурации. В УТ 11.4 у реквизита Договор документа ЗаказКлиента заданы связи Отбор.Контрагент, Отбор.Организация, Отбор.ХозяйственнаяОперация, Отбор.ВалютаВзаиморасчетов (из реквизита Валюта) и параметры Отбор.Статус = «Действует», Отбор.ПометкаУдаления = Ложь. Ещё примеры оттуда же:
ПеремещениеТоваров у реквизита Товары.Номенклатура параметр Отбор.ТипНоменклатуры — массив «Товар, Многооборотная тара»: услугу не выбрать;Товары.Характеристика заказа клиента связь называется просто Номенклатура — это не отбор, а параметр для формы выбора характеристик;КонтактноеЛицо связано с партнёром через Отбор.Владелец в самой форме заказа, а не в метаданных.| Способ | Где задаётся | Когда подходит |
|---|---|---|
| Параметры выбора реквизита | Конфигуратор, свойства реквизита | Постоянное условие для всех форм; действует и в отборах отчётов и списков |
| Связи параметров выбора реквизита | Там же | Значение зависит от другого реквизита или той же строки таблицы |
| Параметры и связи поля формы | Редактор формы, свойства поля | Условие нужно в одной форме |
ПараметрыВыбора, СвязиПараметровВыбора из кода | ПриСозданииНаСервере формы или расширения | Условие вычисляется (настройки, права, опции) или форма типовая |
Отбор в ОткрытьФорму | Команда, НачалоВыбора | Выбор из кнопки, множественный выбор, другая форма |
| Код формы выбора и модуля менеджера | ПриСозданииНаСервере, ОбработкаПолученияДанныхВыбора | ИЛИ, пустые значения, отбор, который можно снять |
По стандарту разработки 1С #std411 то, что одинаково для любой формы, задают в метаданных, а форма и код уточняют условие под сценарий. Параметры выбора реквизита действуют и в отборах отчётов и динамических списков, поэтому их ставят даже у измерений регистров.
Отбор непонятного происхождения в форме выбора ищите в том же порядке: свойства реквизита, свойства поля, код формы (поиск по ПараметрыВыбора), НачалоВыбора поля, ПриСозданииНаСервере формы выбора, ОбработкаПолученияДанныхВыбора в модуле менеджера.
В палитре свойств реквизита (для табличной части — реквизита внутри неё) ищите «Параметры выбора» и «Связи параметров выбора», рядом — «Выбор групп и элементов» и «Быстрый выбор». Параметр выбора — пара «имя — постоянное значение». Связь — имя параметра, реквизит-источник и режим изменения: «Очищать» или «Не изменять».
Имя с префиксом Отбор. становится отбором списка в форме выбора; после точки пишут поле выбираемого объекта, а не реквизит-источник. Такой отбор работает и при вводе по строке, и в быстром выборе. При создании элемента прямо из формы выбора его значения уходят в ДанныеЗаполнения обработчика ОбработкаЗаполнения, и одноимённые реквизиты заполняются сами. Имя без префикса — произвольный параметр: он попадёт в параметры формы выбора и в ОбработкаПолученияДанныхВыбора, а разбирает его ваш код.
Режим «Очищать» стандарт #std411 не рекомендует: зависимое значение очищается даже при повторном выборе того же ведущего и даже когда осталось допустимым. Он уместен, если повторно выбрать то же значение нельзя (ведущее поле — флажок) и каждому зависимому значению соответствует одно ведущее. В остальных случаях — «Не изменять» и проверка кодом.
У поля в редакторе формы есть свои «Параметры выбора» и «Связи параметров выбора». Они дополняют заданные у реквизита: в #std411 разобран пример, где связь из метаданных и связь из формы работают одновременно. Кодом их задают, когда условие вычисляется или типовую форму меняют расширением. Пример — форма документа с реквизитами Организация, Контрагент, Договор (справочник ДоговорыКонтрагентов, имена как в УТ 11 и КА 2), Проект (свой справочник) и табличной частью Товары. В БП 3.0 договор подчинён контрагенту, там нужен Отбор.Владелец.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
НастроитьОграниченияВыбора();
КонецПроцедуры
// Ограничения выбора для полей формы документа.
// Всё на сервере: связи параметров выбора меняют только там.
&НаСервере
Процедура НастроитьОграниченияВыбора()
// Договор: действующие договоры контрагента и организации из шапки
УстановитьСвязьВыбора(Элементы.Договор, "Отбор.Контрагент", "Объект.Контрагент");
УстановитьСвязьВыбора(Элементы.Договор, "Отбор.Организация", "Объект.Организация");
УстановитьПараметрВыбора(Элементы.Договор, "Отбор.Статус",
Перечисления.СтатусыДоговоровКонтрагентов.Действует);
// Проект: проекты контрагента; свой параметр разберёт форма выбора проектов
УстановитьСвязьВыбора(Элементы.Проект, "Отбор.Контрагент", "Объект.Контрагент");
УстановитьПараметрВыбора(Элементы.Проект, "ТолькоОткрытые", Истина);
// Колонка «Номенклатура»: только товары и тара, массив даёт отбор «В списке»
ТипыНоменклатуры = Новый Массив;
ТипыНоменклатуры.Добавить(Перечисления.ТипыНоменклатуры.Товар);
ТипыНоменклатуры.Добавить(Перечисления.ТипыНоменклатуры.МногооборотнаяТара);
УстановитьПараметрВыбора(Элементы.ТоварыНоменклатура, "Отбор.ТипНоменклатуры",
Новый ФиксированныйМассив(ТипыНоменклатуры));
Элементы.ТоварыНоменклатура.ВыборГруппИЭлементов = ГруппыИЭлементы.Элементы;
// Колонка «Характеристика»: номенклатура из текущей строки таблицы
УстановитьСвязьВыбора(Элементы.ТоварыХарактеристика, "Номенклатура",
"Элементы.Товары.ТекущиеДанные.Номенклатура");
КонецПроцедуры
// Добавляет полю параметр выбора, одноимённый заменяет.
// Параметры из редактора формы и из другого кода сохраняются.
&НаСервере
Процедура УстановитьПараметрВыбора(Поле, ИмяПараметра, Значение)
НовыеПараметры = Новый Массив;
Для Каждого Параметр Из Поле.ПараметрыВыбора Цикл
Если Параметр.Имя <> ИмяПараметра Тогда
НовыеПараметры.Добавить(Параметр);
КонецЕсли;
КонецЦикла;
НовыеПараметры.Добавить(Новый ПараметрВыбора(ИмяПараметра, Значение));
Поле.ПараметрыВыбора = Новый ФиксированныйМассив(НовыеПараметры);
КонецПроцедуры
// Добавляет полю связь параметра выбора, одноимённую заменяет.
// По умолчанию режим «Не изменять»: зависимое значение проверяет код формы.
&НаСервере
Процедура УстановитьСвязьВыбора(Поле, ИмяПараметра, ПутьКДанным, Очищать = Ложь)
НовыеСвязи = Новый Массив;
Для Каждого Связь Из Поле.СвязиПараметровВыбора Цикл
Если Связь.Имя <> ИмяПараметра Тогда
НовыеСвязи.Добавить(Связь);
КонецЕсли;
КонецЦикла;
Если Очищать Тогда
Режим = РежимИзмененияСвязанногоЗначения.Очищать;
Иначе
Режим = РежимИзмененияСвязанногоЗначения.НеИзменять;
КонецЕсли;
НовыеСвязи.Добавить(Новый СвязьПараметраВыбора(ИмяПараметра, ПутьКДанным, Режим));
Поле.СвязиПараметровВыбора = Новый ФиксированныйМассив(НовыеСвязи);
КонецПроцедуры
ПараметрыВыбора и СвязиПараметровВыбора — фиксированные массивы, их присваивают только целиком. Процедуры копируют то, что уже есть у поля, и заменяют одноимённый элемент, поэтому настройку можно вызывать повторно, не теряя параметров из редактора формы.СвязиПараметровВыбора сказано, что запись возможна только на сервере, а у объекта ПараметрВыбора в доступности нет веб-клиента.ФиксированныйМассив в значении параметра даёт отбор «В списке». Неопределено значением параметра выбора быть не может."Объект.Контрагент" — путь к данным формы. Для колонки таблицы источник — текущая строка: "Элементы.Товары.ТекущиеДанные.Номенклатура", так же сделано в формах УТ 11.4.СвязьПараметраВыбора по умолчанию — Очищать, поэтому режим передаётся явно.ВыборГруппИЭлементов имеет тип ГруппыИЭлементы, а одноимённый параметр формы выбора — ИспользованиеГруппИЭлементов: перечисления разные.Постоянные условия в своей конфигурации лучше перенести в свойства реквизитов. В расширении этот код вызывают из обработчика заимствованной формы с аннотацией &После("ПриСозданииНаСервере"); про свои реквизиты и поля формы — в статье реквизит формы программно.
При режиме «Не изменять» неподходящий договор убираем сами — и только при реальном несоответствии: если выбран тот же контрагент или договор подходит новой организации, он остаётся.
&НаКлиенте
Процедура КонтрагентПриИзменении(Элемент)
ОчиститьНеподходящийДоговор();
КонецПроцедуры
&НаКлиенте
Процедура ОрганизацияПриИзменении(Элемент)
ОчиститьНеподходящийДоговор();
КонецПроцедуры
// Связи договора заданы с режимом «Не изменять», платформа его не трогает.
// Очищаем, только если договор действительно перестал подходить шапке.
&НаКлиенте
Процедура ОчиститьНеподходящийДоговор()
Если Не ЗначениеЗаполнено(Объект.Договор) Тогда
Возврат;
КонецЕсли;
Если Не ДоговорПодходит(Объект.Договор, Объект.Контрагент, Объект.Организация) Тогда
Объект.Договор = ПредопределенноеЗначение("Справочник.ДоговорыКонтрагентов.ПустаяСсылка");
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ДоговорПодходит(Договор, Контрагент, Организация)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ДоговорыКонтрагентов.Ссылка КАК Ссылка
|ИЗ
| Справочник.ДоговорыКонтрагентов КАК ДоговорыКонтрагентов
|ГДЕ
| ДоговорыКонтрагентов.Ссылка = &Договор
| И ДоговорыКонтрагентов.Контрагент = &Контрагент
| И ДоговорыКонтрагентов.Организация = &Организация";
Запрос.УстановитьПараметр("Договор", Договор);
Запрос.УстановитьПараметр("Контрагент", Контрагент);
Запрос.УстановитьПараметр("Организация", Организация);
Возврат Не Запрос.Выполнить().Пустой();
КонецФункции
Обработчики назначьте полям «Контрагент» и «Организация» на событие «При изменении». При изменении реквизита из кода (заполнение, загрузка, обработка) ПриИзменении не вызывается — проверку запускайте там же. Параметры выбора ограничивают только интерактивный выбор: значение из кода или обмена они не проверяют, поэтому критичные условия дублируют в ОбработкаПроверкиЗаполнения объекта.
Если выбор запускает команда (кнопка «Подобрать» над таблицей), отбор передают параметром Отбор метода ОткрытьФорму: ключ — имя поля основной таблицы списка, а массив или список значений из нескольких элементов дают «В списке». Ниже — открытие формы выбора справочника программно с отбором и множественным выбором.
&НаКлиенте
Процедура ПодобратьТовары(Команда)
// Ключ структуры Отбор - имя поля списка; массив значений даёт «В списке»
ТипыНоменклатуры = Новый Массив;
ТипыНоменклатуры.Добавить(ПредопределенноеЗначение("Перечисление.ТипыНоменклатуры.Товар"));
ТипыНоменклатуры.Добавить(ПредопределенноеЗначение("Перечисление.ТипыНоменклатуры.МногооборотнаяТара"));
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Отбор", Новый Структура("ТипНоменклатуры", ТипыНоменклатуры));
ПараметрыФормы.Вставить("РежимВыбора", Истина);
ПараметрыФормы.Вставить("МножественныйВыбор", Истина);
ПараметрыФормы.Вставить("ЗакрыватьПриВыборе", Истина);
ПараметрыФормы.Вставить("ВыборГруппИЭлементов", ИспользованиеГруппИЭлементов.Элементы);
Оповещение = Новый ОписаниеОповещения("ПодобратьТоварыЗавершение", ЭтотОбъект);
ОткрытьФорму("Справочник.Номенклатура.ФормаВыбора", ПараметрыФормы, ЭтотОбъект, , , ,
Оповещение, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
КонецПроцедуры
&НаКлиенте
Процедура ПодобратьТоварыЗавершение(Результат, ДополнительныеПараметры) Экспорт
Если Результат = Неопределено Тогда
Возврат; // окно закрыли без выбора
КонецЕсли;
// При множественном выборе приходит массив, при одиночном - одна ссылка
Выбранные = Новый Массив;
Если ТипЗнч(Результат) = Тип("Массив") Или ТипЗнч(Результат) = Тип("ФиксированныйМассив") Тогда
Для Каждого Значение Из Результат Цикл
Выбранные.Добавить(Значение);
КонецЦикла;
Иначе
Выбранные.Добавить(Результат);
КонецЕсли;
// НайтиСтроки на клиенте обращается к серверу, поэтому дубли ищем соответствием
УжеЕсть = Новый Соответствие;
Для Каждого СтрокаТоваров Из Объект.Товары Цикл
УжеЕсть.Вставить(СтрокаТоваров.Номенклатура, Истина);
КонецЦикла;
Для Каждого Номенклатура Из Выбранные Цикл
Если УжеЕсть[Номенклатура] = Неопределено Тогда
НоваяСтрока = Объект.Товары.Добавить();
НоваяСтрока.Номенклатура = Номенклатура;
УжеЕсть.Вставить(Номенклатура, Истина);
Модифицированность = Истина;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Параметры формы выбора с динамическим списком:
Отбор — структура «поле — значение», пользователь её не снимет;РежимВыбора — открыть форму списка на выбор;МножественныйВыбор — выбор нескольких строк основной таблицы;ЗакрыватьПриВыборе — закрыть окно после выбора;ВыборГруппИЭлементов — группы, элементы или то и другое;ТекущаяСтрока — ссылка, на которой встанет курсор.Тот же вызов делают в НачалоВыбора поля с СтандартнаяОбработка = Ложь — пример в статье про отбор динамического списка программно. Открывая форму своим кодом, все условия кладите в Отбор сами.
Если основной реквизит формы выбора — динамический список, ключи Отбор платформа применяет к нему после ПриСозданииНаСервере, поэтому там Параметры.Отбор можно прочитать, изменить или удалить из неё ключ. Так делают типовые формы: в УТ 11.4 форма выбора характеристик забирает из отбора Владелец и удаляет его, а форма выбора складов разбирает параметры ВыборГруппыСкладов и ДокументПродажи из параметров выбора реквизита Склад заказа клиента. Если основной реквизит — не динамический список, отбор сам не применится, его разбирают кодом.
Пример — форма выбора своего справочника «Проекты» (реквизиты Контрагент и Закрыт, на форме флажок ТолькоОткрытые). Поле «Проект» передаёт Отбор.Контрагент и ТолькоОткрытые из первого листинга, процедура РасширитьОтборПоКонтрагенту лежит в модуле менеджера — она в следующем листинге.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Ключи Отбор платформа наложит на список после этого обработчика,
// поэтому здесь их можно прочитать, заменить или удалить
Справочники.Проекты.РасширитьОтборПоКонтрагенту(Параметры.Отбор);
// Свой параметр выбора (имя без «Отбор.») читаем через Свойство():
// если форму открыли из меню, а не из поля, его нет
ЗначениеПараметра = Неопределено;
Если Параметры.Свойство("ТолькоОткрытые", ЗначениеПараметра) Тогда
ТолькоОткрытые = (ЗначениеПараметра = Истина);
КонецЕсли;
УстановитьОтборОткрытых(Список, ТолькоОткрытые);
КонецПроцедуры
&НаКлиенте
Процедура ТолькоОткрытыеПриИзменении(Элемент)
УстановитьОтборОткрытых(Список, ТолькоОткрытые);
КонецПроцедуры
// Отбор «Закрыт = Ложь», который пользователь включает и снимает флажком.
&НаКлиентеНаСервереБезКонтекста
Процедура УстановитьОтборОткрытых(Список, Включить)
ПолеЗакрыт = Новый ПолеКомпоновкиДанных("Закрыт");
Для Каждого ЭлементОтбора Из Список.Отбор.Элементы Цикл
Если ТипЗнч(ЭлементОтбора) = Тип("ЭлементОтбораКомпоновкиДанных")
И ЭлементОтбора.ЛевоеЗначение = ПолеЗакрыт Тогда
ЭлементОтбора.Использование = Включить;
Возврат;
КонецЕсли;
КонецЦикла;
ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = ПолеЗакрыт;
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = Ложь;
ЭлементОтбора.Использование = Включить;
КонецПроцедуры
Равенство по контрагенту скрыло бы общие проекты без контрагента, поэтому отбор расширен до массива. Побочный эффект: новый проект из такой формы контрагента не получит — платформа заполняет реквизиты только из отборов «Равно» и «В списке» с одним значением. Свой параметр стал отбором, который снимается флажком; жёсткий Отбор.Закрыт снять было бы нельзя.
При вводе по строке форма выбора не открывается: варианты формирует платформа, предварительно вызвав ОбработкаПолученияДанныхВыбора модуля менеджера, — так же при автоподборе и быстром выборе. Ключи Отбор сюда приходят, а свои параметры и расширение отбора нужно повторить, иначе ввод по строке предложит то, чего нет в форме выбора.
// Отбор по контрагенту расширяет до «проекты контрагента и общие проекты».
// Вызывается из формы выбора и из ОбработкаПолученияДанныхВыбора.
Процедура РасширитьОтборПоКонтрагенту(Отбор) Экспорт
Контрагент = Неопределено;
Если Не Отбор.Свойство("Контрагент", Контрагент)
Или ТипЗнч(Контрагент) <> Тип("СправочникСсылка.Контрагенты")
Или Не ЗначениеЗаполнено(Контрагент) Тогда
Возврат;
КонецЕсли;
// Массив в значении ключа Отбор применяется как «В списке»
Допустимые = Новый Массив;
Допустимые.Добавить(Контрагент);
Допустимые.Добавить(Справочники.Контрагенты.ПустаяСсылка());
Отбор.Вставить("Контрагент", Допустимые);
КонецПроцедуры
// Ввод по строке, автоподбор и быстрый выбор: те же правила, что в форме выбора.
Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка)
РасширитьОтборПоКонтрагенту(Параметры.Отбор);
// Свой параметр платформа здесь не применит - превращаем его в обычный отбор
ТолькоОткрытые = Неопределено;
Если Параметры.Свойство("ТолькоОткрытые", ТолькоОткрытые) И ТолькоОткрытые = Истина Тогда
Параметры.Отбор.Вставить("Закрыт", Ложь);
КонецЕсли;
КонецПроцедуры
СтандартнаяОбработка остаётся равной Истина: поиск и список вариантов платформа сделает сама. Собирать ДанныеВыбора запросом стоит, только когда условие не выражается отбором.
Контрагент вместо Отбор.Контрагент стандартная форма выбора проигнорирует молча.Отбор.ВалютаВзаиморасчетов, хотя реквизит документа называется Валюта.ПараметрыВыбора без копирования старых элементов стирает параметры из редактора формы.СвязиПараметровВыбора записываются только на сервере.Перечисления.ТипыНоменклатуры.Товар в клиентской процедуре не компилируется: «Переменная не определена (Перечисления)». Нужен ПредопределенноеЗначение("Перечисление.ТипыНоменклатуры.Товар").Параметры.ТолькоОткрытые в форме, открытой из меню, даёт «Поле объекта не обнаружено (ТолькоОткрытые)» — читайте через Параметры.Свойство().Элементы.Товары.ТекущиеДанные.Номенклатура, а не Объект.Товары.Номенклатура.Новый СвязьПараметраВыбора("Отбор.Владелец", "Объект.Контрагент") очищает договор даже при повторном выборе того же контрагента.Вызовом ОткрытьФорму("Справочник.Номенклатура.ФормаВыбора", ПараметрыФормы, Владелец): отбор — в ключе Отбор, результат — в ОписаниеОповещения, а если владелец — поле формы, значение попадёт в поле само. Другие варианты — в статье открыть форму 1С программно.
Параметр хранит постоянное значение, связь берёт его в момент выбора из другого реквизита. «Только действующие договоры» — параметр, «договоры этого контрагента» — связь.
Значение параметра — массив: в коде Новый ФиксированныйМассив(...), в конфигураторе — как у номенклатуры в перемещении товаров УТ 11.4. Для «не в списке», ИЛИ и пустых значений нужен код формы выбора.
Условие держится на параметре без префикса Отбор., который разбирает только форма выбора. Повторите его в ОбработкаПолученияДанныхВыбора модуля менеджера.
Отбор из параметров и связей выбора он не снимет. Отключаемый ставят в форме выбора по своему параметру, как в примере с проектами.
Если ограничения нужно встроить в типовую форму через расширение, согласовать с вводом по строке и проверкой при записи и не сломать обновления, быстрее отдать задачу программисту. Опишите её и разместите задание бесплатно: оценка тоже бесплатная, ответ — в течение рабочего дня. Другие направления доработок — на странице услуг.
Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.