К статье
Практический материал

Разработка и Конфигурация · 13 мин

1С: как сделать отбор по полю ввода

Как настроить в 1С отбор списка по значению поля ввода: программный отбор динамического списка, отбор через параметры формы, примеры кода и типичные ошибки.

Задача отбора по полю ввода возникает в 1С постоянно: пользователь вводит часть наименования, номер документа или артикул в поле, а список на форме должен показать только подходящие записи. Реализуется это несколькими способами — от простого программного отбора динамического списка до передачи параметров при открытии формы выбора.

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

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

Как работает отбор динамического списка

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

Когда вы добавляете элемент отбора программно, платформа пересчитывает запрос динамического списка и показывает только записи, удовлетворяющие условию. Пользовательский отбор (который человек настраивает через кнопку «Ещё — Настроить список») и программный отбор существуют независимо и применяются вместе.

Ключевые свойства элемента отбора:

  • ЛевоеЗначение — поле данных, по которому фильтруем (например, Новый ПолеКомпоновкиДанных("Наименование"));
  • ВидСравнения — оператор: Равно, Содержит, ВСписке, БольшеИлиРавно и другие;
  • ПравоеЗначение — значение из поля ввода;
  • Использование — включён ли элемент (Истина/Ложь);
  • РежимОтображения — виден ли отбор пользователю.

Отбор списка по полю ввода на той же форме

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

Пример кода в модуле формы:

&НаКлиенте

Процедура СтрокаПоискаПриИзменении(Элемент)

УстановитьОтборПоНаименованию();

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

&НаСервере

Процедура УстановитьОтборПоНаименованию()

ЭлементыОтбора = Список.Отбор.Элементы;

ЭлементыОтбора.Очистить();

Если Не ПустаяСтрока(СтрокаПоиска) Тогда

ЭлементОтбора = ЭлементыОтбора.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));

ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Наименование");

ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит;

ЭлементОтбора.ПравоеЗначение = СтрокаПоиска;

ЭлементОтбора.Использование = Истина;

ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;

КонецЕсли;

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

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

Если нужно искать по нескольким полям сразу (например, по наименованию или артикулу), добавьте группу отбора с типом «Или» и поместите элементы внутрь неё:

ГруппаИли = ЭлементыОтбора.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));

ГруппаИли.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли;

ГруппаИли.Использование = Истина;

Элемент1 = ГруппаИли.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));

Элемент1.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Наименование");

Элемент1.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит;

Элемент1.ПравоеЗначение = СтрокаПоиска;

Элемент2 = ГруппаИли.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));

Элемент2.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Артикул");

Элемент2.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит;

Элемент2.ПравоеЗначение = СтрокаПоиска;

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

Отбор при открытии формы выбора

Вторая частая задача — поле ввода с кнопкой выбора, при нажатии на которую открывается форма выбора, уже отфильтрованная по нужному условию. Например, в поле «Контрагент» показывать только поставщиков, а в поле «Номенклатура» — только товары, а не услуги.

Для этого в обработчике события НачалоВыбора поля ввода формируется структура параметров с ключом «Отбор» и передаётся в ОткрытьФорму:

&НаКлиенте

Процедура КонтрагентНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)

СтандартнаяОбработка = Ложь;

Отбор = Новый Структура;

Отбор.Вставить("Поставщик", Истина);

ПараметрыФормы = Новый Структура("Отбор", Отбор);

ОткрытьФорму("Справочник.Контрагенты.ФормаВыбора", ПараметрыФормы, Элемент);

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

Структура «Отбор» — это стандартный механизм: ключи соответствуют именам реквизитов объекта, а значения — требуемым значениям. Платформа автоматически применяет такой отбор к списку формы выбора и делает его недоступным для отключения пользователем. Третий параметр ОткрытьФорму (в примере — Элемент) привязывает результат выбора к полю ввода, чтобы выбранное значение попало именно в него.

Если нужно отобрать по нескольким значениям одного поля, передайте массив или список значений — платформа преобразует его в условие «В списке»:

МассивТипов = Новый Массив;

МассивТипов.Добавить(Перечисления.ТипыНоменклатуры.Товар);

МассивТипов.Добавить(Перечисления.ТипыНоменклатуры.Комплект);

Отбор.Вставить("ТипНоменклатуры", МассивТипов);

Автоподбор и быстрый поиск в самом поле ввода

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

Настроить поведение можно через свойства поля ввода в конфигураторе или программно:

  • АвтоОтметкаНезаполненного и КнопкаВыпадающегоСписка — визуальные настройки;
  • Обработчик АвтоПодбор(Текст, ДанныеВыбора, ...) — позволяет самому сформировать список вариантов, например искать сразу по наименованию и коду;
  • Обработчик ОкончаниеВводаТекста — срабатывает, когда пользователь закончил ввод, и позволяет обработать неоднозначный результат.

Пример собственного автоподбора по двум полям:

&НаКлиенте

Процедура НоменклатураАвтоПодбор(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, Ожидание, СтандартнаяОбработка)

