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