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