Если СтрДлина(Текст) < 3 Тогда

Возврат;

КонецЕсли;

СтандартнаяОбработка = Ложь;

ПараметрыПолученияДанных.СтрокаПоиска = Текст;

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

Параметр Ожидание задаёт паузу в секундах перед запросом к серверу — полезно установить 0,5–1 секунду, чтобы не дёргать базу на каждый символ. Для полноты контроля можно отменить стандартную обработку и сформировать ДанныеВыбора самостоятельно запросом на сервере.

Сравнение вариантов

Программный отбор динамического списка

Подходит, когда поле ввода и список на одной форме. Гибкий, поддерживает «Содержит» и группы условий, но требует кода в модуле формы.

Параметр «Отбор» при ОткрытьФорму

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

Автоподбор в поле ввода

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

Производительность и ограничения

Отбор с видом сравнения «Содержит» транслируется в условие ПОДОБНО с символом процента в начале строки, а такой запрос не использует индекс по полю. На справочнике в несколько сотен тысяч записей поиск может занимать заметное время. Если это критично, рассмотрите альтернативы: поиск по точному совпадению кода или артикула, полнотекстовый поиск или отдельный индексированный реквизит для поиска.

Второе ограничение — отбор динамического списка возможен только по полям, присутствующим в его запросе. Если в произвольном запросе динамического списка поле называется через псевдоним (например, Товары.Номенклатура КАК Товар), то в ЛевоеЗначение нужно указывать именно псевдоним «Товар», иначе отбор молча не сработает или выдаст ошибку.

Третий момент — событие ИзменениеТекстаРедактирования срабатывает на каждый символ, и каждый раз выполняется серверный вызов. На медленных соединениях это ощутимо. Практичное решение — обновлять отбор по событию ПриИзменении (когда поле потеряло фокус или нажат Enter) либо добавить кнопку «Найти».

Проверка результата и типичные ошибки

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

Ошибка «Поле не найдено» при установке отбора означает, что имя в ЛевоеЗначение не совпадает с полем запроса динамического списка. Проверьте псевдонимы в запросе и учтите, что обращение идёт по имени поля данных, а не по имени колонки таблицы формы.

Типичные ошибки
01
Не очищать коллекцию элементов отбора перед добавлением нового — условия накапливаются, и список показывает всё меньше записей
02
Указывать в ЛевоеЗначение имя колонки таблицы формы вместо поля данных динамического списка — отбор не применяется
03
Использовать вид сравнения «Равно» для поиска по части наименования — частичные совпадения не находятся
04
Добавлять элемент отбора при пустой строке поиска — список становится пустым вместо показа всех записей
05
Каждый символ ввода отправляет запрос на сервер без задержки — форма тормозит на больших списках
Контрольные точки

Как проверить результат

Ввод существующего значения
Норма

В списке остаются только подходящие записи

Тревожный признак

Список не меняется или пустеет при верном значении

Очистка поля поиска
Норма

Отображается полный список

Тревожный признак

Список остаётся отфильтрованным или пустым

Повторный ввод другого значения
Норма

Отбор заменяется новым, записи соответствуют только ему

Тревожный признак

Условия складываются, найти ничего нельзя

Отбор через параметр «Отбор» формы выбора
Норма

Форма открывается с отбором, который нельзя снять кнопкой

Тревожный признак

Отбор отсутствует или пользователь может его отключить

Частые вопросы

Как сделать отбор по нескольким значениям одного поля?

Передайте в правое значение массив или список значений и установите вид сравнения «В списке». При открытии формы выбора достаточно вставить массив в структуру «Отбор» — платформа сама преобразует его в нужное условие.

Почему отбор с видом сравнения «Содержит» работает медленно?

Условие «Содержит» превращается в ПОДОБНО с маской в начале строки, и СУБД не может использовать индекс по этому полю — выполняется полное сканирование. На больших таблицах лучше искать по точному совпадению индексированного поля (код, артикул) или применять полнотекстовый поиск.

Можно ли сделать отбор без программирования?

Да, пользователь может настроить отбор сам через «Ещё — Настроить список» на форме списка. Но привязать такой отбор к отдельному полю ввода на форме без кода нельзя — для реакции на изменение поля нужен обработчик события.

Как отобрать по полю табличной части документа?

Через структуру «Отбор» при открытии формы — никак. Нужно создать собственную форму со списком на произвольном запросе: в запросе соединить шапку с табличной частью, а отбор накладывать программно по полю из запроса.

Отбор установлен, но список не обновляется. Что проверить?

Убедитесь, что у элемента отбора свойство Использование равно Истина, что вы меняете отбор именно того динамического списка, который привязан к таблице формы, и что имя поля в ЛевоеЗначение совпадает с полем (или псевдонимом) в запросе списка.

Как доработать форму, не снимая конфигурацию с поддержки?

Используйте расширение конфигурации: форма заимствуется в расширение, туда добавляются поле ввода и обработчики. Типовой код не меняется, обновления конфигурации продолжают устанавливаться штатно.

Итог

Что важно запомнить

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