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

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

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

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

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

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

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

Метод Найти: поиск одной строки по значению колонки

Метод Найти() ищет первую строку, в которой указанная колонка равна переданному значению. Синтаксис: ТЗ.Найти(ИскомоеЗначение, ИмяКолонки). Имя колонки передаётся строкой, при необходимости можно указать несколько колонок через запятую — тогда поиск пойдёт последовательно по каждой из них.

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

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

Сообщить("Строка с такой номенклатурой не найдена");

Иначе

НайденнаяСтрока.Количество = НайденнаяСтрока.Количество + 1;

КонецЕсли;

Ключевой момент: если строка не найдена, метод возвращает Неопределено, а не вызывает ошибку. Поэтому обращаться к полям результата можно только после проверки. Обращение НайденнаяСтрока.Количество без проверки при отсутствии строки приведёт к ошибке «Поле объекта не обнаружено».

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

Метод НайтиСтроки: поиск по одному или нескольким условиям

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

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

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

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

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

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

СтрокаТовара.Количество = СтрокаТовара.Количество + 1;

КонецЦикла;

Условия в структуре объединяются по «И»: строка попадёт в результат, только если совпадут значения всех перечисленных колонок. Если подходящих строк нет, метод вернёт пустой массив — проверка выполняется через НайденныеСтроки.Количество() = 0.

Компактная форма записи той же структуры: Новый Структура("Номенклатура, Склад", НоменклатураСсылка, СкладСсылка). Порядок значений должен соответствовать порядку имён колонок.

bsl
Отбор = Новый Структура("Контрагент, Договор", КонтрагентСсылка, ДоговорСсылка);
Строки = ТаблицаОплат.НайтиСтроки(Отбор);
Если Строки.Количество() > 0 Тогда
    СуммаОплат = Строки[0].Сумма;
КонецЕсли;

Поиск через цикл: когда методов недостаточно

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

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

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

И СтрНайти(СтрокаТовара.Наименование, "услуга") > 0 Тогда

// строка удовлетворяет сложному условию

КонецЕсли;

КонецЦикла;

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

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

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

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

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

Ускорение поиска: индексы таблицы значений

Если поиск по одной и той же колонке выполняется многократно — например, внутри цикла обхода другой таблицы — имеет смысл добавить индекс. Это делается одной строкой: ТаблицаТоваров.Индексы.Добавить("Номенклатура").

После добавления индекса методы Найти() и НайтиСтроки() по этой колонке начинают работать существенно быстрее. Индекс поддерживается автоматически при добавлении и удалении строк, поэтому дополнительный код сопровождения не нужен.

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

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

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

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

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

Типичные ошибки
01
Обращение к полям результата Найти() без проверки на Неопределено — ошибка «Поле объекта не обнаружено» при отсутствии строки
02
Поиск ссылки по строковому наименованию или наоборот — типы не совпадают, метод молча возвращает пустой результат
03
Опечатка в имени колонки в строке — ошибка «Колонка не найдена» возникает только в момент выполнения, а не при проверке модуля
04
Отбор по нескольким колонкам через несколько вызовов Найти() вместо одной структуры — лишний код и риск логической ошибки
05
Перебор большой таблицы в цикле без Прервать и без индекса — замедление проведения документов

Ограничения и альтернативные подходы

Методы Найти() и НайтиСтроки() не поддерживают неравенства, вхождение в список и сравнение по части значения. Всё, что выходит за рамки равенства, решается циклом или запросом.

Если данные уже находятся в базе, а таблица значений нужна только для промежуточной обработки, часто эффективнее выполнить отбор сразу в запросе с условием ГДЕ — это переносит работу на СУБД и сокращает объём перекачиваемых данных.

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

Итог

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

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

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

Что возвращает Найти(), если строка не найдена?

Значение Неопределено. Ошибки при этом не возникает, поэтому перед обращением к полям результата обязательно выполняйте проверку «Если Строка = Неопределено».

Как найти строку по двум и более условиям?

Используйте НайтиСтроки со структурой отбора: Новый Структура("Колонка1, Колонка2", Значение1, Значение2). Условия объединяются по «И». Если нужна только первая строка, возьмите нулевой элемент массива после проверки его количества.

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

Чаще всего не совпадают типы: в колонке ссылка, а ищется строка, или число сравнивается со строкой. Также проверьте лишние пробелы в строковых значениях и точность имени колонки.

Можно ли искать по части строки, например по фрагменту наименования?

Штатные методы Найти и НайтиСтроки этого не умеют — они работают только на полное равенство. Переберите таблицу в цикле и используйте СтрНайти(Строка.Наименование, Фрагмент) > 0.

Работают ли эти методы для табличных частей документа?

Да, табличные части поддерживают Найти и НайтиСтроки с тем же синтаксисом, что и таблица значений: ДокументОбъект.Товары.НайтиСтроки(Отбор).

Как ускорить многократный поиск в большой таблице?

Добавьте индекс по колонке поиска: ТЗ.Индексы.Добавить("Номенклатура"). После этого Найти и НайтиСтроки будут работать заметно быстрее. Если данные можно отобрать на стороне СУБД, рассмотрите запрос с условием ГДЕ.