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

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

Как отобрать строки в таблице значений 1С

Способы отбора строк в таблице значений 1С: НайтиСтроки, Найти, параметры отбора, циклы и запросы. Примеры кода, типичные ошибки и рекомендации.

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

Платформа 1С предлагает несколько подходов к отбору: методы НайтиСтроки() и Найти() со структурой параметров, перебор строк в цикле с проверкой условий, а также выгрузку таблицы в запрос с конструкцией ГДЕ. Каждый способ имеет свои ограничения по скорости, гибкости условий и удобству сопровождения кода.

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

Отбор одной строки методом Найти()

Метод Найти(Значение, Колонки) возвращает первую найденную строку таблицы значений или Неопределено, если совпадений нет. Он подходит, когда нужно проверить существование строки или получить одну конкретную запись — например, найти товар по коду или сотрудника по табельному номеру.

СтрокаТовара = ТаблицаТоваров.Найти(КодТовара, "Код");

Если СтрокаТовара = Неопределено Тогда

Сообщить("Товар с кодом " + КодТовара + " не найден");

Иначе

Цена = СтрокаТовара.Цена;

КонецЕсли;

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

Важно помнить: сравнение выполняется строго по значению и типу. Строка «001» и число 1 — разные значения, и поиск не найдёт совпадения. Это одна из самых частых причин «неработающего» отбора.

Отбор нескольких строк методом НайтиСтроки()

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

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

ПараметрыОтбора.Вставить("Склад", ВыбранныйСклад);

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

НайденныеСтроки = ТаблицаОстатков.НайтиСтроки(ПараметрыОтбора);

Для Каждого Строка Из НайденныеСтроки Цикл

ОбщееКоличество = ОбщееКоличество + Строка.Количество;

КонецЦикла;

Условия в структуре объединяются по логике «И»: строка попадёт в результат, только если совпадут все указанные значения. Условия «ИЛИ», «не равно», «больше/меньше» через структуру задать нельзя — для них нужен цикл или запрос.

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

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

Когда условие сложнее простого равенства — диапазоны дат, сравнение «больше нуля», проверка заполненности, комбинации «ИЛИ» — используется прямой перебор строк с проверкой внутри цикла.

Для Каждого Строка Из ТаблицаПродаж Цикл

Если Строка.Сумма > 100000

И (Строка.Менеджер = ТекущийМенеджер

Или Строка.Менеджер = Заместитель) Тогда

// обработка подходящей строки

КонецЕсли;

КонецЦикла;

Цикл даёт полную свободу условий, но требует аккуратности при удалении строк. Если нужно удалить часть строк таблицы, перебирайте её в обратном порядке по индексу — иначе после удаления индексы сместятся и часть строк будет пропущена:

Для Инд = 1 - Таблица.Количество() По 0 Цикл

Если Таблица[-Инд].Пометка Тогда

Таблица.Удалить(-Инд);

КонецЕсли;

КонецЦикла;

Альтернатива — собрать подходящие строки в новую таблицу через Скопировать() с параметром отбора или добавлять строки в пустую таблицу-копию структуры. Такой подход безопаснее, когда исходную таблицу нужно сохранить без изменений.

Типичные ошибки
01
Удаление строк в прямом цикле перебора — после удаления индексы смещаются, часть строк пропускается. Удаляйте в обратном порядке по индексу.
02
Сравнение значений разных типов: строка «1» не равна числу 1, отбор молча ничего не находит. Приводите типы явно.
03
Обращение к НайденныеСтроки[0] без проверки Количество() — при пустом результате возникает ошибка обращения за границу массива.
04
Лишние пробелы и неразрывные пробелы в строковых значениях — отбор по равенству не срабатывает. Используйте СокрЛП() при подготовке данных.

Отбор через запрос к таблице значений

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Таб.Номенклатура,

| СУММА(Таб.Количество) КАК Количество

|ПОМЕСТИТЬ ВТ_Данные

|ИЗ &Таблица КАК Таб

|;

|ВЫБРАТЬ *

|ИЗ ВТ_Данные

|ГДЕ ВТ_Данные.Количество > 0";

Запрос.УстановитьПараметр("Таблица", ТаблицаЗначений);

Результат = Запрос.Выполнить().Выгрузить();

