Как правильно программно установить отбор «Не в списке» по критерию отбора в 1С

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

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

Анализ проблемы: почему метод Установить() не всегда подходит

Рассмотрим ситуацию, когда в документе (например, «Счет на оплату») в табличной части «Товары» есть реквизит «Поставщик». Для быстрого поиска по этому полю создан объект конфигурации Критерий отбора. При попытке программно установить фильтр, чтобы скрыть документы определенных поставщиков, разработчики часто пишут следующий код:


список2 = Новый СписокЗначений;
список2.Добавить(Справочники.Контрагенты.НайтиПоНаименованию("Поставщик 1"));
список2.Добавить(Справочники.Контрагенты.НайтиПоНаименованию("Поставщик 2"));

Отбор.ОтборПоПоставщику.ВидСравнения = ВидСравнения.НеВСписке;
Отбор.ОтборПоПоставщику.Установить(список2);

Проблема заключается в том, что после выполнения такого кода список документов отображает данные некорректно (например, выводится всего несколько записей вместо сотен). Проанализируем причину: согласно синтакс-помощнику 1С, метод Установить(<Значение>, <Использование>) объекта ЭлементОтбора автоматически сбрасывает свойство ВидСравнения в значение Равно. Таким образом, строка с установкой НеВСписке просто игнорируется платформой.

Правильное решение: прямое управление свойствами отбора

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

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

Посмотрим на пример работающего кода:


// Формируем список исключаемых контрагентов
СписокИсключений = Новый СписокЗначений;
Поставщик1 = Справочники.Контрагенты.НайтиПоНаименованию("СППбд");
Поставщик2 = Справочники.Контрагенты.НайтиПоНаименованию("СППбд ТТК");

Если Не Поставщик1.Пустая() Тогда
    СписокИсключений.Добавить(Поставщик1);
КонецЕсли;
Если Не Поставщик2.Пустая() Тогда
    СписокИсключений.Добавить(Поставщик2);
КонецЕсли;

// Устанавливаем отбор правильно
Элемент = Отбор.ОтборПоПоставщику; // Здесь ОтборПоПоставщику — имя критерия отбора
Элемент.ВидСравнения = ВидСравнения.НеВСписке;
Элемент.Значение = СписокИсключений;
Элемент.Использование = Истина;

Такой подход гарантирует, что платформа применит именно отрицание (НЕ В), и в списке останутся все документы, кроме тех, где в табличной части указаны данные контрагенты.

Особенности работы отборов по табличным частям

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

Важный момент: если в одном и том же документе есть две строки — одна с «запрещенным» поставщиком, а другая с любым другим, — такой документ может попасть в выборку. Это происходит потому, что одна из строк удовлетворяет условию «Поставщик НЕ равен значению из списка». Если ваша задача — полностью исключить документ, в котором хотя бы один раз встречается нежелательный поставщик, использование простого критерия отбора в динамическом списке может быть недостаточно. В таких случаях эффективнее использовать произвольный запрос в динамическом списке с конструкцией ГДЕ НЕ Ссылка В (ВЫБРАТЬ... ГДЕ Поставщик В (&Список)).

Рекомендации по оптимизации и надежности

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

  1. Индексирование: Критерий отбора будет работать быстро только в том случае, если реквизит табличной части (в нашем случае Поставщик) проиндексирован. Убедитесь, что в конфигураторе для этого реквизита установлено свойство Индексировать.
  2. Поиск объектов: Использование НайтиПоНаименованию() в коде считается плохой практикой. Если пользователь случайно изменит название контрагента (добавит лишний пробел или кавычку), код перестанет работать. Рекомендуется использовать поиск по уникальному идентификатору (GUID) или выносить такие настройки в константы/дополнительные реквизиты.
  3. Проверка на пустые ссылки: Всегда проверяйте результат поиска контрагента. Если метод вернет пустую ссылку, и вы добавите её в список исключений, отбор может отсечь все документы, где поставщик не заполнен, что часто является ошибкой логики.

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

← На главную