Как отфильтровать список выбора в поле справочника и исключить удаленные объекты в обычном приложении 1С

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

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

Анализ проблемы и выбор стратегии

В обычном приложении существует несколько способов управления выбором данных. Рассмотрим ситуацию, когда у нас есть реквизит с типом ссылки на справочник Автомобили. Нам нужно, чтобы при нажатии на "треугольник" (кнопку выпадающего списка) пользователь видел только актуальные записи.

Проанализируем основные подходы к решению этой задачи:

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

Способ 1. Программное заполнение списка выбора (ChoiceList)

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

Во-первых, необходимо настроить свойства элемента формы в конфигураторе или программно. Для работы выпадающего списка у поля ввода должны быть включены следующие свойства:

Во-вторых, разберем типичную ошибку в запросе. Посмотрим на логическое условие. Часто начинающие разработчики пишут ГДЕ НЕ Автомобили.ПометкаУдаления = ЛОЖЬ. Проанализируем эту конструкцию: НЕ ЛОЖЬ превращается в ИСТИНА, и запрос в итоге выбирает только помеченные на удаление объекты. Правильное условие в языке запросов 1С выглядит так:


ГДЕ Автомобили.ПометкаУдаления = ЛОЖЬ
// Или еще проще
ГДЕ НЕ Автомобили.ПометкаУдаления

Теперь реализуем само заполнение. Наиболее эффективно заполнять список при открытии формы или в специализированном событии. Рассмотрим вариант заполнения в процедуре ПриОткрытии, чтобы список был готов заранее:


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

Способ 2. Использование события НачалоВыбораИзСписка

Если справочник динамичный и данные могут измениться за время работы с формой, лучше обновлять список непосредственно перед показом. Для этого используем событие НачалоВыбораИзСписка. Выясним причину, почему код может "не реагировать": если вы устанавливаете СтандартнаяОбработка = Ложь, вы берете управление на себя, и если список пуст, визуально ничего не произойдет.


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

Способ 3. Установка отбора в форме выбора (рекомендуемый)

Если объектов в справочнике много (более 50-100), использование выпадающего списка становится неудобным для пользователя. В этом случае лучше использовать полноценную форму выбора, но с жестким фильтром. Разберем, как это сделать через событие НачалоВыбора.

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


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

Важные рекомендации по производительности

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

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

← На главную