Поле поиска в 1С 8.3: от реквизита формы до кода

· 10 мин

Содержание

Проще всего поле поиска добавить так: открыть форму в Конфигураторе, завести строковый реквизит, положить его на форму и в обработчике ПриИзменении передать текст в отбор динамического списка. Это 10–15 строк кода и ни одной внешней библиотеки.

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

Какой способ поиска выбрать

Сначала определитесь с задачей — от неё зависит объём работы.

  • 🔍 Встроенный поиск списка — ничего не программируете. Пользователь жмёт Ctrl+F или начинает печатать в списке, платформа ищет по видимым колонкам. Подходит в 90% случаев.
  • 🧩 Свой реквизит + отбор — отдельное поле ввода над таблицей, фильтрует динамический список по нужным полям (наименование, артикул, ИНН). Нужно, когда поиск должен работать по не видимым в таблице реквизитам.
  • 📑 Запрос или СКД — когда данные собираются из нескольких таблиц или с расчётами, и список формируется не напрямую из справочника.
  • 🌐 Полнотекстовый поиск — поиск слова сразу по всем объектам базы (как у поисковика). Для «найти всё, где встречается этот артикул или фамилия».

Если конфигурация на поддержке, не снимайте её с замка ради одного поля — используйте расширение конфигурации (последний раздел).

Дальше — по порядку, от самого простого к коду.

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

Любая таблица формы, построенная на динамическом списке, уже умеет искать. Отдельное поле заводить не обязательно.

Пользователю доступны:

  1. Быстрый поиск — встать в таблицу и начать печатать. Платформа подсветит первую подходящую строку по текущей колонке.
  2. Поиск по Ctrl+F — откроется строка поиска с выбором колонки и режима (с начала строки / любое вхождение).
  3. Расширенный отбор — команда «Ещё» → «Настроить список» → вкладка «Отбор», где задают условия по любому реквизиту.

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

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

Этого хватает, пока не требуется своё поле ввода с особым поведением. Если требуется — переходим к реквизиту формы.

Реквизит формы для ввода запроса

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

Порядок в Конфигураторе:

  1. Откройте нужную форму (например, форму списка справочника Номенклатура).
  2. Вкладка «Реквизиты» формы → кнопка «Добавить». Назовите реквизит, например ТекстПоиска, тип — Строка (длина 0 — неограниченная или, скажем, 150).
  3. Перетащите реквизит из «Реквизитов» в дерево «Элементы» — на форме появится поле ввода.
  4. В свойствах элемента задайте заголовок («Поиск»), а в поле РежимРедактированияТекста при желании — МногострочныйРежим = Ложь.
  5. Чтобы поиск срабатывал на каждый символ, в свойствах поля включите РежимИзменения → «ПриИзменении» (а не «ПриЗавершении»), тогда событие будет вызываться по мере ввода.

Теперь поле есть, но оно ничего не делает. Логику добавим в следующем разделе — через отбор динамического списка.

Длинную строку поиска без ограничения лучше не делать: пользователь может вставить абзац текста, и это уйдёт в условие отбора. 100–150 символов достаточно.

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

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

Клиентская часть — обработчик события поля ТекстПоиска:

&НаКлиенте
Процедура ТекстПоискаПриИзменении(Элемент)
    УстановитьОтборПоиска(ТекстПоиска);
КонецПроцедуры

Серверная часть — собирает условие отбора:

&НаСервере
Процедура УстановитьОтборПоиска(Текст)

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

    Если ПустаяСтрока(Текст) Тогда
        Возврат;
    КонецЕсли;

    Элемент = Список.Отбор.Элементы.Добавить(
        Тип("ЭлементОтбораКомпоновкиДанных"));
    Элемент.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("Наименование");
    Элемент.ВидСравнения   = ВидСравненияКомпоновкиДанных.Содержит;
    Элемент.ПравоеЗначение = Текст;
    Элемент.Использование  = Истина;

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

Разберём ключевые моменты:

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

