Как правильно программно ограничить список выбора перечисления в документе 1С?

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием IT и автоматизация бизнеса
← На главную

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

Вариант 1. Использование списка выбора в событии ПриСозданииНаСервере

Проанализируем самый распространенный и производительный метод. Если список доступных значений перечисления для конкретной формы документа известен заранее и не меняется динамически при каждом клике пользователя, логичнее всего сформировать его один раз при открытии формы. Это делается в серверной процедуре ПриСозданииНаСервере.

Рассмотрим по шагам, как это реализовать. Нам необходимо обратиться к элементу формы, очистить его текущий список выбора и добавить туда только нужные значения. Важным моментом здесь является установка свойства РежимВыбораИзСписка. Если его не включить, платформа может проигнорировать ваш список и открыть стандартную форму выбора со всеми значениями перечисления.

Посмотрим на пример кода:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // 1. Очищаем существующий список выбора элемента формы
    Элементы.ВидДокумента.СписокВыбора.Очистить();
    
    // 2. Устанавливаем режим выбора именно из нашего списка
    Элементы.ВидДокумента.РежимВыбораИзСписка = Истина;
    
    // 3. Добавляем необходимые значения из метаданных
    Элементы.ВидДокумента.СписокВыбора.Добавить(Перечисления.ХХХ_ВидДокумента.ЭтапПроизводства);
    Элементы.ВидДокумента.СписокВыбора.Добавить(Перечисления.ХХХ_ВидДокумента.НарядЗадание);
    
КонецПроцедуры

Преимущества этого метода:

  1. Производительность: Код выполняется один раз при инициализации формы. При последующих нажатиях пользователя на поле выбора никаких серверных вызовов для формирования списка не происходит.
  2. Простота: Весь код локализован в одном обработчике формы.

Однако помните о модифицированности. Если вы устанавливаете значение реквизита по умолчанию в этой же процедуре, форма пометится как измененная (появится «звездочка»). Чтобы этого избежать для новых документов, используйте ЭтаФорма.Модифицированность = Ложь; в конце процедуры.

Вариант 2. Динамическое формирование в событии НачалоВыбора

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

Разберем алгоритм реализации:

  1. Устанавливаем параметр СтандартнаяОбработка = Ложь, чтобы подавить открытие стандартного окна выбора.
  2. Создаем новый СписокЗначений.
  3. Заполняем его программно нужными элементами перечисления.
  4. Вызываем метод ВыбратьИзСписка, передавая туда наш сформированный список.

Пример программного кода для реализации этого подхода:


&НаКлиенте
Процедура ВидДокументаНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    СписокФОП = Новый СписокЗначений;
    // Используем ПредопределенноеЗначение для обращения к перечислениям на клиенте
    СписокФОП.Добавить(ПредопределенноеЗначение("Перечисление.ХХХ_ВидДокумента.ЭтапПроизводства"));
    СписокФОП.Добавить(ПредопределенноеЗначение("Перечисление.ХХХ_ВидДокумента.НарядЗадание"));
    
    // Описываем оповещение о завершении выбора
    Оповещение = Новый ОписаниеОповещения("ВидДокументаЗавершениеВыбора", ЭтаФорма);
    
    // Показываем список пользователю
    ПоказатьВыборИзСписка(Оповещение, СписокФОП, Элемент);
    
КонецПроцедуры

&НаКлиенте
Процедура ВидДокументаЗавершениеВыбора(ВыбранныйЭлемент, Параметры) Экспорт
    Если ВыбранныйЭлемент <> Неопределено Тогда
        Объект.ВидДокумента = ВыбранныйЭлемент.Значение;
    КонецЕсли;
КонецПроцедуры

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

Вариант 3. Глобальное решение через ОбработкаПолученияДанныхВыбора

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

Этот обработчик располагается в модуле менеджера конкретного перечисления. Он срабатывает не только при нажатии на кнопку выбора, но и при автоподборе (когда пользователь начинает печатать название значения в поле ввода).

Рассмотрим, как это выглядит в модуле менеджера перечисления:


Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка)
    
    // Если нам нужно применить фильтр только при определенных условиях, 
    // передаваемых из формы через ПараметрыВыбора
    Если Параметры.Свойство("ТолькоПроизводственные") Тогда
        СтандартнаяОбработка = Ложь;
        Список = Новый СписокЗначений;
        Список.Добавить(Перечисления.ХХХ_ВидДокумента.ЭтапПроизводства);
        Список.Добавить(Перечисления.ХХХ_ВидДокумента.НарядЗадание);
        ДанныеВыбора = Список;
    КонецЕсли;
    
КонецПроцедуры

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

Дополнительные рекомендации и «подводные камни»

Проанализируем несколько важных нюансов, которые часто упускают начинающие разработчики:

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

2. Быстрый выбор. Если у перечисления всего 2-3 значения, убедитесь, что свойство элемента формы БыстрыйВыбор установлено в Истина. Это позволит пользователю выбирать значение в один клик без открытия дополнительных диалогов.

3. Проверка заполнения. Помните, что программное ограничение списка выбора на форме не является жестким ограничением на уровне базы данных. Если данные в документ могут попасть через обработки или загрузку из внешних источников, необходимо также добавить проверку корректности значения в процедуру ПередЗаписью модуля объекта документа.

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

← На главную