Запрос поддерживает всю гибкость языка запросов: условия ГДЕ с любыми операторами сравнения, В ИЕРАРХИИ, соединения с таблицами базы данных, агрегатные функции. Плата за это — накладные расходы на передачу таблицы и выполнение запроса, поэтому для простого отбора по равенству запрос избыточен.

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

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

Найти()

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

НайтиСтроки()

Все строки по равенству одного или нескольких полей (логика И). Не поддерживает неравенства, диапазоны и ИЛИ.

Цикл с условием

Любые условия и логика. Требует аккуратности при удалении строк; код длиннее.

Запрос к таблице

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

Отбор в табличной части и на форме

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

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

Для реквизита формы типа «ТаблицаЗначений» методы поиска доступны напрямую в серверных процедурах. В клиентском контексте таблица представлена как ДанныеФормыКоллекция, где НайтиСтроки() тоже работает, но параметры отбора передаются той же структурой.

Маршрут решения

Как выбрать действие

Нужно проверить существование строки или получить одну запись по значениюИспользуйте Найти(Значение, "Колонка") и проверяйте результат на Неопределено
Нужны все строки с равенством по одному или нескольким полямИспользуйте НайтиСтроки() со структурой параметров отбора
Условия содержат неравенства, диапазоны, ИЛИ или функцииПереберите таблицу в цикле с проверкой условий
Нужны группировки, итоги или соединение с данными базыПередайте таблицу в запрос через параметр и используйте ГДЕ
Требуется удалить часть строк таблицыУдаляйте в цикле по индексу в обратном порядке

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

После отбора всегда проверяйте результат перед использованием: для Найти() — сравнение с Неопределено, для НайтиСтроки() — проверка Количество() у возвращённого массива. Обращение к несуществующей строке или элементу пустого массива приведёт к ошибке исполнения.

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

Ещё один приём ускорения — индексация: метод Индексы.Добавить("Колонка") создаёт индекс таблицы значений, после чего поиск по этой колонке выполняется быстрее. Индексы оправданы при многократных поисках по большой таблице; для разового отбора их создание не окупается.

Контрольные точки

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

Результат Найти()
Норма

Возвращена строка, поля доступны для чтения

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

Возвращено Неопределено — значение не найдено или не совпал тип

Результат НайтиСтроки()
Норма

Массив с Количество() > 0, строки содержат ожидаемые значения

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

Пустой массив при заведомо существующих данных — проверяйте типы и пробелы

Изменение найденной строки
Норма

Изменение видно в исходной таблице (это ссылка на строку)

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

Ожидалась копия, а изменилась исходная таблица — используйте Скопировать()

Отбор после удаления строк
Норма

Удалены все помеченные строки, таблица корректна

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

Часть строк пропущена — удаление шло в прямом цикле перебора

Частые вопросы по отбору строк

Можно ли в НайтиСтроки() задать условие «не равно» или «больше»?

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

Почему НайтиСтроки() не находит строку, хотя значение в таблице есть?

Чаще всего не совпадают типы (строка вместо числа), различается длина строки в колонке фиксированной длины или в значении есть лишние пробелы. Проверьте тип колонки, примените СокрЛП() к строковым значениям и приведите искомое значение к типу колонки.

Изменение найденной строки меняет исходную таблицу — это нормально?

Да, Найти() и НайтиСтроки() возвращают ссылки на строки исходной таблицы, а не копии. Если нужна независимая копия данных, используйте метод Скопировать() у таблицы с параметром отбора или скопируйте отдельную строку в новую таблицу.

Как отобрать строки по части строки, например по вхождению подстроки?

Методы Найти() и НайтиСтроки() работают только по полному равенству. Для поиска по подстроке переберите таблицу в цикле с функцией СтрНайти() либо передайте таблицу в запрос и используйте оператор ПОДОБНО с шаблоном.

Что быстрее: НайтиСтроки() или перебор в цикле?

При одиночном отборе по равенству НайтиСтроки() обычно эффективнее и короче в коде. При многократных поисках по большой таблице оба варианта медленные — выигрыш даёт построение соответствия для прямого доступа к строкам или добавление индекса по колонке поиска.

Как отобрать строки в динамическом списке на форме?

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

Итог

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

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