Если нужно искать сразу по нескольким полям (наименование ИЛИ артикул), добавьте группу отбора с типом Или:

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

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

Этот подход хорош тем, что динамический список сам дочитывает данные порциями — вы не грузите весь справочник в память.

Поиск через запрос и СКД

Когда список формируется не напрямую из справочника, а запросом (например, остатки с ценами из нескольких регистров), поиск встраивают в сам запрос.

Простой вариант — параметр в условии ГДЕ:

ВЫБРАТЬ
    Номенклатура.Ссылка       КАК Ссылка,
    Номенклатура.Наименование КАК Наименование,
    Номенклатура.Артикул      КАК Артикул
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.Наименование ПОДОБНО &Текст

Параметр подставляют со спецсимволами шаблона:

Запрос.УстановитьПараметр("Текст", "%" + ТекстПоиска + "%");

% в операторе ПОДОБНО означает «любое число любых символов». %слово% — вхождение в любом месте, слово% — в начале.

Если список выводится через систему компоновки данных (СКД) — например, в отчёте или в форме с полем табличного документа — текст поиска передают как параметр компоновки, а в схеме делают отбор:

&НаСервере
Процедура ПрименитьПоискСКД(Текст)
    КомпоновщикНастроек = Отчёт.КомпоновщикНастроек;
    ЭлементыОтбора = КомпоновщикНастроек.Настройки.Отбор.Элементы;
    ЭлементыОтбора.Очистить();

    Если НЕ ПустаяСтрока(Текст) Тогда
        Отб = ЭлементыОтбора.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
        Отб.ЛевоеЗначение  = Новый ПолеКомпоновкиДанных("Наименование");
        Отб.ВидСравнения   = ВидСравненияКомпоновкиДанных.Содержит;
        Отб.ПравоеЗначение = Текст;
        Отб.Использование  = Истина;
    КонецЕсли;
КонецПроцедуры

В СКД отбор по «Содержит» транслируется в тот же ПОДОБНО на уровне запроса к СУБД, поэтому правила те же, что и выше.

Не подставляйте текст поиска прямым склеиванием в текст запроса. Только через УстановитьПараметр или элемент отбора — это и безопаснее, и позволяет СУБД переиспользовать план запроса.

Клиент и сервер: как разнести код правильно

Управляемое приложение разделяет выполнение на клиент и сервер, и поиск — наглядный пример, где это важно.

Коротко, что где работает:

ДирективаГде выполняетсяЧто можно
&НаКлиентена компьютере пользователяловить события поля, читать введённый текст
&НаСерверена сервере, с контекстом формыменять Список.Отбор, выполнять запрос
&НаСервереБезКонтекстана сервере, без формытяжёлые выборки, где контекст формы не нужен

Правила, которые экономят нервы:

  • Отбор динамического списка (Список.Отбор) меняют только на сервере — на клиенте этот объект недоступен для записи.
  • Запросы к базе выполняются на сервере. Клиент запрос выполнить не может в принципе.
  • Чем меньше контекста формы вы тащите на сервер, тем быстрее вызов. Если процедуре поиска нужен только текст — выносите её в &НаСервереБезКонтекста и передавайте текст параметром, возвращая готовый результат.

Типичная ошибка новичка — попытка поменять отбор прямо в клиентском обработчике. Платформа выдаст ошибку компиляции: нужный объект на клиенте «не виден». Решение всегда одно — серверная процедура, как в примерах выше.

Полнотекстовый поиск по всей базе

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

Чтобы он работал, индекс должен быть включён и построен. Обновление индекса обычно ставят в регламентное задание:

ПолнотекстовыйПоиск.ОбновитьИндекс(Ложь);

Сам поиск из кода:

СписокПоиска = ПолнотекстовыйПоиск.СоздатьСписок(ТекстПоиска, 20);
СписокПоиска.ПервыйЧасть();

Для Каждого Элемент Из СписокПоиска Цикл
    Сообщить(Элемент.Значение);
