При разработке и адаптации конфигураций 1С на управляемых формах мы часто сталкиваемся с задачей ограничения пользователя в выборе определенных значений для полей. Это особенно актуально для полей, имеющих тип "Перечисление", когда нам необходимо исключить одно или несколько значений из выпадающего списка выбора, чтобы предотвратить некорректные операции или обеспечить соблюдение бизнес-логики. Мы подробно рассмотрим, как эффективно реализовать такое ограничение, опираясь на программное управление свойствами элементов формы в управляемом приложении.
Этот метод является одним из наиболее прямых и рекомендуемых, когда речь идет об ограничении выбора для полей, которые непосредственно привязаны к реквизитам объекта или формы и имеют тип "Перечисление" или "Булево". Правильное использование этого свойства помогает выполнить оптимизацию интерфейса управляемых форм для полей, делая их более понятными для конечного пользователя. Мы будем программно управлять списком значений, который отображается пользователю в выпадающем меню.
ВидОперации в документе ЗаказПокупателя, которое является реквизитом типа "Перечисление".ПриСозданииНаСервере. В нем мы можем вызвать серверную процедуру, которая сформирует список выбора, или непосредственно использовать клиентскую процедуру, которая будет вызываться из серверного контекста. Нам потребуется получить программный доступ к элементу формы, соответствующему нашему полю. Существуют разные подходы к добавлению реквизитов и элементов на форму, но в данном случае мы предполагаем, что нужный элемент уже размещен.СписокВыбора. Это свойство представляет собой коллекцию, которую мы можем полностью очистить, а затем программно добавить в нее только те значения перечисления, которые разрешены для выбора пользователем.Давайте рассмотрим подробный пример кода, который иллюстрирует этот подход. Предположим, мы хотим исключить значение "Возврат" из перечисления ВидыОперацийЗаказПокупателя для поля ВидОперации.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Вызываем клиентскую процедуру для загрузки значений,
// так как работа со свойствами формы (Элементы) обычно производится на клиенте.
ЗагрузитьРазрешенныеЗначенияВидовОпераций();
КонецПроцедуры
&НаКлиенте
Процедура ЗагрузитьРазрешенныеЗначенияВидовОпераций()
// Получаем элемент формы, связанный с полем ВидОперации.
// Убедимся, что имя элемента формы соответствует имени реквизита или задано явно.
ЭлементВидОперации = Элементы.ВидОперации;
// Проверяем, является ли элемент формы доступным и имеет ли свойство СписокВыбора
// (актуально для полей выбора перечислений, булевых значений и т.п.)
Если ЭлементВидОперации = Неопределено Или НЕ ТипЗнч(ЭлементВидОперации.СписокВыбора) = Тип("СписокЗначений") Тогда
Возврат; // Элемент не найден или не поддерживает СписокВыбора
КонецЕсли;
// Очищаем существующий список выбора элемента формы.
// Это гарантирует, что мы начнем с чистого листа.
ЭлементВидОперации.СписокВыбора.Очистить();
// Добавляем только разрешенные значения перечисления.
// В данном примере мы разрешаем "Продажа" и "Переработка".
ЭлементВидОперации.СписокВыбора.Добавить(Перечисления.ВидыОперацийЗаказПокупателя.Продажа);
ЭлементВидОперации.СписокВыбора.Добавить(Перечисления.ВидыОперацийЗаказПокупателя.Переработка);
// Продолжаем добавлять все остальные значения, которые хотим оставить в списке.
// Например: ЭлементВидОперации.СписокВыбора.Добавить(Перечисления.ВидыОперацийЗаказПокупателя.ОтгрузкаБезЗаказа);
// Важно: если перечисление имеет много значений, и мы хотим исключить лишь одно,
// может быть эффективнее сначала получить все значения, затем удалить одно, а потом добавить.
// Пример:
// Для Каждого ЗначениеПеречисления Из Метаданные.Перечисления.ВидыОперацийЗаказПокупателя.Значения Цикла
// Если ЗначениеПеречисления.Имя <> "Возврат" Тогда
// ЭлементВидОперации.СписокВыбора.Добавить(ЗначениеПеречисления.Ссылка);
// КонецЕсли;
// КонецЦикла;
КонецПроцедуры
В этом примере ЭлементВидОперации = Элементы.ВидОперации; позволяет нам получить программный доступ к элементу формы. Затем мы используем метод ЭлементВидОперации.СписокВыбора.Очистить();, чтобы удалить все существующие значения из списка выбора, и последовательно добавляем разрешенные значения с помощью ЭлементВидОперации.СписокВыбора.Добавить(...);. Этот подход максимально прозрачен и эффективен для типовых полей перечислений.
Важно отметить, что если поле не связано напрямую с перечислением через реквизит, а представляет собой, например, поле ввода с типом значения Произвольный, или если требуется более сложная логика, то этот подход может потребовать дополнительных манипуляций или вовсе не подойти. Однако для типовых полей перечислений это является оптимальным и наиболее рекомендуемым решением. Для отладки и анализа свойств элементов в режиме предприятия можно использовать вспомогательные инструменты, такие как редактор форм, позволяющий просматривать и изменять их «на лету».
В некоторых случаях, особенно если поле является полем ввода и позволяет выбирать значения из более сложного источника, можно использовать событие ПриНачалеВыбора элемента формы. Этот метод незаменим для реализации сложных подборов и предоставляет нам значительно больше контроля над процессом выбора.
ПриНачалеВыбора мы устанавливаем параметр СтандартнаяОбработка = Ложь;. Это критически важный шаг, который предотвращает вызов стандартного механизма выбора 1С и позволяет нам полностью управлять процессом.СписокЗначений), который будет содержать только те значения, которые разрешены для выбора.ВыбратьИзСписка() для создания интерактивного выбора из нашего подготовленного списка. Для более сложных сценариев можно открыть форму списка перечисления или справочника с установленными отборами.Рассмотрим пример кода для использования события ПриНачалеВыбора. В этом примере мы также будем фильтровать значения перечисления, но через другой механизм.
&НаКлиенте
Процедура ВидОперацииПриНачалеВыбора(Элемент, СтандартнаяОбработка)
// Отключаем стандартную обработку выбора. Это позволяет нам полностью управлять процессом.
СтандартнаяОбработка = Ложь;
// Создаем массив или список значений, в который будем добавлять только разрешенные варианты.
МассивРазрешенныхЗначений = Новый Массив();
МассивРазрешенныхЗначений.Добавить(Перечисления.ВидыОперацийЗаказПокупателя.Продажа);
МассивРазрешенныхЗначений.Добавить(Перечисления.ВидыОперацийЗаказПокупателя.Переработка);
// Добавляем все остальные значения, которые хотим видеть в списке.
// Вызываем функцию, которая откроет форму выбора и позволит пользователю выбрать значение из нашего массива.
// Функция ВыбратьИзСписка() является удобным инструментом для интерактивного выбора из простого списка.
ВыбранноеЗначение = ВыбратьИзСписка(МассивРазрешенныхЗначений, Элемент);
// Если пользователь что-то выбрал, устанавливаем это значение в поле формы.
Если ВыбранноеЗначение <> Неопределено Тогда
Элемент.Значение = ВыбранноеЗначение;
КонецЕсли;
КонецПроцедуры
В этом примере СтандартнаяОбработка = Ложь; является ключевым моментом для перехвата управления. Мы формируем МассивРазрешенныхЗначений, содержащий только допустимые варианты, а затем используем функцию ВыбратьИзСписка(). Этот метод дает большую гибкость, учитывая логику взаимодействия между формами и механизмы возврата выбранного значения в основную форму. Он особенно полезен, когда логика выбора зависит от других данных в форме или от прав пользователя, и требуется более сложная, динамическая фильтрация.
В целом, для ограничения выбора значений в поле типа Перечисление на управляемых формах, мы рекомендуем использовать первый подход с непосредственным управлением свойством СписокВыбора элемента формы. Он более прямолинеен и оптимален для данного типа задачи. Если же задача требует более сложной логики выбора или взаимодействия с другими объектами, тогда рассмотрите вариант с перехватом события ПриНачалеВыбора.
Мы также можем рассмотреть сценарии, когда поле связано не с перечислением, а, например, со справочником. В таких случаях для ограничения выбора обычно используют динамический список. Расширенная настройка отборов и параметров в нем позволяет фильтровать элементы справочника, которые отображаются пользователю при выборе, не изменяя сам справочник. Например, мы можем установить отбор по определенному реквизиту справочника или использовать связи параметров выбора в метаданных, чтобы ограничить список без написания сложного кода.
При работе с динамическими списками для установки отборов мы используем коллекцию Отбор динамического списка. Рассмотрим пример, как мы можем добавить элемент отбора в событии ПриСозданииНаСервере или при изменении другого поля формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Предположим, у нас есть поле формы 'Контрагент',
// связанное с динамическим списком справочника 'Контрагенты'.
// Мы хотим, чтобы пользователь мог выбирать только контрагентов с определенным статусом.
ЭлементСписка = Элементы.Контрагент; // Имя элемента формы, связанного с динамическим списком
Если ЭлементСписка <> Неопределено Тогда
// Получаем коллекцию отборов динамического списка, связанного с элементом формы.
ОтборДинамическогоСписка = ЭлементСписка.Отбор;
// Создаем новый элемент отбора.
НовыйЭлементОтбора = ОтборДинамическогоСписка.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
// Устанавливаем левое значение элемента отбора – это поле, по которому будем фильтровать.
// Например, реквизит справочника "СтатусКонтрагента".
НовыйЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СтатусКонтрагента");
// Устанавливаем вид сравнения (например, "Равно").
НовыйЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
// Устанавливаем правое значение элемента отбора – конкретное значение, по которому фильтруем.
// Например, значение перечисления "СтатусыКонтрагентов.Активный".
НовыйЭлементОтбора.ПравоеЗначение = Перечисления.СтатусыКонтрагентов.Активный;
// Включаем использование данного элемента отбора.
НовыйЭлементОтбора.Использование = Истина;
// Также можно установить режим отображения для пользователя (если отбор должен быть виден)
// НовыйЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Всегда;
// Если необходимо сделать отбор нередактируемым пользователем:
// НовыйЭлементОтбора.Доступность = Ложь;
КонецЕсли;
КонецПроцедуры
Этот подход позволяет гибко настраивать выбор элементов справочника, делая его незаменимым при необходимости динамической фильтрации, которая может зависеть от других данных, введенных в форму, или от прав текущего пользователя. Кроме того, динамические списки поддерживают и более сложные визуальные настройки, например, существует способ реализовать флажок в динамическом списке, что расширяет интерактивные возможности интерфейса.
Важный совет: При внесении любых изменений в логику выбора значений всегда помните о необходимости тщательного тестирования ваших решений. Убедитесь, что ограничения работают корректно во всех сценариях использования и не вызывают непредвиденных ошибок или нарушения бизнес-процессов в других частях системы. Мы рекомендуем проверять поведение как при создании новых документов, так и при открытии существующих, а также при различных правах пользователей.