Разработка и Конфигурация · 10 мин
Как выбрать строки в 1С: практическое руководство
Как выбрать строки в 1С: запрос с условием ГДЕ, отбор в таблице значений, поиск в табличной части и динамическом списке. Примеры кода, ошибки, FAQ.
Задача «выбрать строчки» в 1С возникает в нескольких разных контекстах: нужно получить записи из базы данных запросом, отобрать строки в таблице значений или табличной части документа, настроить отбор в динамическом списке либо найти нужные позиции в форме списка. В каждом случае инструменты и синтаксис свои, и путаница между ними — частая причина ошибок у начинающих разработчиков и пользователей.
Ключевой принцип: чем ближе отбор к базе данных, тем быстрее работает код. Выборка запросом с условием ГДЕ почти всегда предпочтительнее, чем получение всех данных и последующая фильтрация в цикле. Поэтому правильный путь — сначала определить, где физически находятся данные (регистр, справочник, таблица значений в памяти, форма), а затем применить соответствующий механизм.
Ниже разобраны все основные сценарии: от запроса с параметрами до отбора строк табличной части и настройки динамического списка, с примерами кода, проверкой результата и типичными ошибками.
Выбор строк запросом с условием ГДЕ
Запрос — основной инструмент выборки данных из базы. Условие отбора задаётся в секции ГДЕ, а значения условий передаются через параметры. Прямая подстановка значений в текст запроса через конкатенацию строк — грубая ошибка: это и медленнее (запрос каждый раз компилируется заново), и небезопасно при работе с пользовательским вводом.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Товар,
| Номенклатура.Артикул КАК Артикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Родитель = &Группа
| И НЕ Номенклатура.ПометкаУдаления";
Запрос.УстановитьПараметр("Группа", ГруппаТоваров);
Результат = Запрос.Выполнить().Выбрать();
Пока Результат.Следующий() Цикл
Сообщить(Результат.Товар);
КонецЦикла;
Обратите внимание на типовые приёмы в секции ГДЕ: сравнение с параметром (= &Группа), проверка вхождения в список (В (&СписокЗначений)), отбор по иерархии (В ИЕРАРХИИ (&Группа)), отбор по шаблону строки (ПОДОБНО "%текст%") и проверка на NULL через ЕСТЬ NULL. Для виртуальных таблиц регистров (остатки, обороты, срез последних) условия лучше задавать в параметрах виртуальной таблицы в фигурных скобках, а не в секции ГДЕ — так отбор выполняется до соединения таблиц и работает заметно быстрее.
Отбор строк в таблице значений и табличной части
Когда данные уже находятся в памяти — в таблице значений, табличной части документа или данных формы — используется метод НайтиСтроки() с параметром типа Структура. Ключи структуры — имена колонок, значения — искомые значения. Метод возвращает массив найденных строк.
Отбор = Новый Структура;
Отбор.Вставить("Склад", СкладОтгрузки);
Отбор.Вставить("Отменено", Ложь);
НайденныеСтроки = ТаблицаТоваров.НайтиСтроки(Отбор);
Для Каждого СтрокаТовара Из НайденныеСтроки Цикл
СтрокаТовара.Количество = 0;
КонецЦикла;
Важное ограничение: НайтиСтроки() сравнивает значения только на точное равенство. Условия «больше», «содержит подстроку», «в списке» этим методом не выразить — понадобится цикл с проверкой условия вручную или запрос к временной таблице. Для поиска одной строки удобнее Найти(Значение, "ИмяКолонки"): он вернёт первую найденную строку или Неопределено.
Если по одной и той же таблице значений выполняется много поисков в цикле, добавьте индекс: ТаблицаЗначений.Индексы.Добавить("Номенклатура"). На таблицах в десятки тысяч строк это ускоряет НайтиСтроки() на порядки.
Отбор с помощью СКД и отчётов
Когда строки нужно выбрать для анализа, а не для обработки кодом, правильный инструмент — отчёт на системе компоновки данных. Пользователь задаёт отбор в настройках отчёта без всякого программирования: перетаскивает поле в отбор, выбирает вид сравнения (равно, в списке, в группе, не заполнено) и значение.
Преимущество СКД перед ручным запросом в том, что условия применяются на уровне запроса к базе, а не после получения данных. Отчёт с отбором «Контрагент в списке» выполнится быстро даже по регистру с миллионами записей, если поле отбора индексировано. Поэтому для разовых выборок «покажи все документы по этому контрагенту за период» не пишите обработку — используйте универсальный отчёт или отчёт по регистру.
Сравнение способов выбора строк
Для данных в базе. Самый быстрый, работает на сервере СУБД. Требует написания текста запроса.
Для таблиц значений и табличных частей в памяти. Только точное равенство по колонкам.
Для форм списков. Виден пользователю, тот может его изменить или снять.
Для аналитических выборок без программирования. Гибкие настройки, но результат — табличный документ, а не данные для обработки.
Проверка результата и типичные ошибки
После любой выборки проверяйте результат до того, как использовать его в дальнейшей логике. Для запроса — РезультатЗапроса.Пустой перед обходом или после Выбрать() проверка первого Следующий(). Для НайтиСтроки() — проверка НайденныеСтроки.Количество() = 0. Обращение к полям пустой выборки или к элементу пустого массива — классическая ошибка времени выполнения.
Отдельная группа проблем — несовпадение типов. Если параметр запроса имеет тип, отличный от типа поля (например, строка вместо ссылки на справочник), условие просто не сработает без всякой ошибки. Проверяйте тип значения параметра через отладчик, когда «запрос ничего не возвращает, хотя данные есть».
Как проверить результат выборки
РезультатЗапроса.Пустой = Ложь, выборка обходится
Пустой результат при заведомо существующих данных — проверяйте типы параметров
Количество() массива больше нуля
Пустой массив — проверьте имена колонок в структуре отбора
Выполняется за секунды на рабочей базе
Минуты на большом регистре — проверьте индексы и параметры виртуальных таблиц
FAQ: частые вопросы о выборе строк в 1С
Как выбрать строки, где поле не заполнено?
В запросе используйте условие на пустое значение соответствующего типа: ГДЕ Поле = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка) для ссылочных типов, ГДЕ Поле = "" для строк, либо ГДЕ Поле ЕСТЬ NULL, если поле может быть NULL (например, после левого соединения). В отборе СКД есть вид сравнения «Не заполнено».
Как выбрать строки по части наименования?
В запросе — оператор ПОДОБНО с шаблоном: ГДЕ Наименование ПОДОБНО "%" + &Фрагмент + "%". Учтите, что поиск с подстановочным знаком в начале шаблона не использует индекс и на больших справочниках работает медленно. В форме списка проще использовать стандартную строку поиска.
Чем НайтиСтроки отличается от Найти?
НайтиСтроки(СтруктураОтбора) возвращает массив всех строк, удовлетворяющих отбору по нескольким колонкам сразу. Найти(Значение, "Колонка") ищет по одной колонке и возвращает только первую найденную строку либо Неопределено. Для проверки существования строки достаточно Найти, для обработки всех совпадений — НайтиСтроки.
Почему запрос с условием не находит данные, которые точно есть?
Чаще всего причины три: несовпадение типов параметра и поля (строка вместо ссылки), лишние пробелы или неразрывные пробелы в строковых значениях, и отбор по виду документа/справочника, который не совпадает с фактическим. Проверьте значение параметра в отладчике и попробуйте тот же запрос в консоли запросов без условия.
Как выбрать строки из нескольких значений сразу (список)?
Передайте в параметр массив или список значений и используйте оператор В: ГДЕ Ссылка В (&СписокСсылок). Для иерархических справочников — В ИЕРАРХИИ (&Группы), тогда в выборку попадут элементы всех вложенных подгрупп.
Можно ли выбрать строки табличной части без перебора, по сложному условию?
НайтиСтроки поддерживает только равенство. Для сложных условий (диапазоны, «больше», «содержит») либо перебирайте строки в цикле с проверкой условия, либо выгрузите табличную часть в таблицу значений, поместите её в запрос как временную таблицу и отберите запросом — это оправдано при большом числе строк.
Что важно запомнить
Данные в базе выбирайте запросом с параметрами и условием ГДЕ, данные в памяти — методом НайтиСтроки со структурой отбора, списки в формах — отбором динамического списка, аналитические выборки — отчётом на СКД. Всегда проверяйте результат на пустоту и следите за соответствием типов параметров.