КонецЦикла;
  • Второй параметр СоздатьСписок — размер порции результатов.
  • Полнотекстовый поиск понимает морфологию: по запросу «договор» найдёт и «договора», и «договору». Это его главное отличие от ПОДОБНО.
  • Индекс не обновляется мгновенно: только что созданный документ попадёт в поиск после ближайшего ОбновитьИндекс.

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

Чем способы отличаются на практике

Сводная таблица — чтобы выбрать под свою задачу:

СпособКод нуженПо каким полямНагрузкаКогда брать
Встроенный поиск списканетвидимые колонкиминимальнаябольшинство форм списка
Реквизит + отбор~15 строклюбые поля объектанизкаясвоё поле над таблицей
Запрос / СКДсреднелюбые, в т.ч. из регистровзависит от запросасложные списки и отчёты
Полнотекстовый поиск~10 строквся база, с морфологиейиндекс + его обновлениеглобальный поиск по слову

Общее правило: не усложняйте. Если хватает встроенного поиска — не пишите код. Отдельный реквизит оправдан, когда нужно искать по невидимым полям или по нескольким сразу.

Производительность: почему поиск тормозит

На справочнике в сотни тысяч строк неудачный поиск «думает» секундами. Чаще всего виноват один из пунктов ниже.

Диагностика: выберите симптом

Ещё две вещи, которые помогают держать поиск быстрым:

  • 🏎️ Индексируйте поля поиска. Для реквизита справочника в Конфигураторе есть свойство «Индексировать». Для частого поиска по артикулу — включите его.
  • 📦 Не грузите всё в память. Динамический список читает данные порциями сам. Не заменяйте его на загрузку всего справочника в таблицу значений ради поиска — это и есть причина «зависаний» на больших базах.

Поле поиска через расширение конфигурации

Если основная конфигурация на поддержке и снимать её с замка нельзя, поле поиска добавляют расширением — не трогая типовую форму.

Порядок действий:

  1. В Конфигураторе: меню «Конфигурация» → «Расширения конфигурации », создайте расширение (назначение — «Адаптация»).
  2. В расширение добавьте нужную форму — платформа предложит заимствовать её из основной конфигурации.
  3. В заимствованной форме добавьте свой реквизит ТекстПоиска и элемент поля, как описано выше.
  4. Обработчик события и серверную процедуру напишите в модуле формы расширения.

При обновлении типовой конфигурации расширение, как правило, продолжает работать — вы не меняли саму форму, а дополнили её. Это штатный способ дорабатывать типовые решения без снятия с поддержки.

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

Проверьте себя
Где меняют отбор динамического списка?
Какой оператор запроса ищет вхождение подстроки?
Что отличает полнотекстовый поиск от `ПОДОБНО`?

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

Почему мой обработчик поиска не вызывается при вводе?
Скорее всего, у поля стоит режим изменения «ПриЗавершении» — тогда событие срабатывает только при потере фокуса. Для поиска «на лету» переключите свойство поля на «ПриИзменении».
Можно ли сделать поиск без программирования вообще?
Да. Встроенный поиск динамического списка (Ctrl+F и быстрый поиск при вводе) работает без единой строки кода. Код нужен только для своего поля над таблицей или для нестандартной логики.
Как искать сразу по наименованию и по коду?
Добавьте в отбор группу с типом «ИЛИ» и в неё два условия «Содержит» — по наименованию и по коду. Пример группы есть в разделе про отбор динамического списка.
Регистр букв важен при поиске?
Для ПОДОБНО и «Содержит» регистр обычно не учитывается — зависит от настроек сравнения базы данных. Полнотекстовый поиск регистр не различает в принципе.
Чем отбор отличается от параметра динамического списка?
Отбор фильтрует уже выбранные строки по условию. Параметр подставляется внутрь запроса динамического списка (если список задан произвольным запросом) и влияет на сам отбор данных из базы — он эффективнее, когда поиск нужно учитывать до выборки.