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