Разработка и Конфигурация · 11 мин
Как найти строку в динамическом списке в 1С
Как найти строку в динамическом списке 1С: поиск через пользовательский интерфейс, программная установка отбора, метод НайтиСтроки и типичные ошибки разработчиков.
Динамический список в 1С — это объект формы, который отображает данные из базы с автоматическим обновлением: списки документов, справочников, регистров. В отличие от таблицы значений, его нельзя просто перебрать в цикле на сервере, потому что данные подгружаются порциями по мере прокрутки. Поэтому задача «найти строку» решается по-разному в зависимости от того, кто ищет — пользователь в интерфейсе или разработчик в коде.
Чаще всего под поиском строки понимают три разные задачи: быстро найти запись визуально в открытом списке, программно установить отбор, чтобы список показал только нужные строки, или проверить в коде, существует ли запись с заданными условиями. Каждая из этих задач имеет свой инструмент, и смешивание подходов — главный источник ошибок.
Ниже разобраны все рабочие способы: от штатного поиска в пользовательском режиме до программной настройки отбора динамического списка и обходных путей через запрос, когда штатных средств недостаточно.
Поиск строки в пользовательском режиме
В обычном приложении и в управляемых формах пользователь может найти строку без программирования. Основной инструмент — строка поиска, которая вызывается сочетанием клавиш Ctrl+F или через меню «Ещё» → «Найти». Поиск выполняется по отображаемым колонкам текущего списка, поэтому если нужной колонки нет на форме, по ней искать не получится.
Второй способ — кнопка «Найти» на панели списка в виде поля ввода (в типовых конфигурациях она часто называется «Поиск»). Введённый текст фильтрует список по всем видимым полям одновременно. Это быстрее, чем настраивать отбор, но менее точно: например, поиск по фрагменту «Иван» покажет и контрагента «Иванов», и документ, где «Иван» встречается в комментарии.
Третий вариант — отбор через «Ещё» → «Настроить список». Здесь пользователь задаёт условие по конкретному полю: равно, содержит, в списке, больше/меньше для дат и чисел. Отбор сохраняется при закрытии формы, если в конфигурации включено сохранение пользовательских настроек.
- 1Откройте нужный список (документы, справочник, регистр)
- 2Нажмите Ctrl+F и введите искомое значение, либо воспользуйтесь полем поиска на панели
- 3Если результатов слишком много, откройте «Ещё» → «Настроить список» и задайте отбор по конкретному полю
- 4Проверьте, что список отфильтрован и нужная строка видна
- 5После работы снимите отбор, если он больше не нужен, чтобы не потерять остальные записи
Почему динамический список нельзя перебрать в цикле
Разработчики, привыкшие к таблицам значений, часто пытаются обойти динамический список методом вроде «Для Каждого Строка Из Список Цикл» и получают ошибку. Динамический список — это не коллекция данных в памяти, а механизм выполнения запроса к базе с постраничной выдачей. В памяти формы в каждый момент находится только видимая часть строк, остальные подгружаются при прокрутке.
Из этого следует главный принцип: чтобы «найти» строку программно, нужно не искать её в списке, а изменить условия выборки — установить отбор или изменить текст запроса динамического списка. Тогда СУБД сама вернёт только нужные записи, что к тому же работает быстрее любого перебора.
Программная установка отбора динамического списка
Стандартный способ найти строки по условию — добавить элемент в коллекцию Список.Отбор.Элементы. Отбор применяется сразу после установки, список обновляется автоматически. Код выполняется на сервере (в обработчике ПриСозданииНаСервере) или в серверной процедуре, вызываемой с клиента.
Пример: показать в списке документов только проведённые документы по конкретному контрагенту. Оба условия соединяются по «И», потому что находятся в корневой группе отбора.
&НаСервере
Процедура УстановитьОтборПоКонтрагенту(Контрагент)
ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Контрагент");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = Контрагент;
ЭлементОтбора.Использование = Истина;
ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
КонецПроцедуры
Обратите внимание на свойство РежимОтображения. Значение Недоступный скрывает отбор от пользователя: он не сможет его снять через настройки списка. Если нужно, чтобы пользователь видел и мог менять отбор, используйте Обычный или БыстрыйДоступ.
Отбор по нескольким значениям и по части строки
Для поиска по нескольким значениям используется вид сравнения ВСписке с массивом или списком значений в правой части. Для поиска подстроки — вид сравнения Содержит. Учтите, что «Содержит» в большинстве СУБД не использует индекс и на больших таблицах работает медленно.
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит;
ЭлементОтбора.ПравоеЗначение = "Иван";
Как спозиционироваться на конкретной строке
Отдельная задача — не отфильтровать список, а найти нужную запись и поставить на неё курсор. Для этого у таблицы формы, связанной с динамическим списком, есть свойство ТекущаяСтрока. Ему присваивается ссылка на объект: платформа найдёт эту строку в списке и выделит её.
&НаКлиенте
Процедура ПерейтиКДокументу(СсылкаНаДокумент)
Элементы.Список.ТекущаяСтрока = СсылкаНаДокумент;
КонецПроцедуры
Если документ не попадает под установленный отбор или находится за пределами загруженной части, платформа всё равно попытается спозиционироваться, но при активных отборах строка может просто не отображаться. Поэтому перед позиционированием стоит убедиться, что отборы не исключают искомую запись.
При открытии формы списка с параметром ТекущаяСтрока позиционирование происходит автоматически — передавать ссылку вручную после открытия не нужно. Это стандартное поведение для переходов «перейти к документу» из отчётов.
Проверка существования записи через запрос
Когда задача — не показать строку пользователю, а узнать в коде, есть ли запись с нужными условиями, динамический список вообще не нужен. Правильный инструмент — запрос к базе данных. Это работает и без формы, и в фоновых заданиях, и на сервере.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Документы.Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Документы
|ГДЕ
| Документы.Номер = &Номер
| И Документы.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания";
Запрос.УстановитьПараметр("Номер", ИскомыйНомер);
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
// запись найдена
КонецЕсли;
Конструкция ПЕРВЫЕ 1 важна: она ограничивает выборку одной записью и не заставляет сервер перебирать всё множество подходящих строк. Для проверки факта существования это оптимальный вариант.
Сравнение вариантов поиска
Подходит, когда результат нужно показать пользователю в форме списка. Ограничение: отбор возможен только по полям запроса списка.
Подходит для перехода к известной ссылке. Не работает, если запись исключена отбором или не существует.
Подходит для проверки существования и получения данных в коде без формы. Требует написания текста запроса и прав с чтение таблицы.
Подходит, когда штатного отбора недостаточно (вычисляемые поля, соединения). Требует аккуратности: ломается стандартная группировка и динамическое считывание.
Поиск через произвольный запрос динамического списка
Если штатного отбора недостаточно — например, нужно искать по вычисляемому полю или по данным связанной таблицы, — динамическому списку можно задать собственный текст запроса. Для этого в свойствах списка включается флаг «Произвольный запрос», а текст вводится вручную или формируется программно через Список.ТекстЗапроса.
У этого подхода есть цена: при произвольном запросе нужно явно указать основную таблицу (свойство ОсновнаяТаблица), иначе пропадёт динамическое обновление и стандартные команды вроде «Создать» и «Обновить» могут работать некорректно. Также платформа добавляет пользовательские отборы к произвольному запросу через конструкцию с условиями, поэтому запрос должен быть написан с учётом этого.
Типичные ошибки и их диагностика
Самая частая ошибка — попытка установить отбор по полю, которого нет в запросе списка. Платформа выдаёт ошибку «Поле не найдено» либо отбор молча не работает, если поле указано с опечаткой. Проверить состав доступных полей можно в настройке динамического списка в конфигураторе.
Вторая ошибка — установка отбора на клиенте. Коллекция отбора динамического списка доступна для изменения на сервере; попытка изменить её в клиентской процедуре приводит к ошибке вызова. Правильный шаблон: клиентская процедура вызывает серверную, та меняет отбор, список обновляется сам.
Третья группа проблем — производительность: отбор по неиндексированному полю с видом сравнения «Содержит» на таблице в сотни тысяч записей заставляет список «зависать» при каждом обновлении. В таких случаях ищите по индексированным полям (номер, дата, ссылка) или добавьте индексирование реквизиту в конфигураторе.
Как проверить результат
Отображаются только строки, удовлетворяющие условию
Список пустой или отбор не применился — проверьте имя поля и вид сравнения
Курсор встал на нужную строку, она подсвечена
Строка не найдена — проверьте, не исключает ли её текущий отбор
Список обновляется без заметной задержки
Заметная пауза — условие идёт по неиндексированному полю
FAQ: частые вопросы о поиске в динамическом списке
Как снять программно установленный отбор?
Удалите элемент из коллекции: найдите его в Список.Отбор.Элементы и вызовите метод Удалить, либо установите свойству Использование значение Ложь. Второй вариант удобен, если отбор нужно временно отключить и потом включить снова без пересоздания.
Можно ли искать сразу по нескольким полям с условием «ИЛИ»?
Да. Добавьте в отбор группу элементов с типом ГруппаЭлементовОтбораКомпоновкиДанных.ГруппаИли и поместите в неё условия по разным полям. Например, «Номер содержит текст ИЛИ Комментарий содержит текст».
Почему поиск по части номера документа не находит запись?
Номер документа хранится как строка фиксированной длины с лидирующими нулями. Если в базе номер «0000-001234», поиск «1234» через «Равно» ничего не найдёт. Используйте вид сравнения «Содержит» или учитывайте полный формат номера с префиксом.
Как найти строку, если список строится по регистру сведений?
Так же, как для документов: отбор по измерениям и реквизитам регистра. Для независимых регистров сведений удобно позиционироваться через ключ записи — его можно получить запросом и присвоить свойству ТекущаяСтрока таблицы формы.
Можно ли сохранить настройки отбора между сеансами?
Да, если у формы включено автоматическое сохранение пользовательских настроек (свойство формы) — платформа сама сохранит отборы, сделанные через «Настроить список». Программно установленные отборы с режимом отображения «Недоступный» не сохраняются и применяются заново при каждом открытии.
Что важно запомнить
Динамический список нельзя перебрать — строку в нём «находят» отбором или позиционированием по ссылке. Отбор устанавливается только на сервере и только по полям запроса списка. Для проверки существования записи в коде используйте запрос с ПЕРВЫЕ 1, а не форму списка.