При изучении программирования в 1С начинающие разработчики часто сталкиваются с ситуацией, когда условие проверки результатов поиска строк в таблице значений или табличной части срабатывает всегда, независимо от того, есть ли искомый элемент в таблице. Разберем по шагам, почему так происходит, как устроена работа метода НайтиСтроки и какие подходы следует применять для корректной обработки данных.
Рассмотрим распространенный пример некорректного кода:
ТекТовар = Справочники.Номенклатура.НайтиПоНаименованию("Стул высокий");
ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("Товар", ТекТовар);
НЗ = Товары.НайтиСтроки(ПараметрыОтбора);
Если НЗ <> Неопределено Тогда
Сообщить("Верно");
Иначе
Сообщить("Нет");
КонецЕсли;
В данном примере условие Если НЗ <> Неопределено будет выполняться всегда, даже если в таблице Товары нет ни одной строки с указанным товаром.
Выясним причину этого поведения: согласно синтаксису платформы 1С, метод НайтиСтроки() возвращает значение типа Массив. Объект типа Массив существует всегда — даже если по вашему отбору ничего не было найдено, метод вернет пустой массив, но не значение Неопределено.
Чтобы выяснить, есть ли в таблице строки, соответствующие отбору, необходимо проверять количество элементов в возвращенном массиве с помощью метода Количество().
Правильный вариант проверки выглядит следующим образом:
ПараметрыОтбора = Новый Структура("Товар", ТекТовар);
НайденныеСтроки = Товары.НайтиСтроки(ПараметрыОтбора);
Если НайденныеСтроки.Количество() > 0 Тогда
Сообщить("Строки найдены! Найдено штук: " + НайденныеСтроки.Количество());
Иначе
Сообщить("Строки с таким товаром не найдены.");
КонецЕсли;
Если задача заключается в том, чтобы выполнить действия с каждой найденной строкой, нет необходимости предварительно делать проверку через Если. Достаточно сразу запустить цикл обхода массива:
ПараметрыОтбора = Новый Структура("Товар", ТекТовар);
НайденныеСтроки = Товары.НайтиСтроки(ПараметрыОтбора);
Для Каждого ТекущаяСтрока Из НайденныеСтроки Цикл
// Работаем с конкретной найденной строкой
Сообщить("Найден товар: " + ТекущаяСтрока.Товар);
КонецЦикла;
Если массив пуст (ничего не найдено), цикл Для Каждого просто не выполнит ни одной итерации, и программа продолжит работу дальше без ошибок.
Также часто применяется компактная запись без создания промежуточных переменных:
Для Каждого ТекСтрока Из Товары.НайтиСтроки(Новый Структура("Товар", ТекТовар)) Цикл
// Действия с найденной строкой
КонецЦикла;
Разберем основные отличия двух главных методов поиска в коллекциях 1С:
Найти():
Ищет первое попавшееся совпадение в таблице. Возвращает непосредственно строку таблицы (тип СтрокаТаблицыЗначений или СтрокаТабличнойЧасти). Если значение не найдено, возвращает Неопределено.
// Пример использования метода Найти
НайденнаяСтрока = Товары.Найти(ТекТовар, "Товар");
Если НайденнаяСтрока <> Неопределено Тогда
Сообщить("Первая найденная строка: " + НайденнаяСтрока.Товар);
КонецЕсли;
НайтиСтроки():
Ищет все строки, удовлетворяющие условиям отбора. Возвращает Массив ссылок на найденные строки. Если ничего не найдено, возвращает пустой массив (количество элементов равно 0).
Проанализируем особенности и ограничения метода НайтиСтроки():
Если требуется выполнить поиск по сложному вычисляемому условию (например, найти строки, где длина наименования номенклатуры не превышает 68 символов), метод НайтиСтроки() использовать напрямую нельзя. В таких случаях применяют обход всех строк таблицы в цикле:
Для Каждого Стр Из Товары Цикл
Если СтрДлина(Стр.Товар.Наименование) <= 68 Тогда
// Обработка строки, удовлетворяющей условию
Сообщить("Подходит по длине: " + Стр.Товар);
КонецЕсли;
КонецЦикла;
Для сложной фильтрации больших объемов данных также рекомендуется использовать механизм Запросов с загрузкой таблицы значений во временную таблицу через МенеджерВременныхТаблиц.