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

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

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

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

Почему популярные механизмы не всегда подходят?

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

  1. Ограничение доступа на уровне записей (RLS): Этот метод кажется самым простым, так как он настраивается глобально в роли пользователя. Мы можем прописать условие, запрещающее чтение элементов, у которых установлен признак неактуальности (например, реквизит Архивный = Истина). Однако у этого способа есть критический недостаток. В 1С нет отдельного права на «Автоподбор» или «Выбор». Запрещая чтение элемента, мы делаем его полностью невидимым для пользователя. Как результат — во всех старых проведенных документах вместо названия товара пользователи увидят надпись <Объект не найден>, а отчеты за прошлые периоды перестанут собираться корректно.
  2. Использование события ОбработкаПолученияДанныхВыбора: Данное событие действительно присутствует в модуле менеджера справочника начиная с платформы 8.2.14. Однако оно ориентировано на управляемый режим. Если ваше решение работает в толстом клиенте на обычных формах, платформа проигнорирует этот обработчик при интерактивном вводе текста в поле ввода, используя старые внутренние механизмы автоподбора.

Теперь рассмотрим рабочие и безопасные альтернативы, которые позволят решить задачу без разрушения исторических данных.

Способ 1. Использование обработчиков «АвтоПодборТекста» и «ОкончаниеВводаТекста»

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

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

Разберем по шагам реализацию этого механизма для поля ввода Номенклатура в табличной части документа.

Шаг 1. Создаем обработчик события АвтоПодборТекста для элемента управления (поля ввода):


Процедура ТоварыНоменклатураАвтоПодборТекста(Элемент, Текст, ТекстАвтоПодбора, СтандартнаяОбработка)
    
    // Отключаем стандартный поиск платформы
    СтандартнаяОбработка = Ложь;
    
    // Нам нужно найти первый подходящий элемент, который не является архивным
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 1
        |	Номенклатура.Наименование КАК Наименование
        |ИЗ
        |	Справочник.Номенклатура КАК Номенклатура
        |ГДЕ
        |	Номенклатура.Наименование ПОДОБНО &СтрокаПоиска
        |	И НЕ Номенклатура.Архивный // Исключаем архивные элементы
        |	И НЕ Номенклатура.ПометкаУдаления";
        
    Запрос.УстановитьПараметр("СтрокаПоиска", Текст + "%");
    
    РезультатЗапроса = Запрос.Выполнить();
    Если Не РезультатЗапроса.Пустой() Тогда
        Выборка = РезультатЗапроса.Выбрать();
        Выборка.Следующий();
        
        // Подставляем найденное значение в качестве подсказки
        ТекстАвтоПодбора = Сред(Выборка.Наименование, СтрДлина(Текст) + 1);
    КонецЕсли;

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

Шаг 2. Создаем обработчик события ОкончаниеВводаТекста. Этот обработчик срабатывает, когда пользователь завершает ввод (нажимает Enter или переходит в другое поле). Здесь мы должны вернуть конкретное найденное значение или список значений для выбора:


Процедура ТоварыНоменклатураОкончаниеВводаТекста(Элемент, Текст, Значение, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // Ищем все подходящие неархивные элементы
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ РАЗРЕШЕННЫЕ
        |	Номенклатура.Ссылка КАК Ссылка,
        |	Номенклатура.Наименование КАК Наименование
        |ИЗ
        |	Справочник.Номенклатура КАК Номенклатура
        |ГДЕ
        |	Номенклатура.Наименование ПОДОБНО &СтрокаПоиска
        |	И НЕ Номенклатура.Архивный
        |	И НЕ Номенклатура.ПометкаУдаления";
        
    Запрос.УстановитьПараметр("СтрокаПоиска", Текст + "%");
    СписокВыбора = Новый СписокЗначений;
    
    Выборка = Запрос.Выполнить().Выбрать();
    Пока Выборка.Следующий() Цикл
        СписокВыбора.Добавить(Выборка.Ссылка, Выборка.Наименование);
    КонецЦикла;
    
    Если СписокВыбора.Количество() = 0 Тогда
        // Ничего не найдено
        Значение = Неопределено;
    ИначеЕсли СписокВыбора.Количество() = 1 Тогда
        // Найдено точное совпадение
        Значение = СписокВыбора[0].Значение;
    Иначе
        // Найдено несколько элементов, предлагаем пользователю выбрать из списка
        Значение = СписокВыбора;
    КонецЕсли;

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

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

Способ 2. Блокировка ввода текста и использование формы выбора с отбором

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

Проанализируем шаги реализации этого сценария:

  1. Для нужного поля ввода в свойствах устанавливаем флаг РедактированиеТекста в значение Ложь. Теперь пользователь физически не может начать набирать буквы в ячейке.
  2. Создаем обработчик события НачалоВыбора для этого поля ввода, где программно открываем форму выбора с жестко заданным отбором:

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

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

Этот метод исключает любые ошибки ручного ввода и гарантирует, что пользователь выберет только разрешенный элемент из структуры справочника.

Способ 3. Административно-технический лайфхак с префиксами

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

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

Выполним следующие шаги:

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

Резюме

Выбор конкретного решения зависит от архитектуры вашей базы данных и требований к удобству работы пользователей:

← На главную