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

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

В процессе разработки часто возникает задача ограничить пользователю возможность выбора определенных данных. Типичный пример: в справочнике сотрудников существует группа «Уволенные», элементы которой должны храниться в базе для истории, но их категорически нельзя выбирать в новых документах или при настройке констант. Рассмотрим, как реализовать такой запрет максимально эффективно, избегая дублирования кода во всех формах системы.

Метод 1: Переопределение формы выбора справочника

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

Нам необходимо обработать событие ВыборЗначения или ОбработкаВыбора. Проанализируем пример кода, который проверяет родителя выбранного элемента:


&НаСервере
Функция СписокВыборНаСервере(ДанныеВыбора, СтандартнаяОбработка)
    // Проверяем родителя элемента. 
    // Внимание: проверка по наименованию считается плохой практикой
    Если ДанныеВыбора.Родитель.Наименование = "Уволенные" Тогда
        СтандартнаяОбработка = Ложь;
        Возврат Ложь;
    Иначе
        Возврат Истина;
    КонецЕсли;
КонецФункции

&НаКлиенте
Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
    Если НЕ СписокВыборНаСервере(Элементы.Список.ТекущиеДанные.Ссылка, СтандартнаяОбработка) Тогда
        ОчиститьСообщения();
        Сообщить("Сотрудники из этой группы приведены исключительно справочно и недоступны для выбора!");
    КонецЕсли;
КонецПроцедуры

Важное замечание: использование проверки по наименованию "Уволенные" крайне ненадежно. Если пользователь переименует группу, код перестанет работать. Правильнее использовать метод ПринадлежитЭлементу() или проверять ссылку на предопределенный элемент.

Метод 2: Использование события менеджера «ОбработкаПолученияДанныхВыбора»

Если мы хотим решить задачу по-настоящему глобально, включая запрет не только при открытии формы, но и при «вводе по строке» (когда пользователь начинает набирать текст прямо в поле ввода), нам следует обратиться к модулю менеджера справочника. Разберем, как работает событие ОбработкаПолученияДанныхВыбора.

Этот метод хорош тем, что он срабатывает на стороне сервера до того, как список выбора будет сформирован и показан пользователю. Мы можем динамически добавить фильтр, который просто скроет запрещенные элементы из выпадающего списка. Рассмотрим алгоритм реализации:

  1. Откроем модуль менеджера нужного справочника.
  2. Создадим обработчик события ОбработкаПолученияДанныхВыбора.
  3. Внесем изменения в структуру Параметры.Отбор.

Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка)
    // Добавляем условие: элемент не должен входить в запрещенную группу
    // Предположим, у нас есть ссылка на группу ГруппаЗапрета
    Если Параметры.Свойство("Отбор") Тогда
        // Добавляем программный фильтр
        Параметры.Отбор.Вставить("Родитель", Новый ФиксированныйМассив(СписокРазрешенныхГрупп));
    КонецЕсли;
    // Платформа сама применит обновленные параметры отбора
КонецПроцедуры

Преимущество этого метода в том, что он работает везде: в формах документов, в формах констант, в обработках. Пользователь даже не увидит «запрещенные» элементы в списке быстрого подбора.

Метод 3: Настройка параметров выбора в метаданных

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

Найдите свойство Параметры выбора у реквизита и добавьте условие: Отбор.Родитель(НеВГруппе). Это самый «дешевый» в плане производительности и поддержки способ. Однако он не является глобальным — такую настройку придется повторить для каждого реквизита, где требуется ограничение.

Метод 4: Использование метода «ПринадлежитЭлементу» для иерархических проверок

Выясним причину, по которой обычная проверка Элемент.Родитель = Группа часто оказывается недостаточной. В иерархических справочниках группы могут быть вложенными. Если вы запрещаете выбор из «Группы А», а пользователь пытается выбрать элемент из «Группы Б», которая находится внутри «Группы А», проверка только по непосредственному родителю не сработает.

Для надежной проверки всегда используйте системный метод ПринадлежитЭлементу(). Рассмотрим пример функции проверки:


&НаСервереБезКонтекста
Функция ЭтоЗапрещенныйЭлемент(СсылкаНаЭлемент)
    ГруппаЗапрета = Справочники.Сотрудники.Уволенные; // Или получаем из константы
    Возврат СсылкаНаЭлемент.ПринадлежитЭлементу(ГруппаЗапрета);
КонецФункции

Этот метод корректно обходит всю цепочку родителей вверх до корня справочника и возвращает Истина, если элемент находится где-либо внутри указанной группы.

Метод 5: Жесткий контроль в модуле объекта (защита от программной записи)

Все вышеперечисленные методы касаются интерфейса. Однако опытный пользователь или внешняя обработка могут записать «запрещенное» значение программно, минуя формы. Чтобы обеспечить 100% гарантию, добавим проверку в модуль объекта самого справочника или в модуль набора записей констант.

Проанализируем пример для модуля объекта:


Процедура ПередЗаписью(Отказ)
    Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;
    
    Если ЭтоЗапрещеннаяГруппа(ЭтотОбъект.Ссылка) Тогда
        // Здесь можно реализовать логику запрета изменения самих элементов группы
    КонецЕсли;
КонецПроцедуры

Для констант аналогичную проверку стоит разместить в модуле набора записей константы. Если значение не проходит валидацию, мы устанавливаем Отказ = Истина, что предотвращает запись некорректных данных в базу.

Сводная таблица решений

Подводя итог, выберем оптимальный инструмент в зависимости от целей:

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

← На главную