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