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

Разберу задачу на примере, покажу код для обычной конфигурации и для расширения и перечислю ограничения подхода — главное из них касается форм выбора.

Задача

Есть перечисление СтатусыЗаказа и несколько документов с полем этого типа. Нужно, чтобы на формах только этих документов в поле можно было выбрать лишь два статуса — «Выполнен» и «Отменён». Условия:

  • обработчики поля на форме не трогаем;
  • метаданные и формы в конфигураторе не меняем, всё делаем кодом;
  • на остальных формах, где есть поле этого перечисления, список полный.

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

Откуда берутся Параметры в ОбработкаПолученияДанныхВыбора

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

Ключевой момент: если имя параметра начинается с Отбор., значение попадает в Параметры.Отбор. Если имя без префикса — оно становится отдельным свойством структуры Параметры. Этим и пользуемся: связь параметра выбора с произвольным именем доставит в обработчик менеджера метку формы.

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

Шаг 1. Метка на форме документа

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

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

	ДобавитьМеткуОграниченияСтатусов(ЭтотОбъект, "СтатусЗаказа");

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

Саму логику удобно вынести в серверный общий модуль, чтобы вызывать её из всех нужных форм одной строкой:

1С
// Добавляет на форму реквизит-метку и связь параметра выбора поля с ним.
// Обработчик ОбработкаПолученияДанныхВыбора увидит параметр ОграничиватьСтатусы.
Процедура ДобавитьМеткуОграниченияСтатусов(Форма, ИмяПоля) Экспорт

	ИмяМетки = "ОграничиватьСтатусы";

	Если Форма.Элементы.Найти(ИмяПоля) = Неопределено Тогда
		Возврат;
	КонецЕсли;

	Реквизиты = Новый Массив;
	Реквизиты.Добавить(Новый РеквизитФормы(ИмяМетки, Новый ОписаниеТипов("Булево")));
	Форма.ИзменитьРеквизиты(Реквизиты);
	Форма[ИмяМетки] = Истина;

	// Сохраняем существующие связи и добавляем свою
	Связи = Новый Массив;
	Для Каждого Связь Из Форма.Элементы[ИмяПоля].СвязиПараметровВыбора Цикл
		Связи.Добавить(Связь);
	КонецЦикла;
	Связи.Добавить(Новый СвязьПараметраВыбора(ИмяМетки, ИмяМетки,
		РежимИзмененияСвязанногоЗначения.НеИзменять));

	Форма.Элементы[ИмяПоля].СвязиПараметровВыбора = Новый ФиксированныйМассив(Связи);

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

Режим НеИзменять важен: по умолчанию при изменении связанного значения платформа очищает поле. Метка у нас не меняется, но явный режим страхует от сюрпризов.

Шаг 2. Ограничение в модуле менеджера

В модуле менеджера перечисления проверяем наличие параметра:

1С
Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка)

	Если Не Параметры.Свойство("ОграничиватьСтатусы") Тогда
		Возврат; // Обычная форма — стандартный список
	КонецЕсли;

	СтандартнаяОбработка = Ложь;
	ДанныеВыбора = Новый СписокЗначений;
	ДанныеВыбора.Добавить(Перечисления.СтатусыЗаказа.Выполнен);
	ДанныеВыбора.Добавить(Перечисления.СтатусыЗаказа.Отменен);

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

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

Вариант для расширения

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

1С
&После("ОбработкаПолученияДанныхВыбора")
Процедура пр_ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка)

	Если Не Параметры.Свойство("ОграничиватьСтатусы") Тогда
		Возврат;
	КонецЕсли;

	Разрешенные = Новый Массив;
	Разрешенные.Добавить(Перечисления.СтатусыЗаказа.Выполнен);
	Разрешенные.Добавить(Перечисления.СтатусыЗаказа.Отменен);

	Если СтандартнаяОбработка Или ДанныеВыбора = Неопределено Тогда
		// Типовой код список не строил — строим сами
		СтандартнаяОбработка = Ложь;
		ДанныеВыбора = Новый СписокЗначений;
		ДанныеВыбора.ЗагрузитьЗначения(Разрешенные);
		Возврат;
	КонецЕсли;

	// Типовой код построил список — убираем лишнее
	Индекс = ДанныеВыбора.Количество() - 1;
	Пока Индекс >= 0 Цикл
		Элемент = ДанныеВыбора[Индекс];
		Значение = ?(ТипЗнч(Элемент.Значение) = Тип("Структура") И Элемент.Значение.Свойство("Значение"),
			Элемент.Значение.Значение, Элемент.Значение);
		Если Разрешенные.Найти(Значение) = Неопределено Тогда
			ДанныеВыбора.Удалить(Индекс);
		КонецЕсли;
		Индекс = Индекс - 1;
	КонецЦикла;

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

Элемент данных выбора может быть как самим значением, так и структурой с ключом Значение (так передаются, например, пометка удаления или предупреждение) — поэтому проверяем оба варианта. Обход идёт с конца, чтобы удаление не сбивало индексы.

Аннотация &После для модуля менеджера в расширении работает, если в типовом модуле этот обработчик есть. Если его нет, в расширении просто объявляется обработчик события модуля менеджера.

Где подход не сработает

  • Полноценная форма выбора. ОбработкаПолученияДанныхВыбора вызывается для ввода по строке и быстрого выбора. Для справочника, у которого по кнопке выбора открывается форма списка, ограничение нужно повторить в форме выбора: параметр из связи придёт в неё, если в форме объявлен параметр с таким именем, а дальше накладывается отбор на динамический список.
  • Значение, вставленное без выбора. Копирование строк, заполнение кодом, загрузка из файла обходят список выбора. Если ограничение — бизнес-правило, проверяйте значение ещё и в ОбработкаПроверкиЗаполнения объекта.
  • Поле в табличной части. Работает, но путь к данным в связи указывается к реквизиту формы — метка остаётся реквизитом верхнего уровня.

Типичные ошибки

  • Затёрли типовые связи. Присвоили полю новый массив только со своей связью — пропали зависимости от организации или склада.
  • Префикс «Отбор.» у метки. Тогда параметр окажется в Параметры.Отбор, а для перечисления платформа попытается применить его как отбор.
  • ИзменитьРеквизиты вызывается повторно. Если код может выполниться дважды, проверяйте, есть ли уже реквизит.
  • Ограничение только в интерфейсе. Обход через копирование или обмен — данные всё равно попадут в базу.
Связь параметра выбора с собственным именем — это канал, по которому форма сообщает модулю менеджера свой контекст. Его хватает, чтобы ограничить выбор точечно и без правки типовых обработчиков.

Подобные точечные доработки форм удобнее всего держать в расширении — их я делаю в рамках разработки расширений 1С и доработки 1С.

Итог

  • В ОбработкаПолученияДанныхВыбора приходят параметры из связей параметров выбора поля; имя без префикса «Отбор.» становится свойством Параметры.
  • Служебный реквизит на форме плюс связь с ним — метка, по которой менеджер отличает нужные формы.
  • Существующие связи поля сохраняйте, режим изменения ставьте НеИзменять.
  • В расширении фильтруйте результат типового обработчика через &После.
  • Для форм выбора и для защиты данных ограничение нужно продублировать.